mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-17 02:51:45 -05:00
Fix Intellisense not working for saved files (#867)
* Fix tools service to store the corrected file path * Use ClientFilePath for key * Further fixes * Undo spacing changes * Fix tests * Trigger CI rebuild
This commit is contained in:
@@ -41,7 +41,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
PublishDiagnosticsNotification.Type,
|
PublishDiagnosticsNotification.Type,
|
||||||
new PublishDiagnosticsNotification
|
new PublishDiagnosticsNotification
|
||||||
{
|
{
|
||||||
Uri = scriptFile.ClientFilePath,
|
Uri = scriptFile.ClientUri,
|
||||||
Diagnostics =
|
Diagnostics =
|
||||||
allMarkers
|
allMarkers
|
||||||
.Select(GetDiagnosticFromMarker)
|
.Select(GetDiagnosticFromMarker)
|
||||||
|
|||||||
@@ -452,7 +452,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
|
|
||||||
ConnectionInfo connInfo;
|
ConnectionInfo connInfo;
|
||||||
ConnectionServiceInstance.TryFindConnection(
|
ConnectionServiceInstance.TryFindConnection(
|
||||||
scriptFile.ClientFilePath,
|
scriptFile.ClientUri,
|
||||||
out connInfo);
|
out connInfo);
|
||||||
|
|
||||||
var completionItems = await GetCompletionItems(
|
var completionItems = await GetCompletionItems(
|
||||||
@@ -514,7 +514,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
DefinitionResult definitionResult = null;
|
DefinitionResult definitionResult = null;
|
||||||
if (scriptFile != null)
|
if (scriptFile != null)
|
||||||
{
|
{
|
||||||
isConnected = ConnectionServiceInstance.TryFindConnection(scriptFile.ClientFilePath, out connInfo);
|
isConnected = ConnectionServiceInstance.TryFindConnection(scriptFile.ClientUri, out connInfo);
|
||||||
definitionResult = GetDefinition(textDocumentPosition, scriptFile, connInfo);
|
definitionResult = GetDefinition(textDocumentPosition, scriptFile, connInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,7 +723,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
|
|
||||||
ConnectionInfo connInfo;
|
ConnectionInfo connInfo;
|
||||||
ConnectionServiceInstance.TryFindConnection(
|
ConnectionServiceInstance.TryFindConnection(
|
||||||
scriptFile.ClientFilePath,
|
scriptFile.ClientUri,
|
||||||
out connInfo);
|
out connInfo);
|
||||||
|
|
||||||
// check that there is an active connection for the current editor
|
// check that there is an active connection for the current editor
|
||||||
@@ -809,7 +809,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
|
|
||||||
foreach (var scriptFile in CurrentWorkspace.GetOpenedFiles())
|
foreach (var scriptFile in CurrentWorkspace.GetOpenedFiles())
|
||||||
{
|
{
|
||||||
await DiagnosticsHelper.ClearScriptDiagnostics(scriptFile.ClientFilePath, eventContext);
|
await DiagnosticsHelper.ClearScriptDiagnostics(scriptFile.ClientUri, eventContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// otherwise rerun diagnostic analysis on all opened SQL files
|
// otherwise rerun diagnostic analysis on all opened SQL files
|
||||||
@@ -898,7 +898,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
public ParseResult ParseAndBind(ScriptFile scriptFile, ConnectionInfo connInfo)
|
public ParseResult ParseAndBind(ScriptFile scriptFile, ConnectionInfo connInfo)
|
||||||
{
|
{
|
||||||
// get or create the current parse info object
|
// get or create the current parse info object
|
||||||
ScriptParseInfo parseInfo = GetScriptParseInfo(scriptFile.ClientFilePath, createIfNotExists: true);
|
ScriptParseInfo parseInfo = GetScriptParseInfo(scriptFile.ClientUri, createIfNotExists: true);
|
||||||
|
|
||||||
if (Monitor.TryEnter(parseInfo.BuildingMetadataLock, LanguageService.BindingTimeout))
|
if (Monitor.TryEnter(parseInfo.BuildingMetadataLock, LanguageService.BindingTimeout))
|
||||||
{
|
{
|
||||||
@@ -1130,7 +1130,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
|
|
||||||
private bool ShouldSkipNonMssqlFile(ScriptFile scriptFile)
|
private bool ShouldSkipNonMssqlFile(ScriptFile scriptFile)
|
||||||
{
|
{
|
||||||
return ShouldSkipNonMssqlFile(scriptFile.ClientFilePath);
|
return ShouldSkipNonMssqlFile(scriptFile.ClientUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1335,7 +1335,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
internal DefinitionResult GetDefinition(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile, ConnectionInfo connInfo)
|
internal DefinitionResult GetDefinition(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile, ConnectionInfo connInfo)
|
||||||
{
|
{
|
||||||
// Parse sql
|
// Parse sql
|
||||||
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri);
|
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(scriptFile.ClientUri);
|
||||||
if (scriptParseInfo == null)
|
if (scriptParseInfo == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -1450,7 +1450,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
textDocumentPosition.Position.Character);
|
textDocumentPosition.Position.Character);
|
||||||
int endColumn = textDocumentPosition.Position.Character;
|
int endColumn = textDocumentPosition.Position.Character;
|
||||||
|
|
||||||
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri);
|
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(scriptFile.ClientUri);
|
||||||
if (scriptParseInfo != null && scriptParseInfo.ParseResult != null)
|
if (scriptParseInfo != null && scriptParseInfo.ParseResult != null)
|
||||||
{
|
{
|
||||||
if (Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock))
|
if (Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock))
|
||||||
@@ -1499,7 +1499,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
int startLine = textDocumentPosition.Position.Line;
|
int startLine = textDocumentPosition.Position.Line;
|
||||||
int endColumn = textDocumentPosition.Position.Character;
|
int endColumn = textDocumentPosition.Position.Character;
|
||||||
|
|
||||||
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri);
|
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(scriptFile.ClientUri);
|
||||||
|
|
||||||
if (scriptParseInfo == null)
|
if (scriptParseInfo == null)
|
||||||
{
|
{
|
||||||
@@ -1509,7 +1509,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
|
|
||||||
ConnectionInfo connInfo;
|
ConnectionInfo connInfo;
|
||||||
ConnectionServiceInstance.TryFindConnection(
|
ConnectionServiceInstance.TryFindConnection(
|
||||||
scriptFile.ClientFilePath,
|
scriptFile.ClientUri,
|
||||||
out connInfo);
|
out connInfo);
|
||||||
|
|
||||||
// reparse and bind the SQL statement if needed
|
// reparse and bind the SQL statement if needed
|
||||||
@@ -1587,7 +1587,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
bool useLowerCaseSuggestions = this.CurrentWorkspaceSettings.SqlTools.IntelliSense.LowerCaseSuggestions.Value;
|
bool useLowerCaseSuggestions = this.CurrentWorkspaceSettings.SqlTools.IntelliSense.LowerCaseSuggestions.Value;
|
||||||
|
|
||||||
// get the current script parse info object
|
// get the current script parse info object
|
||||||
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri);
|
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(scriptFile.ClientUri);
|
||||||
|
|
||||||
if (scriptParseInfo == null)
|
if (scriptParseInfo == null)
|
||||||
{
|
{
|
||||||
@@ -1672,7 +1672,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
{
|
{
|
||||||
ConnectionInfo connInfo;
|
ConnectionInfo connInfo;
|
||||||
ConnectionServiceInstance.TryFindConnection(
|
ConnectionServiceInstance.TryFindConnection(
|
||||||
scriptFile.ClientFilePath,
|
scriptFile.ClientUri,
|
||||||
out connInfo);
|
out connInfo);
|
||||||
|
|
||||||
var parseResult = ParseAndBind(scriptFile, connInfo);
|
var parseResult = ParseAndBind(scriptFile, connInfo);
|
||||||
@@ -1797,10 +1797,10 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (ShouldSkipNonMssqlFile(scriptFile.ClientFilePath))
|
else if (ShouldSkipNonMssqlFile(scriptFile.ClientUri))
|
||||||
{
|
{
|
||||||
// Clear out any existing markers in case file type was changed
|
// Clear out any existing markers in case file type was changed
|
||||||
await DiagnosticsHelper.ClearScriptDiagnostics(scriptFile.ClientFilePath, eventContext);
|
await DiagnosticsHelper.ClearScriptDiagnostics(scriptFile.ClientUri, eventContext);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1884,9 +1884,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
/// <param name="scriptFile"></param>
|
/// <param name="scriptFile"></param>
|
||||||
internal bool IsPreviewWindow(ScriptFile scriptFile)
|
internal bool IsPreviewWindow(ScriptFile scriptFile)
|
||||||
{
|
{
|
||||||
if (scriptFile != null && !string.IsNullOrWhiteSpace(scriptFile.ClientFilePath))
|
if (scriptFile != null && !string.IsNullOrWhiteSpace(scriptFile.ClientUri))
|
||||||
{
|
{
|
||||||
return scriptFile.ClientFilePath.StartsWith("tsqloutput:");
|
return scriptFile.ClientUri.StartsWith("tsqloutput:");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -138,16 +138,23 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ResolvedFile TryGetFullPath(string filePath)
|
/// <summary>
|
||||||
|
/// Attempts to resolve the given filePath to an absolute path to a file on disk,
|
||||||
|
/// defaulting to the original filePath if that fails.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">The file path to resolve</param>
|
||||||
|
/// <param name="clientUri">The full file path URI used by the client</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
internal static ResolvedFile TryGetFullPath(string filePath, string clientUri)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new ResolvedFile(Path.GetFullPath(filePath), true);
|
return new ResolvedFile(Path.GetFullPath(filePath), clientUri, true);
|
||||||
}
|
}
|
||||||
catch(NotSupportedException)
|
catch(NotSupportedException)
|
||||||
{
|
{
|
||||||
// This is not a standard path.
|
// This is not a standard path.
|
||||||
return new ResolvedFile(filePath, false);
|
return new ResolvedFile(filePath, clientUri, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,20 +19,24 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class ResolvedFile
|
internal class ResolvedFile
|
||||||
{
|
{
|
||||||
public ResolvedFile(string filePath, bool canReadFromDisk)
|
public ResolvedFile(string filePath, string clientUri, bool canReadFromDisk)
|
||||||
{
|
{
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
|
ClientUri = clientUri;
|
||||||
CanReadFromDisk = canReadFromDisk;
|
CanReadFromDisk = canReadFromDisk;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string FilePath { get; private set; }
|
public string FilePath { get; private set; }
|
||||||
|
|
||||||
|
public string ClientUri { get; private set; }
|
||||||
|
|
||||||
public bool CanReadFromDisk { get; private set; }
|
public bool CanReadFromDisk { get; private set; }
|
||||||
|
|
||||||
public string LowercaseFilePath
|
public string LowercaseClientUri
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return FilePath?.ToLower();
|
return ClientUri?.ToLower();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a unique string that identifies this file. At this time,
|
/// Gets a unique string that identifies this file. At this time,
|
||||||
/// this property returns a normalized version of the value stored
|
/// this property returns a normalized version of the value stored
|
||||||
/// in the FilePath property.
|
/// in the ClientUri property.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Id
|
public string Id
|
||||||
{
|
{
|
||||||
get { return this.FilePath.ToLower(); }
|
get { return this.ClientUri.ToLower(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -34,11 +34,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
|||||||
public string FilePath { get; private set; }
|
public string FilePath { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the path which the editor client uses to identify this file.
|
/// Gets or sets the URI which the editor client uses to identify this file.
|
||||||
/// Setter for testing purposes only
|
/// Setter for testing purposes only
|
||||||
/// virtual to allow mocking.
|
/// virtual to allow mocking.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual string ClientFilePath { get; internal set; }
|
public virtual string ClientUri { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a boolean that determines whether
|
/// Gets or sets a boolean that determines whether
|
||||||
@@ -103,7 +103,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ScriptFile()
|
public ScriptFile()
|
||||||
{
|
{
|
||||||
ClientFilePath = "test.sql";
|
ClientUri = "test.sql";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -111,15 +111,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
|||||||
/// the given TextReader.
|
/// the given TextReader.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filePath">The path at which the script file resides.</param>
|
/// <param name="filePath">The path at which the script file resides.</param>
|
||||||
/// <param name="clientFilePath">The path which the client uses to identify the file.</param>
|
/// <param name="clientUri">The URI which the client uses to identify the file.</param>
|
||||||
/// <param name="textReader">The TextReader to use for reading the file's contents.</param>
|
/// <param name="textReader">The TextReader to use for reading the file's contents.</param>
|
||||||
public ScriptFile(
|
public ScriptFile(
|
||||||
string filePath,
|
string filePath,
|
||||||
string clientFilePath,
|
string clientUri,
|
||||||
TextReader textReader)
|
TextReader textReader)
|
||||||
{
|
{
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
ClientFilePath = clientFilePath;
|
ClientUri = clientUri;
|
||||||
IsAnalysisEnabled = true;
|
IsAnalysisEnabled = true;
|
||||||
IsInMemory = Workspace.IsPathInMemoryOrNonFileUri(filePath);
|
IsInMemory = Workspace.IsPathInMemoryOrNonFileUri(filePath);
|
||||||
|
|
||||||
@@ -130,15 +130,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
|||||||
/// Creates a new ScriptFile instance with the specified file contents.
|
/// Creates a new ScriptFile instance with the specified file contents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filePath">The path at which the script file resides.</param>
|
/// <param name="filePath">The path at which the script file resides.</param>
|
||||||
/// <param name="clientFilePath">The path which the client uses to identify the file.</param>
|
/// <param name="clientUri">The path which the client uses to identify the file.</param>
|
||||||
/// <param name="initialBuffer">The initial contents of the script file.</param>
|
/// <param name="initialBuffer">The initial contents of the script file.</param>
|
||||||
public ScriptFile(
|
public ScriptFile(
|
||||||
string filePath,
|
string filePath,
|
||||||
string clientFilePath,
|
string clientUri,
|
||||||
string initialBuffer)
|
string initialBuffer)
|
||||||
{
|
{
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
ClientFilePath = clientFilePath;
|
ClientUri = clientUri;
|
||||||
IsAnalysisEnabled = true;
|
IsAnalysisEnabled = true;
|
||||||
|
|
||||||
SetFileContents(initialBuffer);
|
SetFileContents(initialBuffer);
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
|||||||
|
|
||||||
// Resolve the full file path
|
// Resolve the full file path
|
||||||
ResolvedFile resolvedFile = this.ResolveFilePath(filePath);
|
ResolvedFile resolvedFile = this.ResolveFilePath(filePath);
|
||||||
string keyName = resolvedFile.LowercaseFilePath;
|
string keyName = resolvedFile.LowercaseClientUri;
|
||||||
|
|
||||||
ScriptFile scriptFile = null;
|
ScriptFile scriptFile = null;
|
||||||
return this.workspaceFiles.TryGetValue(keyName, out scriptFile);
|
return this.workspaceFiles.TryGetValue(keyName, out scriptFile);
|
||||||
@@ -98,7 +98,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
|||||||
|
|
||||||
// Resolve the full file path
|
// Resolve the full file path
|
||||||
ResolvedFile resolvedFile = this.ResolveFilePath(filePath);
|
ResolvedFile resolvedFile = this.ResolveFilePath(filePath);
|
||||||
string keyName = resolvedFile.LowercaseFilePath;
|
string keyName = resolvedFile.LowercaseClientUri;
|
||||||
|
|
||||||
// Make sure the file isn't already loaded into the workspace
|
// Make sure the file isn't already loaded into the workspace
|
||||||
ScriptFile scriptFile = null;
|
ScriptFile scriptFile = null;
|
||||||
@@ -117,7 +117,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
|||||||
using (FileStream fileStream = new FileStream(resolvedFile.FilePath, FileMode.Open, FileAccess.Read))
|
using (FileStream fileStream = new FileStream(resolvedFile.FilePath, FileMode.Open, FileAccess.Read))
|
||||||
using (StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8))
|
using (StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8))
|
||||||
{
|
{
|
||||||
scriptFile = new ScriptFile(resolvedFile.FilePath, filePath,streamReader);
|
scriptFile = new ScriptFile(resolvedFile.FilePath, resolvedFile.ClientUri,streamReader);
|
||||||
|
|
||||||
this.workspaceFiles.Add(keyName, scriptFile);
|
this.workspaceFiles.Add(keyName, scriptFile);
|
||||||
}
|
}
|
||||||
@@ -128,20 +128,26 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
|||||||
return scriptFile;
|
return scriptFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResolvedFile ResolveFilePath(string filePath)
|
/// <summary>
|
||||||
|
/// Resolves a URI identifier into an actual file on disk if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientUri">The URI identifying the file</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private ResolvedFile ResolveFilePath(string clientUri)
|
||||||
{
|
{
|
||||||
bool canReadFromDisk = false;
|
bool canReadFromDisk = false;
|
||||||
if (!IsPathInMemoryOrNonFileUri(filePath))
|
string filePath = clientUri;
|
||||||
|
if (!IsPathInMemoryOrNonFileUri(clientUri))
|
||||||
{
|
{
|
||||||
if (filePath.StartsWith(@"file://"))
|
if (clientUri.StartsWith(@"file://"))
|
||||||
{
|
{
|
||||||
// VS Code encodes the ':' character in the drive name, which can lead to problems parsing
|
// VS Code encodes the ':' character in the drive name, which can lead to problems parsing
|
||||||
// the URI, so unencode it if present. See https://github.com/Microsoft/vscode/issues/2990
|
// the URI, so unencode it if present. See https://github.com/Microsoft/vscode/issues/2990
|
||||||
filePath = filePath.Replace("%3A/", ":/", StringComparison.OrdinalIgnoreCase);
|
clientUri = clientUri.Replace("%3A/", ":/", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
// Client sent the path in URI format, extract the local path and trim
|
// Client sent the path in URI format, extract the local path and trim
|
||||||
// any extraneous slashes
|
// any extraneous slashes
|
||||||
Uri fileUri = new Uri(filePath);
|
Uri fileUri = new Uri(clientUri);
|
||||||
filePath = fileUri.LocalPath;
|
filePath = fileUri.LocalPath;
|
||||||
if (filePath.StartsWith("//") || filePath.StartsWith("\\\\") || filePath.StartsWith("/"))
|
if (filePath.StartsWith("//") || filePath.StartsWith("\\\\") || filePath.StartsWith("/"))
|
||||||
{
|
{
|
||||||
@@ -154,21 +160,36 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
|||||||
// into the SqlTools engine.
|
// into the SqlTools engine.
|
||||||
filePath = UnescapePath(filePath);
|
filePath = UnescapePath(filePath);
|
||||||
|
|
||||||
|
// Client paths are handled a bit differently because of how we currently identifiers in
|
||||||
|
// ADS. The URI is passed around as an identifier - but for things we control like connecting
|
||||||
|
// an editor the URI we pass in is NOT escaped fully. This is a problem for certain functionality
|
||||||
|
// which is handled by VS Code - such as Intellise Completion - as the URI passed in there is
|
||||||
|
// the fully escaped URI. That means we need to do some extra work to make sure that the URI values
|
||||||
|
// are consistent.
|
||||||
|
// So to solve that we'll make sure to unescape ALL uri's that are passed in and store that value for
|
||||||
|
// use as an identifier (filePath will be the actual file path on disk).
|
||||||
|
// # and ? are still always escaped though by ADS so we need to escape those again to get them to actually
|
||||||
|
// match
|
||||||
|
clientUri = Uri.UnescapeDataString(UnescapePath(clientUri));
|
||||||
|
clientUri = clientUri.Replace("#", "%23");
|
||||||
|
clientUri = clientUri.Replace("?", "%3F");
|
||||||
|
|
||||||
// switch to unix path separators on non-Windows platforms
|
// switch to unix path separators on non-Windows platforms
|
||||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
{
|
{
|
||||||
filePath = filePath.Replace('\\', '/');
|
filePath = filePath.Replace('\\', '/');
|
||||||
|
clientUri = clientUri.Replace('\\', '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the absolute file path
|
// Get the absolute file path
|
||||||
ResolvedFile resolvedFile = FileUtilities.TryGetFullPath(filePath);
|
ResolvedFile resolvedFile = FileUtilities.TryGetFullPath(filePath, clientUri);
|
||||||
filePath = resolvedFile.FilePath;
|
filePath = resolvedFile.FilePath;
|
||||||
canReadFromDisk = resolvedFile.CanReadFromDisk;
|
canReadFromDisk = resolvedFile.CanReadFromDisk;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Write(TraceEventType.Verbose, "Resolved path: " + filePath);
|
Logger.Write(TraceEventType.Verbose, "Resolved path: " + clientUri);
|
||||||
|
|
||||||
return new ResolvedFile(filePath, canReadFromDisk);
|
return new ResolvedFile(filePath, clientUri, canReadFromDisk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -204,13 +225,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
|||||||
|
|
||||||
// Resolve the full file path
|
// Resolve the full file path
|
||||||
ResolvedFile resolvedFile = this.ResolveFilePath(filePath);
|
ResolvedFile resolvedFile = this.ResolveFilePath(filePath);
|
||||||
string keyName = resolvedFile.LowercaseFilePath;
|
string keyName = resolvedFile.LowercaseClientUri;
|
||||||
|
|
||||||
// Make sure the file isn't already loaded into the workspace
|
// Make sure the file isn't already loaded into the workspace
|
||||||
ScriptFile scriptFile = null;
|
ScriptFile scriptFile = null;
|
||||||
if (!this.workspaceFiles.TryGetValue(keyName, out scriptFile))
|
if (!this.workspaceFiles.TryGetValue(keyName, out scriptFile))
|
||||||
{
|
{
|
||||||
scriptFile = new ScriptFile(resolvedFile.FilePath, filePath, initialBuffer);
|
scriptFile = new ScriptFile(resolvedFile.FilePath, resolvedFile.ClientUri, initialBuffer);
|
||||||
|
|
||||||
this.workspaceFiles.Add(keyName, scriptFile);
|
this.workspaceFiles.Add(keyName, scriptFile);
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.Utility
|
|||||||
{
|
{
|
||||||
ownerUri = GetTestSqlFile();
|
ownerUri = GetTestSqlFile();
|
||||||
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri);
|
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri);
|
||||||
ownerUri = scriptFile.ClientFilePath;
|
ownerUri = scriptFile.ClientUri;
|
||||||
}
|
}
|
||||||
var connectionService = GetLiveTestConnectionService();
|
var connectionService = GetLiveTestConnectionService();
|
||||||
var connectionResult =
|
var connectionResult =
|
||||||
@@ -68,7 +68,7 @@ namespace Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.Utility
|
|||||||
{
|
{
|
||||||
ownerUri = GetTestSqlFile();
|
ownerUri = GetTestSqlFile();
|
||||||
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri);
|
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri);
|
||||||
ownerUri = scriptFile.ClientFilePath;
|
ownerUri = scriptFile.ClientUri;
|
||||||
}
|
}
|
||||||
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
|
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
|
||||||
|
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
|
|||||||
{
|
{
|
||||||
TextDocument = new TextDocumentIdentifier
|
TextDocument = new TextDocumentIdentifier
|
||||||
{
|
{
|
||||||
Uri = result.ScriptFile.ClientFilePath
|
Uri = result.ScriptFile.ClientUri
|
||||||
},
|
},
|
||||||
Position = new Position
|
Position = new Position
|
||||||
{
|
{
|
||||||
@@ -246,7 +246,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
|
|||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
|
|
||||||
// We should get back a non-null ScriptParseInfo
|
// We should get back a non-null ScriptParseInfo
|
||||||
ScriptParseInfo parseInfo = service.GetScriptParseInfo(result.ScriptFile.ClientFilePath);
|
ScriptParseInfo parseInfo = service.GetScriptParseInfo(result.ScriptFile.ClientUri);
|
||||||
Assert.NotNull(parseInfo);
|
Assert.NotNull(parseInfo);
|
||||||
|
|
||||||
// And we should get back a non-null SignatureHelp
|
// And we should get back a non-null SignatureHelp
|
||||||
@@ -298,7 +298,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
|
|||||||
{
|
{
|
||||||
TextDocument = new TextDocumentIdentifier
|
TextDocument = new TextDocumentIdentifier
|
||||||
{
|
{
|
||||||
Uri = connectionInfoResult.ScriptFile.ClientFilePath
|
Uri = connectionInfoResult.ScriptFile.ClientUri
|
||||||
},
|
},
|
||||||
Position = new Position
|
Position = new Position
|
||||||
{
|
{
|
||||||
@@ -318,7 +318,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
|
|||||||
|
|
||||||
// And refresh the cache
|
// And refresh the cache
|
||||||
await langService.HandleRebuildIntelliSenseNotification(
|
await langService.HandleRebuildIntelliSenseNotification(
|
||||||
new RebuildIntelliSenseParams() { OwnerUri = connectionInfoResult.ScriptFile.ClientFilePath },
|
new RebuildIntelliSenseParams() { OwnerUri = connectionInfoResult.ScriptFile.ClientUri },
|
||||||
new TestEventContext());
|
new TestEventContext());
|
||||||
|
|
||||||
// Now we should expect to see the item show up in the completion list
|
// Now we should expect to see the item show up in the completion list
|
||||||
@@ -342,24 +342,24 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
|
|||||||
public async Task HandleRequestToChangeToSqlcmdFile()
|
public async Task HandleRequestToChangeToSqlcmdFile()
|
||||||
{
|
{
|
||||||
|
|
||||||
var scriptFile = new ScriptFile() { ClientFilePath = "HandleRequestToChangeToSqlcmdFile_" + DateTime.Now.ToLongDateString() + "_.sql" };
|
var scriptFile = new ScriptFile() { ClientUri = "HandleRequestToChangeToSqlcmdFile_" + DateTime.Now.ToLongDateString() + "_.sql" };
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Prepare a script file
|
// Prepare a script file
|
||||||
scriptFile.SetFileContents("koko wants a bananas");
|
scriptFile.SetFileContents("koko wants a bananas");
|
||||||
File.WriteAllText(scriptFile.ClientFilePath, scriptFile.Contents);
|
File.WriteAllText(scriptFile.ClientUri, scriptFile.Contents);
|
||||||
|
|
||||||
// Create a workspace and add file to it so that its found for intellense building
|
// Create a workspace and add file to it so that its found for intellense building
|
||||||
var workspace = new ServiceLayer.Workspace.Workspace();
|
var workspace = new ServiceLayer.Workspace.Workspace();
|
||||||
var workspaceService = new WorkspaceService<SqlToolsSettings> { Workspace = workspace };
|
var workspaceService = new WorkspaceService<SqlToolsSettings> { Workspace = workspace };
|
||||||
var langService = new LanguageService() { WorkspaceServiceInstance = workspaceService };
|
var langService = new LanguageService() { WorkspaceServiceInstance = workspaceService };
|
||||||
langService.CurrentWorkspace.GetFile(scriptFile.ClientFilePath);
|
langService.CurrentWorkspace.GetFile(scriptFile.ClientUri);
|
||||||
langService.CurrentWorkspaceSettings.SqlTools.IntelliSense.EnableIntellisense = true;
|
langService.CurrentWorkspaceSettings.SqlTools.IntelliSense.EnableIntellisense = true;
|
||||||
|
|
||||||
// Add a connection to ensure the intellisense building works
|
// Add a connection to ensure the intellisense building works
|
||||||
ConnectionInfo connectionInfo = GetLiveAutoCompleteTestObjects().ConnectionInfo;
|
ConnectionInfo connectionInfo = GetLiveAutoCompleteTestObjects().ConnectionInfo;
|
||||||
langService.ConnectionServiceInstance.OwnerToConnectionMap.Add(scriptFile.ClientFilePath, connectionInfo);
|
langService.ConnectionServiceInstance.OwnerToConnectionMap.Add(scriptFile.ClientUri, connectionInfo);
|
||||||
|
|
||||||
// Test SQL
|
// Test SQL
|
||||||
int countOfValidationCalls = 0;
|
int countOfValidationCalls = 0;
|
||||||
@@ -367,7 +367,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
|
|||||||
eventContextSql.Setup(x => x.SendEvent(PublishDiagnosticsNotification.Type, It.Is<PublishDiagnosticsNotification>((notif) => ValidateNotification(notif, 2, ref countOfValidationCalls)))).Returns(Task.FromResult(new object()));
|
eventContextSql.Setup(x => x.SendEvent(PublishDiagnosticsNotification.Type, It.Is<PublishDiagnosticsNotification>((notif) => ValidateNotification(notif, 2, ref countOfValidationCalls)))).Returns(Task.FromResult(new object()));
|
||||||
await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams
|
await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams
|
||||||
{
|
{
|
||||||
Uri = scriptFile.ClientFilePath,
|
Uri = scriptFile.ClientUri,
|
||||||
Language = LanguageService.SQL_LANG.ToLower(),
|
Language = LanguageService.SQL_LANG.ToLower(),
|
||||||
Flavor = "MSSQL"
|
Flavor = "MSSQL"
|
||||||
}, eventContextSql.Object);
|
}, eventContextSql.Object);
|
||||||
@@ -378,7 +378,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
|
|||||||
eventContextSqlCmd.Setup(x => x.SendEvent(PublishDiagnosticsNotification.Type, It.Is<PublishDiagnosticsNotification>((notif) => ValidateNotification(notif, 0, ref countOfValidationCalls)))).Returns(Task.FromResult(new object()));
|
eventContextSqlCmd.Setup(x => x.SendEvent(PublishDiagnosticsNotification.Type, It.Is<PublishDiagnosticsNotification>((notif) => ValidateNotification(notif, 0, ref countOfValidationCalls)))).Returns(Task.FromResult(new object()));
|
||||||
await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams
|
await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams
|
||||||
{
|
{
|
||||||
Uri = scriptFile.ClientFilePath,
|
Uri = scriptFile.ClientUri,
|
||||||
Language = LanguageService.SQL_CMD_LANG.ToLower(),
|
Language = LanguageService.SQL_CMD_LANG.ToLower(),
|
||||||
Flavor = "MSSQL"
|
Flavor = "MSSQL"
|
||||||
}, eventContextSqlCmd.Object);
|
}, eventContextSqlCmd.Object);
|
||||||
@@ -388,9 +388,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (File.Exists(scriptFile.ClientFilePath))
|
if (File.Exists(scriptFile.ClientUri))
|
||||||
{
|
{
|
||||||
File.Delete(scriptFile.ClientFilePath);
|
File.Delete(scriptFile.ClientUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,11 @@ GO";
|
|||||||
.Callback<string, Func<IBindingContext, CancellationToken, object>, Func<IBindingContext, object>, Func<Exception, object>, int?, int?>(
|
.Callback<string, Func<IBindingContext, CancellationToken, object>, Func<IBindingContext, object>, Func<Exception, object>, int?, int?>(
|
||||||
(key, bindOperation, timeoutOperation, errHandler, t1, t2) =>
|
(key, bindOperation, timeoutOperation, errHandler, t1, t2) =>
|
||||||
{
|
{
|
||||||
timeoutResult = (DefinitionResult)timeoutOperation((IBindingContext)null);
|
if(timeoutOperation != null)
|
||||||
|
{
|
||||||
|
timeoutResult = (DefinitionResult)timeoutOperation(null);
|
||||||
|
}
|
||||||
|
|
||||||
itemMock.Object.Result = timeoutResult;
|
itemMock.Object.Result = timeoutResult;
|
||||||
})
|
})
|
||||||
.Returns(() => itemMock.Object);
|
.Returns(() => itemMock.Object);
|
||||||
@@ -251,14 +255,14 @@ GO";
|
|||||||
};
|
};
|
||||||
LiveConnectionHelper.TestConnectionResult connectionResult = LiveConnectionHelper.InitLiveConnectionInfo();
|
LiveConnectionHelper.TestConnectionResult connectionResult = LiveConnectionHelper.InitLiveConnectionInfo();
|
||||||
ScriptFile scriptFile = connectionResult.ScriptFile;
|
ScriptFile scriptFile = connectionResult.ScriptFile;
|
||||||
ConnectionInfo connInfo = connectionResult.ConnectionInfo;
|
|
||||||
scriptFile.Contents = "select * from dbo.func ()";
|
scriptFile.Contents = "select * from dbo.func ()";
|
||||||
|
|
||||||
ScriptParseInfo scriptInfo = new ScriptParseInfo { IsConnected = true };
|
ScriptParseInfo scriptInfo = new ScriptParseInfo { IsConnected = true };
|
||||||
languageService.ScriptParseInfoMap.Add(OwnerUri, scriptInfo);
|
languageService.ScriptParseInfoMap.Add(scriptFile.ClientUri, scriptInfo);
|
||||||
|
|
||||||
// When I call the language service
|
// Pass in null connection info to force doing a local parse since that hits the BindingQueue timeout
|
||||||
var result = languageService.GetDefinition(textDocument, scriptFile, connInfo);
|
// before we want it to (this is testing the timeout trying to fetch the definitions after the parse)
|
||||||
|
var result = languageService.GetDefinition(textDocument, scriptFile, null);
|
||||||
|
|
||||||
// Then I expect null locations and an error to be reported
|
// Then I expect null locations and an error to be reported
|
||||||
Assert.NotNull(result);
|
Assert.NotNull(result);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility
|
|||||||
{
|
{
|
||||||
ownerUri = GetTestSqlFile();
|
ownerUri = GetTestSqlFile();
|
||||||
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri);
|
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri);
|
||||||
ownerUri = scriptFile.ClientFilePath;
|
ownerUri = scriptFile.ClientUri;
|
||||||
}
|
}
|
||||||
var connectionService = GetLiveTestConnectionService();
|
var connectionService = GetLiveTestConnectionService();
|
||||||
var connectionResult =
|
var connectionResult =
|
||||||
@@ -70,7 +70,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility
|
|||||||
{
|
{
|
||||||
ownerUri = GetTestSqlFile();
|
ownerUri = GetTestSqlFile();
|
||||||
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri);
|
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri);
|
||||||
ownerUri = scriptFile.ClientFilePath;
|
ownerUri = scriptFile.ClientUri;
|
||||||
}
|
}
|
||||||
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
|
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
|
||||||
|
|
||||||
|
|||||||
@@ -3,23 +3,16 @@
|
|||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
//
|
//
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Binder;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
|
|
||||||
using Microsoft.SqlServer.Management.SqlParser.Parser;
|
using Microsoft.SqlServer.Management.SqlParser.Parser;
|
||||||
using Microsoft.SqlTools.Hosting.Protocol;
|
using Microsoft.SqlTools.Hosting.Protocol;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
|
||||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
|
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
|
||||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
|
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
|
||||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
|
||||||
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
|
|
||||||
using Microsoft.SqlTools.ServiceLayer.Workspace;
|
|
||||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||||
using GlobalCommon = Microsoft.SqlTools.ServiceLayer.Test.Common;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||||
|
using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.LanguageServer
|
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.LanguageServer
|
||||||
{
|
{
|
||||||
@@ -91,11 +84,24 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.LanguageServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetDefinitionInvalidTextDocument()
|
public async void HandleDefinitionRequest_InvalidTextDocument_SendsEmptyListResponse()
|
||||||
{
|
{
|
||||||
InitializeTestObjects();
|
InitializeTestObjects();
|
||||||
textDocument.TextDocument.Uri = "invaliduri";
|
textDocument.TextDocument.Uri = "invaliduri";
|
||||||
Assert.Null(langService.GetDefinition(textDocument, null, null));
|
|
||||||
|
// setup the mock for SendResult
|
||||||
|
var definitionRequestContext = new Mock<RequestContext<Location[]>>();
|
||||||
|
Location[] result = null;
|
||||||
|
definitionRequestContext.Setup(rc => rc.SendResult(It.IsAny<Location[]>()))
|
||||||
|
.Returns<Location[]>((resultDetails) => {
|
||||||
|
result = resultDetails;
|
||||||
|
return Task.FromResult(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
await langService.HandleDefinitionRequest(textDocument, definitionRequestContext.Object);
|
||||||
|
// Should get an empty array when passed
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.True(result.Length == 0, $"Unexpected values passed to SendResult : [{ string.Join(",", (object[])result)}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -113,11 +119,21 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.LanguageServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetCompletionItemsInvalidTextDocument()
|
public async void HandleCompletionRequest_InvalidTextDocument_SendsNullResult()
|
||||||
{
|
{
|
||||||
InitializeTestObjects();
|
InitializeTestObjects();
|
||||||
|
// setup the mock for SendResult to capture the items
|
||||||
|
CompletionItem[] completionItems = null;
|
||||||
|
requestContext.Setup(x => x.SendResult(It.IsAny<CompletionItem[]>()))
|
||||||
|
.Returns<CompletionItem[]>((resultDetails) => {
|
||||||
|
completionItems = resultDetails;
|
||||||
|
return Task.FromResult(0);
|
||||||
|
});
|
||||||
|
|
||||||
textDocument.TextDocument.Uri = "somethinggoeshere";
|
textDocument.TextDocument.Uri = "somethinggoeshere";
|
||||||
Assert.True(langService.GetCompletionItems(textDocument, scriptFile.Object, null).Result.Length > 0);
|
await langService.HandleCompletionRequest(textDocument, requestContext.Object);
|
||||||
|
requestContext.Verify(m => m.SendResult(It.IsAny<CompletionItem[]>()), Times.Once());
|
||||||
|
Assert.Null(completionItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -69,12 +69,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.LanguageServer
|
|||||||
// set up file for returning the query
|
// set up file for returning the query
|
||||||
scriptFile = new Mock<ScriptFile>();
|
scriptFile = new Mock<ScriptFile>();
|
||||||
scriptFile.SetupGet(file => file.Contents).Returns(GlobalCommon.Constants.StandardQuery);
|
scriptFile.SetupGet(file => file.Contents).Returns(GlobalCommon.Constants.StandardQuery);
|
||||||
scriptFile.SetupGet(file => file.ClientFilePath).Returns(this.testScriptUri);
|
scriptFile.SetupGet(file => file.ClientUri).Returns(this.testScriptUri);
|
||||||
|
|
||||||
// set up workspace mock
|
// set up workspace mock
|
||||||
workspaceService = new Mock<WorkspaceService<SqlToolsSettings>>();
|
workspaceService = new Mock<WorkspaceService<SqlToolsSettings>>();
|
||||||
workspaceService.Setup(service => service.Workspace.GetFile(It.IsAny<string>()))
|
workspaceService.Setup(service => service.Workspace.GetFile(It.IsAny<string>()))
|
||||||
.Returns(scriptFile.Object);
|
.Returns((string filePath) => { return filePath == this.testScriptUri ? scriptFile.Object : null; });
|
||||||
|
|
||||||
// setup binding queue mock
|
// setup binding queue mock
|
||||||
bindingQueue = new Mock<ConnectedBindingQueue>();
|
bindingQueue = new Mock<ConnectedBindingQueue>();
|
||||||
|
|||||||
Reference in New Issue
Block a user