mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Initial implementation for autocomplete.
This commit is contained in:
63
src/ServiceHost/Connection/ConnectionMessages.cs
Normal file
63
src/ServiceHost/Connection/ConnectionMessages.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
|
||||
|
||||
namespace Microsoft.SqlTools.EditorServices.Connection
|
||||
{
|
||||
/// <summary>
|
||||
/// Message format for the initial connection request
|
||||
/// </summary>
|
||||
public class ConnectionDetails
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the connection server name
|
||||
/// </summary>
|
||||
public string ServerName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the connection database name
|
||||
/// </summary>
|
||||
public string DatabaseName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the connection user name
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the connection password
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string Password { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Message format for the connection result response
|
||||
/// </summary>
|
||||
public class ConnectionResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the connection id
|
||||
/// </summary>
|
||||
public int ConnectionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets any connection error messages
|
||||
/// </summary>
|
||||
public string Messages { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connect request mapping entry
|
||||
/// </summary>
|
||||
public class ConnectionRequest
|
||||
{
|
||||
public static readonly
|
||||
RequestType<ConnectionDetails, ConnectionResult> Type =
|
||||
RequestType<ConnectionDetails, ConnectionResult>.Create("connection/connect");
|
||||
}
|
||||
|
||||
}
|
||||
160
src/ServiceHost/Connection/ConnectionService.cs
Normal file
160
src/ServiceHost/Connection/ConnectionService.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
//
|
||||
// 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.SqlClient;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.SqlTools.EditorServices.Connection
|
||||
{
|
||||
/// <summary>
|
||||
/// Main class for the Connection Management services
|
||||
/// </summary>
|
||||
public class ConnectionService
|
||||
{
|
||||
/// <summary>
|
||||
/// Singleton service instance
|
||||
/// </summary>
|
||||
private static Lazy<ConnectionService> instance
|
||||
= new Lazy<ConnectionService>(() => new ConnectionService());
|
||||
|
||||
/// <summary>
|
||||
/// The SQL connection factory object
|
||||
/// </summary>
|
||||
private ISqlConnectionFactory connectionFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The current connection id that was previously used
|
||||
/// </summary>
|
||||
private int maxConnectionId = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Active connections lazy dictionary instance
|
||||
/// </summary>
|
||||
private Lazy<Dictionary<int, ISqlConnection>> activeConnections
|
||||
= new Lazy<Dictionary<int, ISqlConnection>>(()
|
||||
=> new Dictionary<int, ISqlConnection>());
|
||||
|
||||
/// <summary>
|
||||
/// Callback for onconnection handler
|
||||
/// </summary>
|
||||
/// <param name="sqlConnection"></param>
|
||||
public delegate Task OnConnectionHandler(ISqlConnection sqlConnection);
|
||||
|
||||
/// <summary>
|
||||
/// List of onconnection handlers
|
||||
/// </summary>
|
||||
private readonly List<OnConnectionHandler> onConnectionActivities = new List<OnConnectionHandler>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the active connection map
|
||||
/// </summary>
|
||||
public Dictionary<int, ISqlConnection> ActiveConnections
|
||||
{
|
||||
get
|
||||
{
|
||||
return activeConnections.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the singleton service instance
|
||||
/// </summary>
|
||||
public static ConnectionService Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return instance.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the SQL connection factory instance
|
||||
/// </summary>
|
||||
public ISqlConnectionFactory ConnectionFactory
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.connectionFactory == null)
|
||||
{
|
||||
this.connectionFactory = new SqlConnectionFactory();
|
||||
}
|
||||
return this.connectionFactory;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor is private since it's a singleton class
|
||||
/// </summary>
|
||||
private ConnectionService()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test constructor that injects dependency interfaces
|
||||
/// </summary>
|
||||
/// <param name="testFactory"></param>
|
||||
public ConnectionService(ISqlConnectionFactory testFactory)
|
||||
{
|
||||
this.connectionFactory = testFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open a connection with the specified connection details
|
||||
/// </summary>
|
||||
/// <param name="connectionDetails"></param>
|
||||
public ConnectionResult Connect(ConnectionDetails connectionDetails)
|
||||
{
|
||||
// build the connection string from the input parameters
|
||||
string connectionString = BuildConnectionString(connectionDetails);
|
||||
|
||||
// create a sql connection instance
|
||||
ISqlConnection connection = this.ConnectionFactory.CreateSqlConnection();
|
||||
|
||||
// open the database
|
||||
connection.OpenDatabaseConnection(connectionString);
|
||||
|
||||
// map the connection id to the connection object for future lookups
|
||||
this.ActiveConnections.Add(++maxConnectionId, connection);
|
||||
|
||||
// invoke callback notifications
|
||||
foreach (var activity in this.onConnectionActivities)
|
||||
{
|
||||
activity(connection);
|
||||
}
|
||||
|
||||
// return the connection result
|
||||
return new ConnectionResult()
|
||||
{
|
||||
ConnectionId = maxConnectionId
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new method to be called when the onconnection request is submitted
|
||||
/// </summary>
|
||||
/// <param name="activity"></param>
|
||||
public void RegisterOnConnectionTask(OnConnectionHandler activity)
|
||||
{
|
||||
onConnectionActivities.Add(activity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build a connection string from a connection details instance
|
||||
/// </summary>
|
||||
/// <param name="connectionDetails"></param>
|
||||
private string BuildConnectionString(ConnectionDetails connectionDetails)
|
||||
{
|
||||
SqlConnectionStringBuilder connectionBuilder = new SqlConnectionStringBuilder();
|
||||
connectionBuilder["Data Source"] = connectionDetails.ServerName;
|
||||
connectionBuilder["Integrated Security"] = false;
|
||||
connectionBuilder["User Id"] = connectionDetails.UserName;
|
||||
connectionBuilder["Password"] = connectionDetails.Password;
|
||||
connectionBuilder["Initial Catalog"] = connectionDetails.DatabaseName;
|
||||
return connectionBuilder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/ServiceHost/Connection/ISqlConnection.cs
Normal file
34
src/ServiceHost/Connection/ISqlConnection.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.SqlTools.EditorServices.Connection
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for the SQL Connection factory
|
||||
/// </summary>
|
||||
public interface ISqlConnectionFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a new SQL Connection object
|
||||
/// </summary>
|
||||
ISqlConnection CreateSqlConnection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for the SQL Connection wrapper
|
||||
/// </summary>
|
||||
public interface ISqlConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// Open a connection to the provided connection string
|
||||
/// </summary>
|
||||
/// <param name="connectionString"></param>
|
||||
void OpenDatabaseConnection(string connectionString);
|
||||
|
||||
IEnumerable<string> GetServerObjects();
|
||||
}
|
||||
}
|
||||
70
src/ServiceHost/Connection/SqlConnection.cs
Normal file
70
src/ServiceHost/Connection/SqlConnection.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace Microsoft.SqlTools.EditorServices.Connection
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory class to create SqlClientConnections
|
||||
/// The purpose of the factory is to make it easier to mock out the database
|
||||
/// in 'offline' unit test scenarios.
|
||||
/// </summary>
|
||||
public class SqlConnectionFactory : ISqlConnectionFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new SqlClientConnection object
|
||||
/// </summary>
|
||||
public ISqlConnection CreateSqlConnection()
|
||||
{
|
||||
return new SqlClientConnection();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper class that implements ISqlConnection and hosts a SqlConnection.
|
||||
/// This wrapper exists primarily for decoupling to support unit testing.
|
||||
/// </summary>
|
||||
public class SqlClientConnection : ISqlConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// the underlying SQL connection
|
||||
/// </summary>
|
||||
private SqlConnection connection;
|
||||
|
||||
/// <summary>
|
||||
/// Opens a SqlConnection using provided connection string
|
||||
/// </summary>
|
||||
/// <param name="connectionString"></param>
|
||||
public void OpenDatabaseConnection(string connectionString)
|
||||
{
|
||||
this.connection = new SqlConnection(connectionString);
|
||||
this.connection.Open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of database server schema objects
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<string> GetServerObjects()
|
||||
{
|
||||
SqlCommand command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT name FROM sys.objects";
|
||||
command.CommandTimeout = 15;
|
||||
command.CommandType = CommandType.Text;
|
||||
var reader = command.ExecuteReader();
|
||||
|
||||
List<string> results = new List<string>();
|
||||
while (reader.Read())
|
||||
{
|
||||
results.Add(reader[0].ToString());
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/ServiceHost/LanguageSupport/AutoCompleteService.cs
Normal file
49
src/ServiceHost/LanguageSupport/AutoCompleteService.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.SqlTools.EditorServices.Connection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.SqlTools.LanguageSupport
|
||||
{
|
||||
/// <summary>
|
||||
/// Main class for Autocomplete functionality
|
||||
/// </summary>
|
||||
public class AutoCompleteService
|
||||
{
|
||||
/// <summary>
|
||||
/// Singleton service instance
|
||||
/// </summary>
|
||||
private static Lazy<AutoCompleteService> instance
|
||||
= new Lazy<AutoCompleteService>(() => new AutoCompleteService());
|
||||
|
||||
private IEnumerable<string> autoCompleteList;
|
||||
|
||||
public IEnumerable<string> AutoCompleteList
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.autoCompleteList;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the singleton service instance
|
||||
/// </summary>
|
||||
public static AutoCompleteService Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return instance.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateAutoCompleteCache(ISqlConnection connection)
|
||||
{
|
||||
this.autoCompleteList = connection.GetServerObjects();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,8 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using Microsoft.SqlTools.EditorServices.Connection;
|
||||
using Microsoft.SqlTools.LanguageSupport;
|
||||
|
||||
namespace Microsoft.SqlTools.EditorServices.Protocol.Server
|
||||
{
|
||||
@@ -57,7 +59,22 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.Server
|
||||
this.SetRequestHandler(DocumentHighlightRequest.Type, this.HandleDocumentHighlightRequest);
|
||||
this.SetRequestHandler(HoverRequest.Type, this.HandleHoverRequest);
|
||||
this.SetRequestHandler(DocumentSymbolRequest.Type, this.HandleDocumentSymbolRequest);
|
||||
this.SetRequestHandler(WorkspaceSymbolRequest.Type, this.HandleWorkspaceSymbolRequest);
|
||||
this.SetRequestHandler(WorkspaceSymbolRequest.Type, this.HandleWorkspaceSymbolRequest);
|
||||
|
||||
this.SetRequestHandler(ConnectionRequest.Type, this.HandleConnectRequest);
|
||||
|
||||
// register an OnConnection callback
|
||||
ConnectionService.Instance.RegisterOnConnectionTask(OnConnection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback for when a user connection is done processing
|
||||
/// </summary>
|
||||
/// <param name="sqlConnection"></param>
|
||||
public Task OnConnection(ISqlConnection sqlConnection)
|
||||
{
|
||||
AutoCompleteService.Instance.UpdateAutoCompleteCache(sqlConnection);
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -245,7 +262,57 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.Server
|
||||
RequestContext<CompletionItem[]> requestContext)
|
||||
{
|
||||
Logger.Write(LogLevel.Verbose, "HandleCompletionRequest");
|
||||
await Task.FromResult(true);
|
||||
|
||||
var connectionService = ConnectionService.Instance;
|
||||
if (connectionService.ActiveConnections.Count > 0)
|
||||
{
|
||||
AutoCompleteService.Instance.UpdateAutoCompleteCache(
|
||||
connectionService.ActiveConnections.First().Value);
|
||||
}
|
||||
|
||||
var autoCompleteList = AutoCompleteService.Instance.AutoCompleteList;
|
||||
var completions = new List<CompletionItem>();
|
||||
|
||||
int i = 0;
|
||||
if (autoCompleteList != null)
|
||||
{
|
||||
foreach (var autoCompleteItem in autoCompleteList)
|
||||
{
|
||||
completions.Add(new CompletionItem()
|
||||
{
|
||||
Label = autoCompleteItem,
|
||||
Kind = CompletionItemKind.Keyword,
|
||||
Detail = autoCompleteItem + " details",
|
||||
Documentation = autoCompleteItem + " documentation",
|
||||
//SortText = "SortText",
|
||||
TextEdit = new TextEdit
|
||||
{
|
||||
NewText = "New Text",
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await requestContext.SendResult(completions.ToArray());
|
||||
}
|
||||
|
||||
protected async Task HandleCompletionResolveRequest(
|
||||
@@ -296,6 +363,24 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.Server
|
||||
await Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle new connection requests
|
||||
/// </summary>
|
||||
/// <param name="connectionDetails"></param>
|
||||
/// <param name="requestContext"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task HandleConnectRequest(
|
||||
ConnectionDetails connectionDetails,
|
||||
RequestContext<ConnectionResult> requestContext)
|
||||
{
|
||||
Logger.Write(LogLevel.Verbose, "HandleConnectRequest");
|
||||
|
||||
// open connection base on request details
|
||||
ConnectionResult result = ConnectionService.Instance.Connect(connectionDetails);
|
||||
|
||||
await requestContext.SendResult(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs script diagnostics on changed files
|
||||
/// </summary>
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "9.0.1",
|
||||
"Microsoft.SqlServer.SqlParser": "140.1.3"
|
||||
"Microsoft.SqlServer.SqlParser": "140.1.3",
|
||||
"System.Data.Common": "4.1.0",
|
||||
"System.Data.SqlClient": "4.1.0"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
|
||||
63
test/ServiceHost.Test/Connection/ConnectionServiceTests.cs
Normal file
63
test/ServiceHost.Test/Connection/ConnectionServiceTests.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
#define USE_LIVE_CONNECTION
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.Test.Utility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.Test.Connection
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for the ServiceHost Connection Service tests
|
||||
/// </summary>
|
||||
public class ConnectionServiceTests
|
||||
{
|
||||
#region "Connection tests"
|
||||
|
||||
/// <summary>
|
||||
/// Verify that the SQL parser correctly detects errors in text
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ConnectToDatabaseTest()
|
||||
{
|
||||
// connect to a database instance
|
||||
var connectionResult =
|
||||
TestObjects.GetTestConnectionService()
|
||||
.Connect(TestObjects.GetTestConnectionDetails());
|
||||
|
||||
// verify that a valid connection id was returned
|
||||
Assert.True(connectionResult.ConnectionId > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that the SQL parser correctly detects errors in text
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void OnConnectionCallbackHandlerTest()
|
||||
{
|
||||
bool callbackInvoked = false;
|
||||
|
||||
// setup connection service with callback
|
||||
var connectionService = TestObjects.GetTestConnectionService();
|
||||
connectionService.RegisterOnConnectionTask(
|
||||
(sqlConnection) => {
|
||||
callbackInvoked = true;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
);
|
||||
|
||||
// connect to a database instance
|
||||
var connectionResult = TestObjects.GetTestConnectionService()
|
||||
.Connect(TestObjects.GetTestConnectionDetails());
|
||||
|
||||
// verify that a valid connection id was returned
|
||||
Assert.True(callbackInvoked);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@
|
||||
using Microsoft.SqlTools.EditorServices;
|
||||
using Microsoft.SqlTools.EditorServices.Session;
|
||||
using Microsoft.SqlTools.LanguageSupport;
|
||||
using Microsoft.SqlTools.Test.Connection;
|
||||
using Microsoft.SqlTools.Test.Utility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.Test.LanguageServer
|
||||
@@ -15,15 +17,6 @@ namespace Microsoft.SqlTools.Test.LanguageServer
|
||||
/// </summary>
|
||||
public class LanguageServiceTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a test language service instance
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private LanguageService CreateTestService()
|
||||
{
|
||||
return new LanguageService(new SqlToolsContext(null, null));
|
||||
}
|
||||
|
||||
#region "Diagnostics tests"
|
||||
|
||||
/// <summary>
|
||||
@@ -36,7 +29,7 @@ namespace Microsoft.SqlTools.Test.LanguageServer
|
||||
const string sqlWithErrors = "SELECT * FROM sys.objects";
|
||||
|
||||
// get the test service
|
||||
LanguageService service = CreateTestService();
|
||||
LanguageService service = TestObjects.GetTestLanguageService();
|
||||
|
||||
// parse the sql statement
|
||||
var scriptFile = new ScriptFile();
|
||||
@@ -57,7 +50,7 @@ namespace Microsoft.SqlTools.Test.LanguageServer
|
||||
const string sqlWithErrors = "SELECT *** FROM sys.objects";
|
||||
|
||||
// get test service
|
||||
LanguageService service = CreateTestService();
|
||||
LanguageService service = TestObjects.GetTestLanguageService();
|
||||
|
||||
// parse sql statement
|
||||
var scriptFile = new ScriptFile();
|
||||
@@ -87,7 +80,7 @@ namespace Microsoft.SqlTools.Test.LanguageServer
|
||||
"SELECT *** FROM sys.objects;\n";
|
||||
|
||||
// get test service
|
||||
LanguageService service = CreateTestService();
|
||||
LanguageService service = TestObjects.GetTestLanguageService();
|
||||
|
||||
// parse sql
|
||||
var scriptFile = new ScriptFile();
|
||||
@@ -111,6 +104,23 @@ namespace Microsoft.SqlTools.Test.LanguageServer
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region "Autocomplete Tests"
|
||||
|
||||
/// <summary>
|
||||
/// Verify that the SQL parser correctly detects errors in text
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AutocompleteTest()
|
||||
{
|
||||
var autocompleteService = TestObjects.GetAutoCompleteService();
|
||||
var connectionService = TestObjects.GetTestConnectionService();
|
||||
var connectionResult = connectionService.Connect(TestObjects.GetTestConnectionDetails());
|
||||
var sqlConnection = connectionService.ActiveConnections[connectionResult.ConnectionId];
|
||||
autocompleteService.UpdateAutoCompleteCache(sqlConnection);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
//
|
||||
|
||||
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.SqlTools.EditorServices.Test.Protocol.MessageProtocol
|
||||
|
||||
108
test/ServiceHost.Test/Utility/TestObjects.cs
Normal file
108
test/ServiceHost.Test/Utility/TestObjects.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
//#define USE_LIVE_CONNECTION
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.EditorServices.Connection;
|
||||
using Microsoft.SqlTools.EditorServices.Session;
|
||||
using Microsoft.SqlTools.LanguageSupport;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.Test.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for the ServiceHost Connection Service tests
|
||||
/// </summary>
|
||||
public class TestObjects
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a test connection service
|
||||
/// </summary>
|
||||
public static ConnectionService GetTestConnectionService()
|
||||
{
|
||||
#if !USE_LIVE_CONNECTION
|
||||
// use mock database connection
|
||||
return new ConnectionService(new TestSqlConnectionFactory());
|
||||
#else
|
||||
// connect to a real server instance
|
||||
return ConnectionService.Instance;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a test connection details object
|
||||
/// </summary>
|
||||
public static ConnectionDetails GetTestConnectionDetails()
|
||||
{
|
||||
return new ConnectionDetails()
|
||||
{
|
||||
UserName = "sa",
|
||||
Password = "Yukon900",
|
||||
DatabaseName = "AdventureWorks2016CTP3_2",
|
||||
ServerName = "sqltools11"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a test language service instance
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static LanguageService GetTestLanguageService()
|
||||
{
|
||||
return new LanguageService(new SqlToolsContext(null, null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a test autocomplete service instance
|
||||
/// </summary>
|
||||
public static AutoCompleteService GetAutoCompleteService()
|
||||
{
|
||||
return AutoCompleteService.Instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a test sql connection factory instance
|
||||
/// </summary>
|
||||
public static ISqlConnectionFactory GetTestSqlConnectionFactory()
|
||||
{
|
||||
#if !USE_LIVE_CONNECTION
|
||||
// use mock database connection
|
||||
return new TestSqlConnectionFactory();
|
||||
#else
|
||||
// connect to a real server instance
|
||||
return ConnectionService.Instance.ConnectionFactory;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test mock class for SqlConnection wrapper
|
||||
/// </summary>
|
||||
public class TestSqlConnection : ISqlConnection
|
||||
{
|
||||
public void OpenDatabaseConnection(string connectionString)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetServerObjects()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test mock class for SqlConnection factory
|
||||
/// </summary>
|
||||
public class TestSqlConnectionFactory : ISqlConnectionFactory
|
||||
{
|
||||
public ISqlConnection CreateSqlConnection()
|
||||
{
|
||||
return new TestSqlConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,13 @@
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "9.0.1",
|
||||
"System.Runtime.Serialization.Primitives": "4.1.1",
|
||||
"System.Data.Common": "4.1.0",
|
||||
"System.Data.SqlClient": "4.1.0",
|
||||
"xunit": "2.1.0",
|
||||
"dotnet-test-xunit": "1.0.0-rc2-192208-24",
|
||||
"ServiceHost": {
|
||||
"target": "project"
|
||||
}
|
||||
"ServiceHost": {
|
||||
"target": "project"
|
||||
}
|
||||
},
|
||||
"testRunner": "xunit",
|
||||
"frameworks": {
|
||||
|
||||
Reference in New Issue
Block a user