* Misc. clean-ups related to removing unneeded PowerShell Language Service code.
* Remove unneeded files and clean up remaining code.
* Enable file change tracking with Workspace and EditorSession.
This commit is contained in:
Karl Burtram
2016-07-16 01:20:56 -07:00
committed by GitHub
parent c78292a680
commit ea3d015961
61 changed files with 275 additions and 3777 deletions

View File

@@ -10,13 +10,15 @@
"args": [],
"cwd": "${workspaceRoot}",
"externalConsole": true,
"requireExactSource": false,
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": 16900
"requireExactSource": false,
"processId": 17264
}
]
}

View File

@@ -1,48 +0,0 @@
//
// 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.DebugAdapter;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.Client
{
public class DebugAdapterClient : ProtocolEndpoint
{
public DebugAdapterClient(ChannelBase clientChannel)
: base(clientChannel, MessageProtocolType.DebugAdapter)
{
}
public async Task LaunchScript(string scriptFilePath)
{
await this.SendRequest(
LaunchRequest.Type,
new LaunchRequestArguments {
Program = scriptFilePath
});
await this.SendRequest(ConfigurationDoneRequest.Type, null);
}
protected override Task OnStart()
{
return Task.FromResult(true);
}
protected override Task OnConnect()
{
// Initialize the debug adapter
return this.SendRequest(
InitializeRequest.Type,
new InitializeRequestArguments
{
LinesStartAt1 = true
});
}
}
}

View File

@@ -1,44 +0,0 @@
//
// 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.LanguageServer;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.Client
{
/// <summary>
/// Provides a base implementation for language server clients.
/// </summary>
public abstract class LanguageClientBase : ProtocolEndpoint
{
/// <summary>
/// Initializes an instance of the language client using the
/// specified channel for communication.
/// </summary>
/// <param name="clientChannel">The channel to use for communication with the server.</param>
public LanguageClientBase(ChannelBase clientChannel)
: base(clientChannel, MessageProtocolType.LanguageServer)
{
}
protected override Task OnStart()
{
// Initialize the implementation class
return this.Initialize();
}
protected override async Task OnStop()
{
// First, notify the language server that we're stopping
var response = await this.SendRequest(ShutdownRequest.Type, new object());
await this.SendEvent(ExitNotification.Type, new object());
}
protected abstract Task Initialize();
}
}

View File

@@ -1,121 +0,0 @@
//
// 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.LanguageServer;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.Client
{
public class LanguageServiceClient : LanguageClientBase
{
private Dictionary<string, ScriptFileMarker[]> cachedDiagnostics =
new Dictionary<string, ScriptFileMarker[]>();
public LanguageServiceClient(ChannelBase clientChannel)
: base(clientChannel)
{
}
protected override Task Initialize()
{
// Add handlers for common events
this.SetEventHandler(PublishDiagnosticsNotification.Type, HandlePublishDiagnosticsEvent);
return Task.FromResult(true);
}
protected override Task OnConnect()
{
// Send the 'initialize' request and wait for the response
var initializeRequest = new InitializeRequest
{
RootPath = "",
Capabilities = new ClientCapabilities()
};
return this.SendRequest(
InitializeRequest.Type,
initializeRequest);
}
#region Events
public event EventHandler<string> DiagnosticsReceived;
protected void OnDiagnosticsReceived(string filePath)
{
if (this.DiagnosticsReceived != null)
{
this.DiagnosticsReceived(this, filePath);
}
}
#endregion
#region Private Methods
private Task HandlePublishDiagnosticsEvent(
PublishDiagnosticsNotification diagnostics,
EventContext eventContext)
{
string normalizedPath = diagnostics.Uri.ToLower();
this.cachedDiagnostics[normalizedPath] =
diagnostics.Diagnostics
.Select(GetMarkerFromDiagnostic)
.ToArray();
this.OnDiagnosticsReceived(normalizedPath);
return Task.FromResult(true);
}
private static ScriptFileMarker GetMarkerFromDiagnostic(Diagnostic diagnostic)
{
DiagnosticSeverity severity =
diagnostic.Severity.GetValueOrDefault(
DiagnosticSeverity.Error);
return new ScriptFileMarker
{
Level = MapDiagnosticSeverityToLevel(severity),
Message = diagnostic.Message,
ScriptRegion = new ScriptRegion
{
StartLineNumber = diagnostic.Range.Start.Line + 1,
StartColumnNumber = diagnostic.Range.Start.Character + 1,
EndLineNumber = diagnostic.Range.End.Line + 1,
EndColumnNumber = diagnostic.Range.End.Character + 1
}
};
}
private static ScriptFileMarkerLevel MapDiagnosticSeverityToLevel(DiagnosticSeverity severity)
{
switch (severity)
{
case DiagnosticSeverity.Hint:
case DiagnosticSeverity.Information:
return ScriptFileMarkerLevel.Information;
case DiagnosticSeverity.Warning:
return ScriptFileMarkerLevel.Warning;
case DiagnosticSeverity.Error:
return ScriptFileMarkerLevel.Error;
default:
return ScriptFileMarkerLevel.Error;
}
}
#endregion
}
}

View File

@@ -1,23 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class AttachRequest
{
public static readonly
RequestType<AttachRequestArguments, object> Type =
RequestType<AttachRequestArguments, object>.Create("attach");
}
public class AttachRequestArguments
{
public string Address { get; set; }
public int Port { get; set; }
}
}

View File

@@ -1,81 +0,0 @@
//
// 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.Utility;
namespace Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter
{
public class Breakpoint
{
/// <summary>
/// Gets an boolean indicator that if true, breakpoint could be set
/// (but not necessarily at the desired location).
/// </summary>
public bool Verified { get; set; }
/// <summary>
/// Gets an optional message about the state of the breakpoint. This is shown to the user
/// and can be used to explain why a breakpoint could not be verified.
/// </summary>
public string Message { get; set; }
public string Source { get; set; }
public int? Line { get; set; }
public int? Column { get; set; }
private Breakpoint()
{
}
#if false
public static Breakpoint Create(
BreakpointDetails breakpointDetails)
{
//Validate.IsNotNull(nameof(breakpointDetails), breakpointDetails);
return new Breakpoint
{
Verified = breakpointDetails.Verified,
Message = breakpointDetails.Message,
Source = breakpointDetails.Source,
Line = breakpointDetails.LineNumber,
Column = breakpointDetails.ColumnNumber
};
}
public static Breakpoint Create(
CommandBreakpointDetails breakpointDetails)
{
//Validate.IsNotNull(nameof(breakpointDetails), breakpointDetails);
return new Breakpoint {
Verified = breakpointDetails.Verified,
Message = breakpointDetails.Message
};
}
#endif
public static Breakpoint Create(
SourceBreakpoint sourceBreakpoint,
string source,
string message,
bool verified = false)
{
Validate.IsNotNull(nameof(sourceBreakpoint), sourceBreakpoint);
Validate.IsNotNull(nameof(source), source);
Validate.IsNotNull(nameof(message), message);
return new Breakpoint {
Verified = verified,
Message = message,
Source = source,
Line = sourceBreakpoint.Line,
Column = sourceBreakpoint.Column
};
}
}
}

View File

@@ -1,16 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class ConfigurationDoneRequest
{
public static readonly
RequestType<object, object> Type =
RequestType<object, object>.Create("configurationDone");
}
}

View File

@@ -1,17 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class ContinueRequest
{
public static readonly
RequestType<object, object> Type =
RequestType<object, object>.Create("continue");
}
}

View File

@@ -1,17 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class DisconnectRequest
{
public static readonly
RequestType<object, object> Type =
RequestType<object, object>.Create("disconnect");
}
}

View File

@@ -1,53 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class EvaluateRequest
{
public static readonly
RequestType<EvaluateRequestArguments, EvaluateResponseBody> Type =
RequestType<EvaluateRequestArguments, EvaluateResponseBody>.Create("evaluate");
}
public class EvaluateRequestArguments
{
/// <summary>
/// The expression to evaluate.
/// </summary>
public string Expression { get; set; }
/// <summary>
/// The context in which the evaluate request is run. Possible
/// values are 'watch' if evaluate is run in a watch or 'repl'
/// if run from the REPL console.
/// </summary>
public string Context { get; set; }
/// <summary>
/// Evaluate the expression in the context of this stack frame.
/// If not specified, the top most frame is used.
/// </summary>
public int FrameId { get; set; }
}
public class EvaluateResponseBody
{
/// <summary>
/// The evaluation result.
/// </summary>
public string Result { get; set; }
/// <summary>
/// If variablesReference is > 0, the evaluate result is
/// structured and its children can be retrieved by passing
/// variablesReference to the VariablesRequest
/// </summary>
public int VariablesReference { get; set; }
}
}

View File

@@ -1,22 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class ExitedEvent
{
public static readonly
EventType<ExitedEventBody> Type =
EventType<ExitedEventBody>.Create("exited");
}
public class ExitedEventBody
{
public int ExitCode { get; set; }
}
}

View File

@@ -1,56 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class InitializeRequest
{
public static readonly
RequestType<InitializeRequestArguments, InitializeResponseBody> Type =
RequestType<InitializeRequestArguments, InitializeResponseBody>.Create("initialize");
}
public class InitializeRequestArguments
{
public string AdapterId { get; set; }
public bool LinesStartAt1 { get; set; }
public string PathFormat { get; set; }
public bool SourceMaps { get; set; }
public string GeneratedCodeDirectory { get; set; }
}
public class InitializeResponseBody
{
/// <summary>
/// Gets or sets a boolean value that determines whether the debug adapter
/// supports the configurationDoneRequest.
/// </summary>
public bool SupportsConfigurationDoneRequest { get; set; }
/// <summary>
/// Gets or sets a boolean value that determines whether the debug adapter
/// supports functionBreakpoints.
/// </summary>
public bool SupportsFunctionBreakpoints { get; set; }
/// <summary>
/// Gets or sets a boolean value that determines whether the debug adapter
/// supports conditionalBreakpoints.
/// </summary>
public bool SupportsConditionalBreakpoints { get; set; }
/// <summary>
/// Gets or sets a boolean value that determines whether the debug adapter
/// supports a (side effect free) evaluate request for data hovers.
/// </summary>
public bool SupportsEvaluateForHovers { get; set; }
}
}

View File

@@ -1,16 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class InitializedEvent
{
public static readonly
EventType<object> Type =
EventType<object>.Create("initialized");
}
}

View File

@@ -1,66 +0,0 @@
//
// 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 Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
namespace Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter
{
public class LaunchRequest
{
public static readonly
RequestType<LaunchRequestArguments, object> Type =
RequestType<LaunchRequestArguments, object>.Create("launch");
}
public class LaunchRequestArguments
{
/// <summary>
/// Gets or sets the absolute path to the program to debug.
/// </summary>
public string Program { get; set; }
/// <summary>
/// Gets or sets a boolean value that indicates whether the script should be
/// run with (false) or without (true) debugging support.
/// </summary>
public bool NoDebug { get; set; }
/// <summary>
/// Gets or sets a boolean value that determines whether to automatically stop
/// target after launch. If not specified, target does not stop.
/// </summary>
public bool StopOnEntry { get; set; }
/// <summary>
/// Gets or sets optional arguments passed to the debuggee.
/// </summary>
public string[] Args { get; set; }
/// <summary>
/// Gets or sets the working directory of the launched debuggee (specified as an absolute path).
/// If omitted the debuggee is lauched in its own directory.
/// </summary>
public string Cwd { get; set; }
/// <summary>
/// Gets or sets the absolute path to the runtime executable to be used.
/// Default is the runtime executable on the PATH.
/// </summary>
public string RuntimeExecutable { get; set; }
/// <summary>
/// Gets or sets the optional arguments passed to the runtime executable.
/// </summary>
public string[] RuntimeArgs { get; set; }
/// <summary>
/// Gets or sets optional environment variables to pass to the debuggee. The string valued
/// properties of the 'environmentVariables' are used as key/value pairs.
/// </summary>
public Dictionary<string, string> Env { get; set; }
}
}

View File

@@ -1,20 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
// /** StepOver request; value of command field is "next".
// he request starts the debuggee to run again for one step.
// penDebug will respond with a StoppedEvent (event type 'step') after running the step.
public class NextRequest
{
public static readonly
RequestType<object, object> Type =
RequestType<object, object>.Create("next");
}
}

View File

@@ -1,24 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class OutputEvent
{
public static readonly
EventType<OutputEventBody> Type =
EventType<OutputEventBody>.Create("output");
}
public class OutputEventBody
{
public string Category { get; set; }
public string Output { get; set; }
}
}

View File

@@ -1,17 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class PauseRequest
{
public static readonly
RequestType<object, object> Type =
RequestType<object, object>.Create("pause");
}
}

View File

@@ -1,40 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
namespace Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter
{
public class Scope
{
/// <summary>
/// Gets or sets the name of the scope (as such 'Arguments', 'Locals')
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the variables of this scope can be retrieved by passing the
/// value of variablesReference to the VariablesRequest.
/// </summary>
public int VariablesReference { get; set; }
/// <summary>
/// Gets or sets a boolean value indicating if number of variables in
/// this scope is large or expensive to retrieve.
/// </summary>
public bool Expensive { get; set; }
#if false
public static Scope Create(VariableScope scope)
{
return new Scope {
Name = scope.Name,
VariablesReference = scope.Id,
// Temporary fix for #95 to get debug hover tips to work well at least for the local scope.
Expensive = (scope.Name != VariableContainerDetails.LocalScopeName)
};
}
#endif
}
}

View File

@@ -1,29 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Diagnostics;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
namespace Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter
{
public class ScopesRequest
{
public static readonly
RequestType<ScopesRequestArguments, ScopesResponseBody> Type =
RequestType<ScopesRequestArguments, ScopesResponseBody>.Create("scopes");
}
[DebuggerDisplay("FrameId = {FrameId}")]
public class ScopesRequestArguments
{
public int FrameId { get; set; }
}
public class ScopesResponseBody
{
public Scope[] Scopes { get; set; }
}
}

View File

@@ -1,43 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
/// <summary>
/// SetBreakpoints request; value of command field is "setBreakpoints".
/// Sets multiple breakpoints for a single source and clears all previous breakpoints in that source.
/// To clear all breakpoint for a source, specify an empty array.
/// When a breakpoint is hit, a StoppedEvent (event type 'breakpoint') is generated.
/// </summary>
public class SetBreakpointsRequest
{
public static readonly
RequestType<SetBreakpointsRequestArguments, SetBreakpointsResponseBody> Type =
RequestType<SetBreakpointsRequestArguments, SetBreakpointsResponseBody>.Create("setBreakpoints");
}
public class SetBreakpointsRequestArguments
{
public Source Source { get; set; }
public SourceBreakpoint[] Breakpoints { get; set; }
}
public class SourceBreakpoint
{
public int Line { get; set; }
public int? Column { get; set; }
public string Condition { get; set; }
}
public class SetBreakpointsResponseBody
{
public Breakpoint[] Breakpoints { get; set; }
}
}

View File

@@ -1,31 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
/// <summary>
/// SetExceptionBreakpoints request; value of command field is "setExceptionBreakpoints".
/// Enable that the debuggee stops on exceptions with a StoppedEvent (event type 'exception').
/// </summary>
public class SetExceptionBreakpointsRequest
{
public static readonly
RequestType<SetExceptionBreakpointsRequestArguments, object> Type =
RequestType<SetExceptionBreakpointsRequestArguments, object>.Create("setExceptionBreakpoints");
}
/// <summary>
/// Arguments for "setExceptionBreakpoints" request.
/// </summary>
public class SetExceptionBreakpointsRequestArguments
{
/// <summary>
/// Gets or sets the names of enabled exception breakpoints.
/// </summary>
public string[] Filters { get; set; }
}
}

View File

@@ -1,31 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class SetFunctionBreakpointsRequest
{
public static readonly
RequestType<SetFunctionBreakpointsRequestArguments, SetBreakpointsResponseBody> Type =
RequestType<SetFunctionBreakpointsRequestArguments, SetBreakpointsResponseBody>.Create("setFunctionBreakpoints");
}
public class SetFunctionBreakpointsRequestArguments
{
public FunctionBreakpoint[] Breakpoints { get; set; }
}
public class FunctionBreakpoint
{
/// <summary>
/// Gets or sets the name of the function to break on when it is invoked.
/// </summary>
public string Name { get; set; }
public string Condition { get; set; }
}
}

View File

@@ -1,17 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
namespace Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter
{
public class Source
{
public string Name { get; set; }
public string Path { get; set; }
public int? SourceReference { get; set; }
}
}

View File

@@ -1,29 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class SourceRequest
{
public static readonly
RequestType<SourceRequestArguments, SourceResponseBody> Type =
RequestType<SourceRequestArguments, SourceResponseBody>.Create("source");
}
public class SourceRequestArguments
{
/// <summary>
/// Gets or sets the reference to the source. This is the value received in Source.reference.
/// </summary>
public int SourceReference { get; set; }
}
public class SourceResponseBody
{
public string Content { get; set; }
}
}

View File

@@ -1,53 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
namespace Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter
{
public class StackFrame
{
public int Id { get; set; }
public string Name { get; set; }
public Source Source { get; set; }
public int Line { get; set; }
public int Column { get; set; }
// /** An identifier for the stack frame. */
//id: number;
///** The name of the stack frame, typically a method name */
//name: string;
///** The source of the frame. */
//source: Source;
///** The line within the file of the frame. */
//line: number;
///** The column within the line. */
//column: number;
///** All arguments and variables declared in this stackframe. */
//scopes: Scope[];
#if false
public static StackFrame Create(
StackFrameDetails stackFrame,
int id)
{
return new StackFrame
{
Id = id,
Name = stackFrame.FunctionName,
Line = stackFrame.LineNumber,
Column = stackFrame.ColumnNumber,
Source = new Source
{
Path = stackFrame.ScriptPath
}
};
}
#endif
}
}

View File

@@ -1,33 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Diagnostics;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
namespace Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter
{
public class StackTraceRequest
{
public static readonly
RequestType<StackTraceRequestArguments, StackTraceResponseBody> Type =
RequestType<StackTraceRequestArguments, StackTraceResponseBody>.Create("stackTrace");
}
[DebuggerDisplay("ThreadId = {ThreadId}, Levels = {Levels}")]
public class StackTraceRequestArguments
{
public int ThreadId { get; private set; }
/// <summary>
/// Gets the maximum number of frames to return. If levels is not specified or 0, all frames are returned.
/// </summary>
public int Levels { get; private set; }
}
public class StackTraceResponseBody
{
public StackFrame[] StackFrames { get; set; }
}
}

View File

@@ -1,16 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class StartedEvent
{
public static readonly
EventType<object> Type =
EventType<object>.Create("started");
}
}

View File

@@ -1,17 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class StepInRequest
{
public static readonly
RequestType<object, object> Type =
RequestType<object, object>.Create("stepIn");
}
}

View File

@@ -1,16 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class StepOutRequest
{
public static readonly
RequestType<object, object> Type =
RequestType<object, object>.Create("stepOut");
}
}

View File

@@ -1,41 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class StoppedEvent
{
public static readonly
EventType<StoppedEventBody> Type =
EventType<StoppedEventBody>.Create("stopped");
}
public class StoppedEventBody
{
/// <summary>
/// A value such as "step", "breakpoint", "exception", or "pause"
/// </summary>
public string Reason { get; set; }
/// <summary>
/// Gets or sets the current thread ID, if any.
/// </summary>
public int? ThreadId { get; set; }
public Source Source { get; set; }
public int Line { get; set; }
public int Column { get; set; }
/// <summary>
/// Gets or sets additional information such as an error message.
/// </summary>
public string Text { get; set; }
}
}

View File

@@ -1,17 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class TerminatedEvent
{
public static readonly
EventType<object> Type =
EventType<object>.Create("terminated");
}
}

View File

@@ -1,15 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
namespace Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter
{
public class Thread
{
public int Id { get; set; }
public string Name { get; set; }
}
}

View File

@@ -1,22 +0,0 @@
//
// 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.Protocol.DebugAdapter
{
public class ThreadsRequest
{
public static readonly
RequestType<object, ThreadsResponseBody> Type =
RequestType<object, ThreadsResponseBody>.Create("threads");
}
public class ThreadsResponseBody
{
public Thread[] Threads { get; set; }
}
}

View File

@@ -1,33 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
namespace Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter
{
public class Variable
{
public string Name { get; set; }
// /** The variable's value. For structured objects this can be a multi line text, e.g. for a function the body of a function. */
public string Value { get; set; }
// /** If variablesReference is > 0, the variable is structured and its children can be retrieved by passing variablesReference to the VariablesRequest. */
public int VariablesReference { get; set; }
#if false
public static Variable Create(VariableDetailsBase variable)
{
return new Variable
{
Name = variable.Name,
Value = variable.ValueString ?? string.Empty,
VariablesReference =
variable.IsExpandable ?
variable.Id : 0
};
}
#endif
}
}

View File

@@ -1,29 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Diagnostics;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
namespace Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter
{
public class VariablesRequest
{
public static readonly
RequestType<VariablesRequestArguments, VariablesResponseBody> Type =
RequestType<VariablesRequestArguments, VariablesResponseBody>.Create("variables");
}
[DebuggerDisplay("VariablesReference = {VariablesReference}")]
public class VariablesRequestArguments
{
public int VariablesReference { get; set; }
}
public class VariablesResponseBody
{
public Variable[] Variables { get; set; }
}
}

View File

@@ -3,11 +3,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer
{

View File

@@ -83,4 +83,3 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer
public object Data { get; set; }
}
}

View File

@@ -4,11 +4,6 @@
//
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer
{

View File

@@ -1,111 +0,0 @@
//
// 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.Protocol.LanguageServer
{
public class ExtensionCommandAddedNotification
{
public static readonly
EventType<ExtensionCommandAddedNotification> Type =
EventType<ExtensionCommandAddedNotification>.Create("SqlTools/extensionCommandAdded");
public string Name { get; set; }
public string DisplayName { get; set; }
}
public class ExtensionCommandUpdatedNotification
{
public static readonly
EventType<ExtensionCommandUpdatedNotification> Type =
EventType<ExtensionCommandUpdatedNotification>.Create("SqlTools/extensionCommandUpdated");
public string Name { get; set; }
}
public class ExtensionCommandRemovedNotification
{
public static readonly
EventType<ExtensionCommandRemovedNotification> Type =
EventType<ExtensionCommandRemovedNotification>.Create("SqlTools/extensionCommandRemoved");
public string Name { get; set; }
}
public class ClientEditorContext
{
public string CurrentFilePath { get; set; }
public Position CursorPosition { get; set; }
public Range SelectionRange { get; set; }
}
public class InvokeExtensionCommandRequest
{
public static readonly
RequestType<InvokeExtensionCommandRequest, string> Type =
RequestType<InvokeExtensionCommandRequest, string>.Create("SqlTools/invokeExtensionCommand");
public string Name { get; set; }
public ClientEditorContext Context { get; set; }
}
public class GetEditorContextRequest
{
public static readonly
RequestType<GetEditorContextRequest, ClientEditorContext> Type =
RequestType<GetEditorContextRequest, ClientEditorContext>.Create("editor/getEditorContext");
}
public enum EditorCommandResponse
{
Unsupported,
OK
}
public class InsertTextRequest
{
public static readonly
RequestType<InsertTextRequest, EditorCommandResponse> Type =
RequestType<InsertTextRequest, EditorCommandResponse>.Create("editor/insertText");
public string FilePath { get; set; }
public string InsertText { get; set; }
public Range InsertRange { get; set; }
}
public class SetSelectionRequest
{
public static readonly
RequestType<SetSelectionRequest, EditorCommandResponse> Type =
RequestType<SetSelectionRequest, EditorCommandResponse>.Create("editor/setSelection");
public Range SelectionRange { get; set; }
}
public class SetCursorPositionRequest
{
public static readonly
RequestType<SetCursorPositionRequest, EditorCommandResponse> Type =
RequestType<SetCursorPositionRequest, EditorCommandResponse>.Create("editor/setCursorPosition");
public Position CursorPosition { get; set; }
}
public class OpenFileRequest
{
public static readonly
RequestType<string, EditorCommandResponse> Type =
RequestType<string, EditorCommandResponse>.Create("editor/openFile");
}
}

View File

@@ -4,11 +4,6 @@
//
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer
{

View File

@@ -61,12 +61,27 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer
public class DidChangeTextDocumentParams : TextDocumentIdentifier
{
public TextDocumentUriChangeEvent TextDocument { get; set; }
/// <summary>
/// Gets or sets the list of changes to the document content.
/// </summary>
public TextDocumentChangeEvent[] ContentChanges { get; set; }
}
public class TextDocumentUriChangeEvent
{
/// <summary>
/// Gets or sets the Uri of the changed text document
/// </summary>
public string Uri { get; set; }
/// <summary>
/// Gets or sets the Version of the changed text document
/// </summary>
public int Version { get; set; }
}
public class TextDocumentChangeEvent
{
/// <summary>

View File

@@ -1,83 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#if false
using System;
using System.IO.Pipes;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel
{
public class NamedPipeClientChannel : ChannelBase
{
private string pipeName;
private bool isClientConnected;
private NamedPipeClientStream pipeClient;
public NamedPipeClientChannel(string pipeName)
{
this.pipeName = pipeName;
}
public override async Task WaitForConnection()
{
#if NanoServer
await this.pipeClient.ConnectAsync();
#else
this.IsConnected = false;
while (!this.IsConnected)
{
try
{
// Wait for 500 milliseconds so that we don't tie up the thread
this.pipeClient.Connect(500);
this.IsConnected = this.pipeClient.IsConnected;
}
catch (TimeoutException)
{
// Connect timed out, wait and try again
await Task.Delay(1000);
continue;
}
}
#endif
// If we've reached this point, we're connected
this.IsConnected = true;
}
protected override void Initialize(IMessageSerializer messageSerializer)
{
this.pipeClient =
new NamedPipeClientStream(
".",
this.pipeName,
PipeDirection.InOut,
PipeOptions.Asynchronous);
this.MessageReader =
new MessageReader(
this.pipeClient,
messageSerializer);
this.MessageWriter =
new MessageWriter(
this.pipeClient,
messageSerializer);
}
protected override void Shutdown()
{
if (this.pipeClient != null)
{
this.pipeClient.Dispose();
}
}
}
}
#endif

View File

@@ -1,65 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#if false
using System;
using System.IO.Pipes;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel
{
public class NamedPipeServerChannel : ChannelBase
{
private string pipeName;
private NamedPipeServerStream pipeServer;
public NamedPipeServerChannel(string pipeName)
{
this.pipeName = pipeName;
}
public override async Task WaitForConnection()
{
#if NanoServer
await this.pipeServer.WaitForConnectionAsync();
#else
await Task.Factory.FromAsync(this.pipeServer.BeginWaitForConnection, this.pipeServer.EndWaitForConnection, null);
#endif
this.IsConnected = true;
}
protected override void Initialize(IMessageSerializer messageSerializer)
{
this.pipeServer =
new NamedPipeServerStream(
pipeName,
PipeDirection.InOut,
1,
PipeTransmissionMode.Byte,
PipeOptions.Asynchronous);
this.MessageReader =
new MessageReader(
this.pipeServer,
messageSerializer);
this.MessageWriter =
new MessageWriter(
this.pipeServer,
messageSerializer);
}
protected override void Shutdown()
{
if (this.pipeServer != null)
{
this.pipeServer.Dispose();
}
}
}
}
#endif

View File

@@ -3,11 +3,9 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Serializers;
using System.Diagnostics;
using System.IO;
using System.Text;
using System;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel

View File

@@ -3,10 +3,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Serializers;
using System.IO;
using System.Text;
using System;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel

View File

@@ -18,7 +18,7 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol
#region Fields
private ChannelBase protocolChannel;
// private AsyncQueue<Message> messagesToWrite;
private AsyncContextThread messageLoopThread;
private Dictionary<string, Func<Message, MessageWriter, Task>> requestHandlers =

View File

@@ -3,10 +3,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Serializers
{

View File

@@ -3,8 +3,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;

View File

@@ -1,58 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#if false
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
namespace Microsoft.SqlTools.EditorServices.Protocol.Messages
{
public class ShowChoicePromptRequest
{
public static readonly
RequestType<ShowChoicePromptRequest, ShowChoicePromptResponse> Type =
RequestType<ShowChoicePromptRequest, ShowChoicePromptResponse>.Create("SqlTools/showChoicePrompt");
public string Caption { get; set; }
public string Message { get; set; }
public ChoiceDetails[] Choices { get; set; }
public int DefaultChoice { get; set; }
}
public class ShowChoicePromptResponse
{
public bool PromptCancelled { get; set; }
public string ChosenItem { get; set; }
}
public class ShowInputPromptRequest
{
public static readonly
RequestType<ShowInputPromptRequest, ShowInputPromptResponse> Type =
RequestType<ShowInputPromptRequest, ShowInputPromptResponse>.Create("SqlTools/showInputPrompt");
/// <summary>
/// Gets or sets the name of the field.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the descriptive label for the field.
/// </summary>
public string Label { get; set; }
}
public class ShowInputPromptResponse
{
public bool PromptCancelled { get; set; }
public string ResponseText { get; set; }
}
}
#endif

View File

@@ -15,7 +15,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("SqlTools Editor Services")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyCopyright("<EFBFBD> Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -37,8 +37,8 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.0.0.0")]
[assembly: AssemblyFileVersion("0.0.0.0")]
[assembly: AssemblyInformationalVersion("0.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("Microsoft.SqlTools.EditorServices.Test.Protocol")]

View File

@@ -1,584 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#if false
using Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel;
using Microsoft.SqlTools.EditorServices.Session;
using Microsoft.SqlTools.EditorServices.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.Server
{
public class DebugAdapter : DebugAdapterBase
{
private EditorSession editorSession;
private OutputDebouncer outputDebouncer;
private bool isConfigurationDoneRequestComplete;
private bool isLaunchRequestComplete;
private bool noDebug;
private string scriptPathToLaunch;
private string arguments;
public DebugAdapter(HostDetails hostDetails, ProfilePaths profilePaths)
: this(hostDetails, profilePaths, new StdioServerChannel())
{
}
public DebugAdapter(HostDetails hostDetails, ProfilePaths profilePaths, ChannelBase serverChannel)
: base(serverChannel)
{
this.editorSession = new EditorSession();
this.editorSession.StartSession(hostDetails, profilePaths);
this.editorSession.DebugService.DebuggerStopped += this.DebugService_DebuggerStopped;
this.editorSession.ConsoleService.OutputWritten += this.SqlToolsContext_OutputWritten;
// Set up the output debouncer to throttle output event writes
this.outputDebouncer = new OutputDebouncer(this);
}
protected override void Initialize()
{
// Register all supported message types
this.SetRequestHandler(LaunchRequest.Type, this.HandleLaunchRequest);
this.SetRequestHandler(AttachRequest.Type, this.HandleAttachRequest);
this.SetRequestHandler(ConfigurationDoneRequest.Type, this.HandleConfigurationDoneRequest);
this.SetRequestHandler(DisconnectRequest.Type, this.HandleDisconnectRequest);
this.SetRequestHandler(SetBreakpointsRequest.Type, this.HandleSetBreakpointsRequest);
this.SetRequestHandler(SetExceptionBreakpointsRequest.Type, this.HandleSetExceptionBreakpointsRequest);
this.SetRequestHandler(SetFunctionBreakpointsRequest.Type, this.HandleSetFunctionBreakpointsRequest);
this.SetRequestHandler(ContinueRequest.Type, this.HandleContinueRequest);
this.SetRequestHandler(NextRequest.Type, this.HandleNextRequest);
this.SetRequestHandler(StepInRequest.Type, this.HandleStepInRequest);
this.SetRequestHandler(StepOutRequest.Type, this.HandleStepOutRequest);
this.SetRequestHandler(PauseRequest.Type, this.HandlePauseRequest);
this.SetRequestHandler(ThreadsRequest.Type, this.HandleThreadsRequest);
this.SetRequestHandler(StackTraceRequest.Type, this.HandleStackTraceRequest);
this.SetRequestHandler(ScopesRequest.Type, this.HandleScopesRequest);
this.SetRequestHandler(VariablesRequest.Type, this.HandleVariablesRequest);
this.SetRequestHandler(SourceRequest.Type, this.HandleSourceRequest);
this.SetRequestHandler(EvaluateRequest.Type, this.HandleEvaluateRequest);
}
protected Task LaunchScript(RequestContext<object> requestContext)
{
return editorSession.SqlToolsContext
.ExecuteScriptAtPath(this.scriptPathToLaunch, this.arguments)
.ContinueWith(
async (t) => {
Logger.Write(LogLevel.Verbose, "Execution completed, terminating...");
await requestContext.SendEvent(
TerminatedEvent.Type,
null);
// Stop the server
await this.Stop();
// Notify that the session has ended
this.OnSessionEnded();
});
}
protected override void Shutdown()
{
// Make sure remaining output is flushed before exiting
this.outputDebouncer.Flush().Wait();
Logger.Write(LogLevel.Normal, "Debug adapter is shutting down...");
if (this.editorSession != null)
{
this.editorSession.Dispose();
this.editorSession = null;
}
}
#region Built-in Message Handlers
protected async Task HandleConfigurationDoneRequest(
object args,
RequestContext<object> requestContext)
{
// The order of debug protocol messages apparently isn't as guaranteed as we might like.
// Need to be able to handle the case where we get the configurationDone request after the
// launch request.
if (this.isLaunchRequestComplete)
{
this.LaunchScript(requestContext);
}
this.isConfigurationDoneRequestComplete = true;
await requestContext.SendResult(null);
}
protected async Task HandleLaunchRequest(
LaunchRequestArguments launchParams,
RequestContext<object> requestContext)
{
// Set the working directory for the SqlTools runspace to the cwd passed in via launch.json.
// In case that is null, use the the folder of the script to be executed. If the resulting
// working dir path is a file path then extract the directory and use that.
string workingDir = launchParams.Cwd ?? launchParams.Program;
workingDir = SqlToolsContext.UnescapePath(workingDir);
try
{
if ((File.GetAttributes(workingDir) & FileAttributes.Directory) != FileAttributes.Directory)
{
workingDir = Path.GetDirectoryName(workingDir);
}
}
catch (Exception ex)
{
Logger.Write(LogLevel.Error, "cwd path is invalid: " + ex.Message);
#if NanoServer
workingDir = AppContext.BaseDirectory;
#else
workingDir = Environment.CurrentDirectory;
#endif
}
editorSession.SqlToolsContext.SetWorkingDirectory(workingDir);
Logger.Write(LogLevel.Verbose, "Working dir set to: " + workingDir);
// Prepare arguments to the script - if specified
string arguments = null;
if ((launchParams.Args != null) && (launchParams.Args.Length > 0))
{
arguments = string.Join(" ", launchParams.Args);
Logger.Write(LogLevel.Verbose, "Script arguments are: " + arguments);
}
// We may not actually launch the script in response to this
// request unless it comes after the configurationDone request.
// If the launch request comes first, then stash the launch
// params so that the subsequent configurationDone request handler
// can launch the script.
this.noDebug = launchParams.NoDebug;
this.scriptPathToLaunch = launchParams.Program;
this.arguments = arguments;
// The order of debug protocol messages apparently isn't as guaranteed as we might like.
// Need to be able to handle the case where we get the launch request after the
// configurationDone request.
if (this.isConfigurationDoneRequestComplete)
{
this.LaunchScript(requestContext);
}
this.isLaunchRequestComplete = true;
await requestContext.SendResult(null);
}
protected Task HandleAttachRequest(
AttachRequestArguments attachParams,
RequestContext<object> requestContext)
{
// TODO: Implement this once we support attaching to processes
throw new NotImplementedException();
}
protected Task HandleDisconnectRequest(
object disconnectParams,
RequestContext<object> requestContext)
{
EventHandler<SessionStateChangedEventArgs> handler = null;
handler =
async (o, e) =>
{
if (e.NewSessionState == SqlToolsContextState.Ready)
{
await requestContext.SendResult(null);
editorSession.SqlToolsContext.SessionStateChanged -= handler;
// Stop the server
this.Stop();
}
};
editorSession.SqlToolsContext.SessionStateChanged += handler;
editorSession.SqlToolsContext.AbortExecution();
return Task.FromResult(true);
}
protected async Task HandleSetBreakpointsRequest(
SetBreakpointsRequestArguments setBreakpointsParams,
RequestContext<SetBreakpointsResponseBody> requestContext)
{
ScriptFile scriptFile;
// Fix for issue #195 - user can change name of file outside of VSCode in which case
// VSCode sends breakpoint requests with the original filename that doesn't exist anymore.
try
{
scriptFile = editorSession.Workspace.GetFile(setBreakpointsParams.Source.Path);
}
catch (FileNotFoundException)
{
Logger.Write(
LogLevel.Warning,
$"Attempted to set breakpoints on a non-existing file: {setBreakpointsParams.Source.Path}");
string message = this.noDebug ? string.Empty : "Source does not exist, breakpoint not set.";
var srcBreakpoints = setBreakpointsParams.Breakpoints
.Select(srcBkpt => Protocol.DebugAdapter.Breakpoint.Create(
srcBkpt, setBreakpointsParams.Source.Path, message, verified: this.noDebug));
// Return non-verified breakpoint message.
await requestContext.SendResult(
new SetBreakpointsResponseBody {
Breakpoints = srcBreakpoints.ToArray()
});
return;
}
var breakpointDetails = new BreakpointDetails[setBreakpointsParams.Breakpoints.Length];
for (int i = 0; i < breakpointDetails.Length; i++)
{
SourceBreakpoint srcBreakpoint = setBreakpointsParams.Breakpoints[i];
breakpointDetails[i] = BreakpointDetails.Create(
scriptFile.FilePath,
srcBreakpoint.Line,
srcBreakpoint.Column,
srcBreakpoint.Condition);
}
// If this is a "run without debugging (Ctrl+F5)" session ignore requests to set breakpoints.
BreakpointDetails[] updatedBreakpointDetails = breakpointDetails;
if (!this.noDebug)
{
updatedBreakpointDetails =
await editorSession.DebugService.SetLineBreakpoints(
scriptFile,
breakpointDetails);
}
await requestContext.SendResult(
new SetBreakpointsResponseBody {
Breakpoints =
updatedBreakpointDetails
.Select(Protocol.DebugAdapter.Breakpoint.Create)
.ToArray()
});
}
protected async Task HandleSetFunctionBreakpointsRequest(
SetFunctionBreakpointsRequestArguments setBreakpointsParams,
RequestContext<SetBreakpointsResponseBody> requestContext)
{
var breakpointDetails = new CommandBreakpointDetails[setBreakpointsParams.Breakpoints.Length];
for (int i = 0; i < breakpointDetails.Length; i++)
{
FunctionBreakpoint funcBreakpoint = setBreakpointsParams.Breakpoints[i];
breakpointDetails[i] = CommandBreakpointDetails.Create(
funcBreakpoint.Name,
funcBreakpoint.Condition);
}
// If this is a "run without debugging (Ctrl+F5)" session ignore requests to set breakpoints.
CommandBreakpointDetails[] updatedBreakpointDetails = breakpointDetails;
if (!this.noDebug)
{
updatedBreakpointDetails =
await editorSession.DebugService.SetCommandBreakpoints(
breakpointDetails);
}
await requestContext.SendResult(
new SetBreakpointsResponseBody {
Breakpoints =
updatedBreakpointDetails
.Select(Protocol.DebugAdapter.Breakpoint.Create)
.ToArray()
});
}
protected async Task HandleSetExceptionBreakpointsRequest(
SetExceptionBreakpointsRequestArguments setExceptionBreakpointsParams,
RequestContext<object> requestContext)
{
// TODO: Handle this appropriately
await requestContext.SendResult(null);
}
protected async Task HandleContinueRequest(
object continueParams,
RequestContext<object> requestContext)
{
editorSession.DebugService.Continue();
await requestContext.SendResult(null);
}
protected async Task HandleNextRequest(
object nextParams,
RequestContext<object> requestContext)
{
editorSession.DebugService.StepOver();
await requestContext.SendResult(null);
}
protected Task HandlePauseRequest(
object pauseParams,
RequestContext<object> requestContext)
{
try
{
editorSession.DebugService.Break();
}
catch (NotSupportedException e)
{
return requestContext.SendError(e.Message);
}
// This request is responded to by sending the "stopped" event
return Task.FromResult(true);
}
protected async Task HandleStepInRequest(
object stepInParams,
RequestContext<object> requestContext)
{
editorSession.DebugService.StepIn();
await requestContext.SendResult(null);
}
protected async Task HandleStepOutRequest(
object stepOutParams,
RequestContext<object> requestContext)
{
editorSession.DebugService.StepOut();
await requestContext.SendResult(null);
}
protected async Task HandleThreadsRequest(
object threadsParams,
RequestContext<ThreadsResponseBody> requestContext)
{
await requestContext.SendResult(
new ThreadsResponseBody
{
Threads = new Thread[]
{
// TODO: What do I do with these?
new Thread
{
Id = 1,
Name = "Main Thread"
}
}
});
}
protected async Task HandleStackTraceRequest(
StackTraceRequestArguments stackTraceParams,
RequestContext<StackTraceResponseBody> requestContext)
{
StackFrameDetails[] stackFrames =
editorSession.DebugService.GetStackFrames();
List<StackFrame> newStackFrames = new List<StackFrame>();
for (int i = 0; i < stackFrames.Length; i++)
{
// Create the new StackFrame object with an ID that can
// be referenced back to the current list of stack frames
newStackFrames.Add(
StackFrame.Create(
stackFrames[i],
i));
}
await requestContext.SendResult(
new StackTraceResponseBody
{
StackFrames = newStackFrames.ToArray()
});
}
protected async Task HandleScopesRequest(
ScopesRequestArguments scopesParams,
RequestContext<ScopesResponseBody> requestContext)
{
VariableScope[] variableScopes =
editorSession.DebugService.GetVariableScopes(
scopesParams.FrameId);
await requestContext.SendResult(
new ScopesResponseBody
{
Scopes =
variableScopes
.Select(Scope.Create)
.ToArray()
});
}
protected async Task HandleVariablesRequest(
VariablesRequestArguments variablesParams,
RequestContext<VariablesResponseBody> requestContext)
{
VariableDetailsBase[] variables =
editorSession.DebugService.GetVariables(
variablesParams.VariablesReference);
VariablesResponseBody variablesResponse = null;
try
{
variablesResponse = new VariablesResponseBody
{
Variables =
variables
.Select(Variable.Create)
.ToArray()
};
}
catch (Exception)
{
// TODO: This shouldn't be so broad
}
await requestContext.SendResult(variablesResponse);
}
protected Task HandleSourceRequest(
SourceRequestArguments sourceParams,
RequestContext<SourceResponseBody> requestContext)
{
// TODO: Implement this message. For now, doesn't seem to
// be a problem that it's missing.
return Task.FromResult(true);
}
protected async Task HandleEvaluateRequest(
EvaluateRequestArguments evaluateParams,
RequestContext<EvaluateResponseBody> requestContext)
{
string valueString = null;
int variableId = 0;
bool isFromRepl =
string.Equals(
evaluateParams.Context,
"repl",
StringComparison.CurrentCultureIgnoreCase);
if (isFromRepl)
{
// Send the input through the console service
editorSession.ConsoleService.ExecuteCommand(
evaluateParams.Expression,
false);
}
else
{
VariableDetails result =
await editorSession.DebugService.EvaluateExpression(
evaluateParams.Expression,
evaluateParams.FrameId,
isFromRepl);
if (result != null)
{
valueString = result.ValueString;
variableId =
result.IsExpandable ?
result.Id : 0;
}
}
await requestContext.SendResult(
new EvaluateResponseBody
{
Result = valueString,
VariablesReference = variableId
});
}
#endregion
#region Events
public event EventHandler SessionEnded;
protected virtual void OnSessionEnded()
{
this.SessionEnded?.Invoke(this, null);
}
#endregion
#region Event Handlers
async void DebugService_DebuggerStopped(object sender, DebuggerStopEventArgs e)
{
// Flush pending output before sending the event
await this.outputDebouncer.Flush();
// Provide the reason for why the debugger has stopped script execution.
// See https://github.com/Microsoft/vscode/issues/3648
// The reason is displayed in the breakpoints viewlet. Some recommended reasons are:
// "step", "breakpoint", "function breakpoint", "exception" and "pause".
// We don't support exception breakpoints and for "pause", we can't distinguish
// between stepping and the user pressing the pause/break button in the debug toolbar.
string debuggerStoppedReason = "step";
if (e.Breakpoints.Count > 0)
{
debuggerStoppedReason =
e.Breakpoints[0] is CommandBreakpoint
? "function breakpoint"
: "breakpoint";
}
await this.SendEvent(
StoppedEvent.Type,
new StoppedEventBody
{
Source = new Source
{
Path = e.InvocationInfo.ScriptName,
},
Line = e.InvocationInfo.ScriptLineNumber,
Column = e.InvocationInfo.OffsetInLine,
ThreadId = 1, // TODO: Change this based on context
Reason = debuggerStoppedReason
});
}
async void SqlToolsContext_OutputWritten(object sender, OutputWrittenEventArgs e)
{
// Queue the output for writing
await this.outputDebouncer.Invoke(e);
}
#endregion
}
}
#endif

View File

@@ -1,73 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#if false
using Microsoft.SqlTools.EditorServices.Protocol.DebugAdapter;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.Server
{
public abstract class DebugAdapterBase : ProtocolEndpoint
{
public DebugAdapterBase(ChannelBase serverChannel)
: base (serverChannel, MessageProtocolType.DebugAdapter)
{
}
/// <summary>
/// Overridden by the subclass to provide initialization
/// logic after the server channel is started.
/// </summary>
protected abstract void Initialize();
/// <summary>
/// Can be overridden by the subclass to provide shutdown
/// logic before the server exits.
/// </summary>
protected virtual void Shutdown()
{
// No default implementation yet.
}
protected override Task OnStart()
{
// Register handlers for server lifetime messages
this.SetRequestHandler(InitializeRequest.Type, this.HandleInitializeRequest);
// Initialize the implementation class
this.Initialize();
return Task.FromResult(true);
}
protected override Task OnStop()
{
this.Shutdown();
return Task.FromResult(true);
}
private async Task HandleInitializeRequest(
object shutdownParams,
RequestContext<InitializeResponseBody> requestContext)
{
// Now send the Initialize response to continue setup
await requestContext.SendResult(
new InitializeResponseBody {
SupportsConfigurationDoneRequest = true,
SupportsConditionalBreakpoints = true,
SupportsFunctionBreakpoints = true
});
// Send the Initialized event so that we get breakpoints
await requestContext.SendEvent(
InitializedEvent.Type,
null);
}
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,7 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.Server
}
}
public class ScriptAnalysisSettings
{
public bool? Enable { get; set; }
@@ -77,6 +78,7 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.Server
}
}
public class LanguageServerSettingsWrapper
{
// NOTE: This property is capitalized as 'SqlTools' because the

View File

@@ -1,102 +0,0 @@
//
// 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.DebugAdapter;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using Microsoft.SqlTools.EditorServices.Utility;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.Server
{
/// <summary>
/// Throttles output written via OutputEvents by batching all output
/// written within a short time window and writing it all out at once.
/// </summary>
internal class OutputDebouncer : AsyncDebouncer<OutputWrittenEventArgs>
{
#region Private Fields
private IMessageSender messageSender;
private bool currentOutputIsError = false;
private string currentOutputString = null;
#endregion
#region Constants
// Set a really short window for output flushes. This
// gives the appearance of fast output without the crushing
// overhead of sending an OutputEvent for every single line
// written. At this point it seems that around 10-20 lines get
// batched for each flush when Get-Process is called.
public const int OutputFlushInterval = 200;
#endregion
#region Constructors
public OutputDebouncer(IMessageSender messageSender)
: base(OutputFlushInterval, false)
{
this.messageSender = messageSender;
}
#endregion
#region Private Methods
protected override async Task OnInvoke(OutputWrittenEventArgs output)
{
bool outputIsError = output.OutputType == OutputType.Error;
if (this.currentOutputIsError != outputIsError)
{
if (this.currentOutputString != null)
{
// Flush the output
await this.OnFlush();
}
this.currentOutputString = string.Empty;
this.currentOutputIsError = outputIsError;
}
// Output string could be null if the last output was already flushed
if (this.currentOutputString == null)
{
this.currentOutputString = string.Empty;
}
// Add to string (and include newline)
this.currentOutputString +=
output.OutputText +
(output.IncludeNewLine ?
System.Environment.NewLine :
string.Empty);
}
protected override async Task OnFlush()
{
// Only flush output if there is some to flush
if (this.currentOutputString != null)
{
// Send an event for the current output
await this.messageSender.SendEvent(
OutputEvent.Type,
new OutputEventBody
{
Output = this.currentOutputString,
Category = (this.currentOutputIsError) ? "stderr" : "stdout"
});
// Clear the output string for the next batch
this.currentOutputString = null;
}
}
#endregion
}
}

View File

@@ -1,190 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#if false
using System;
using Microsoft.SqlTools.EditorServices.Console;
using Microsoft.SqlTools.EditorServices.Protocol.Messages;
using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol;
using Microsoft.SqlTools.EditorServices.Utility;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Protocol.Server
{
internal class ProtocolPromptHandlerContext : IPromptHandlerContext
{
private IMessageSender messageSender;
private ConsoleService consoleService;
public ProtocolPromptHandlerContext(
IMessageSender messageSender,
ConsoleService consoleService)
{
this.messageSender = messageSender;
this.consoleService = consoleService;
}
public ChoicePromptHandler GetChoicePromptHandler()
{
return new ProtocolChoicePromptHandler(
this.messageSender,
this.consoleService);
}
public InputPromptHandler GetInputPromptHandler()
{
return new ProtocolInputPromptHandler(
this.messageSender,
this.consoleService);
}
}
internal class ProtocolChoicePromptHandler : ChoicePromptHandler
{
private IMessageSender messageSender;
private ConsoleService consoleService;
public ProtocolChoicePromptHandler(
IMessageSender messageSender,
ConsoleService consoleService)
{
this.messageSender = messageSender;
this.consoleService = consoleService;
}
protected override void ShowPrompt(PromptStyle promptStyle)
{
messageSender
.SendRequest(
ShowChoicePromptRequest.Type,
new ShowChoicePromptRequest
{
Caption = this.Caption,
Message = this.Message,
Choices = this.Choices,
DefaultChoice = this.DefaultChoice
}, true)
.ContinueWith(HandlePromptResponse)
.ConfigureAwait(false);
}
private void HandlePromptResponse(
Task<ShowChoicePromptResponse> responseTask)
{
if (responseTask.IsCompleted)
{
ShowChoicePromptResponse response = responseTask.Result;
if (!response.PromptCancelled)
{
this.consoleService.ReceivePromptResponse(
response.ChosenItem,
false);
}
else
{
// Cancel the current prompt
this.consoleService.SendControlC();
}
}
else
{
if (responseTask.IsFaulted)
{
// Log the error
Logger.Write(
LogLevel.Error,
"ShowChoicePrompt request failed with error:\r\n{0}",
responseTask.Exception.ToString());
}
// Cancel the current prompt
this.consoleService.SendControlC();
}
}
}
internal class ProtocolInputPromptHandler : ConsoleInputPromptHandler
{
private IMessageSender messageSender;
private ConsoleService consoleService;
public ProtocolInputPromptHandler(
IMessageSender messageSender,
ConsoleService consoleService)
: base(consoleService)
{
this.messageSender = messageSender;
this.consoleService = consoleService;
}
protected override void ShowErrorMessage(Exception e)
{
// Use default behavior for writing the error message
base.ShowErrorMessage(e);
}
protected override void ShowPromptMessage(string caption, string message)
{
// Use default behavior for writing the prompt message
base.ShowPromptMessage(caption, message);
}
protected override void ShowFieldPrompt(FieldDetails fieldDetails)
{
// Write the prompt to the console first so that there's a record
// of it occurring
base.ShowFieldPrompt(fieldDetails);
messageSender
.SendRequest(
ShowInputPromptRequest.Type,
new ShowInputPromptRequest
{
Name = fieldDetails.Name,
Label = fieldDetails.Label
}, true)
.ContinueWith(HandlePromptResponse)
.ConfigureAwait(false);
}
private void HandlePromptResponse(
Task<ShowInputPromptResponse> responseTask)
{
if (responseTask.IsCompleted)
{
ShowInputPromptResponse response = responseTask.Result;
if (!response.PromptCancelled)
{
this.consoleService.ReceivePromptResponse(
response.ResponseText,
true);
}
else
{
// Cancel the current prompt
this.consoleService.SendControlC();
}
}
else
{
if (responseTask.IsFaulted)
{
// Log the error
Logger.Write(
LogLevel.Error,
"ShowInputPrompt request failed with error:\r\n{0}",
responseTask.Exception.ToString());
}
// Cancel the current prompt
this.consoleService.SendControlC();
}
}
}
}
#endif

View File

@@ -3,11 +3,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// using Microsoft.SqlTools.EditorServices.Console;
// using Microsoft.SqlTools.EditorServices.Extensions;
using System;
using Microsoft.SqlTools.EditorServices.Session;
// using Microsoft.SqlTools.EditorServices.Utility;
// using System.IO;
namespace Microsoft.SqlTools.EditorServices
{
@@ -15,12 +12,8 @@ namespace Microsoft.SqlTools.EditorServices
/// Manages a single session for all editor services. This
/// includes managing all open script files for the session.
/// </summary>
public class EditorSession
public class EditorSession : IDisposable
{
public void StartSession(HostDetails hostDetails, ProfilePaths profilePaths)
{
}
#if false
#region Properties
/// <summary>
@@ -33,6 +26,59 @@ namespace Microsoft.SqlTools.EditorServices
/// </summary>
public SqlToolsContext SqlToolsContext { get; private set; }
#endregion
#region Public Methods
/// <summary>
/// Starts the session using the provided IConsoleHost implementation
/// for the ConsoleService.
/// </summary>
/// <param name="hostDetails">
/// Provides details about the host application.
/// </param>
/// <param name="profilePaths">
/// An object containing the profile paths for the session.
/// </param>
public void StartSession(HostDetails hostDetails, ProfilePaths profilePaths)
{
// Initialize all services
this.SqlToolsContext = new SqlToolsContext(hostDetails, profilePaths);
// this.LanguageService = new LanguageService(this.SqlToolsContext);
// this.DebugService = new DebugService(this.SqlToolsContext);
// this.ConsoleService = new ConsoleService(this.SqlToolsContext);
// this.ExtensionService = new ExtensionService(this.SqlToolsContext);
// this.InstantiateAnalysisService();
// Create a workspace to contain open files
this.Workspace = new Workspace(this.SqlToolsContext.SqlToolsVersion);
}
#endregion
#region IDisposable Implementation
/// <summary>
/// Disposes of any Runspaces that were created for the
/// services used in this session.
/// </summary>
public void Dispose()
{
}
#endregion
#if false
#region Properties
/// <summary>
/// Gets the LanguageService instance for this session.
/// </summary>

View File

@@ -0,0 +1,25 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
namespace Microsoft.SqlTools.EditorServices.Session
{
public class SqlToolsContext
{
/// <summary>
/// Gets the PowerShell version of the current runspace.
/// </summary>
public Version SqlToolsVersion
{
get; private set;
}
public SqlToolsContext(HostDetails hostDetails, ProfilePaths profilePaths)
{
}
}
}

View File

@@ -1,169 +0,0 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.EditorServices.Utility
{
/// <summary>
/// Restricts the invocation of an operation to a specified time
/// interval. Can also cause previous requests to be cancelled
/// by new requests within that time window. Typically used for
/// buffering information for an operation or ensuring that an
/// operation only runs after some interval.
/// </summary>
/// <typeparam name="TInvokeArgs">The argument type for the Invoke method.</typeparam>
public abstract class AsyncDebouncer<TInvokeArgs>
{
#region Private Fields
private int flushInterval;
private bool restartOnInvoke;
private Task currentTimerTask;
private CancellationTokenSource timerCancellationSource;
private AsyncLock asyncLock = new AsyncLock();
#endregion
#region Public Methods
/// <summary>
/// Creates a new instance of the AsyncDebouncer class with the
/// specified flush interval. If restartOnInvoke is true, any
/// calls to Invoke will cancel previous calls which have not yet
/// passed the flush interval.
/// </summary>
/// <param name="flushInterval">
/// A millisecond interval to use for flushing prior Invoke calls.
/// </param>
/// <param name="restartOnInvoke">
/// If true, Invoke calls will reset prior calls which haven't passed the flush interval.
/// </param>
public AsyncDebouncer(int flushInterval, bool restartOnInvoke)
{
this.flushInterval = flushInterval;
this.restartOnInvoke = restartOnInvoke;
}
/// <summary>
/// Invokes the debouncer with the given input. The debouncer will
/// wait for the specified interval before calling the Flush method
/// to complete the operation.
/// </summary>
/// <param name="invokeArgument">
/// The argument for this implementation's Invoke method.
/// </param>
/// <returns>A Task to be awaited until the Invoke is queued.</returns>
public async Task Invoke(TInvokeArgs invokeArgument)
{
using (await this.asyncLock.LockAsync())
{
// Invoke the implementor
await this.OnInvoke(invokeArgument);
// If there's no timer, start one
if (this.currentTimerTask == null)
{
this.StartTimer();
}
else if (this.currentTimerTask != null && this.restartOnInvoke)
{
// Restart the existing timer
if (this.CancelTimer())
{
this.StartTimer();
}
}
}
}
/// <summary>
/// Flushes the latest state regardless of the current interval.
/// An AsyncDebouncer MUST NOT invoke its own Flush method otherwise
/// deadlocks could occur.
/// </summary>
/// <returns>A Task to be awaited until Flush completes.</returns>
public async Task Flush()
{
using (await this.asyncLock.LockAsync())
{
// Cancel the current timer
this.CancelTimer();
// Flush the current output
await this.OnFlush();
}
}
#endregion
#region Abstract Methods
/// <summary>
/// Implemented by the subclass to take the argument for the
/// future operation that will be performed by OnFlush.
/// </summary>
/// <param name="invokeArgument">
/// The argument for this implementation's OnInvoke method.
/// </param>
/// <returns>A Task to be awaited for the invoke to complete.</returns>
protected abstract Task OnInvoke(TInvokeArgs invokeArgument);
/// <summary>
/// Implemented by the subclass to complete the current operation.
/// </summary>
/// <returns>A Task to be awaited for the operation to complete.</returns>
protected abstract Task OnFlush();
#endregion
#region Private Methods
private void StartTimer()
{
this.timerCancellationSource = new CancellationTokenSource();
this.currentTimerTask =
Task.Delay(this.flushInterval, this.timerCancellationSource.Token)
.ContinueWith(
t =>
{
if (!t.IsCanceled)
{
return this.Flush();
}
else
{
return Task.FromResult(true);
}
});
}
private bool CancelTimer()
{
if (this.timerCancellationSource != null)
{
// Attempt to cancel the timer task
this.timerCancellationSource.Cancel();
}
// Was the task cancelled?
bool wasCancelled =
this.currentTimerTask == null ||
this.currentTimerTask.IsCanceled;
// Clear the current task so that another may be created
this.currentTimerTask = null;
return wasCancelled;
}
#endregion
}
}

View File

@@ -18,6 +18,30 @@ namespace Microsoft.SqlTools.EditorServices
/// </summary>
public class ScriptFile
{
public ScriptFile(
string filePath,
string clientFilePath,
TextReader textReader,
Version SqlToolsVersion)
{
}
/// <summary>
/// Creates a new ScriptFile instance with the specified file contents.
/// </summary>
/// <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="initialBuffer">The initial contents of the script file.</param>
/// <param name="SqlToolsVersion">The version of SqlTools for which the script is being parsed.</param>
public ScriptFile(
string filePath,
string clientFilePath,
string initialBuffer,
Version SqlToolsVersion)
{
}
#if false
#region Private Fields

View File

@@ -6,9 +6,9 @@
using Microsoft.SqlTools.EditorServices.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace Microsoft.SqlTools.EditorServices
{
@@ -18,8 +18,7 @@ namespace Microsoft.SqlTools.EditorServices
/// </summary>
public class Workspace
{
#if false
#region Private Fields
#region Private Fields
private Version SqlToolsVersion;
private Dictionary<string, ScriptFile> workspaceFiles = new Dictionary<string, ScriptFile>();
@@ -94,6 +93,70 @@ namespace Microsoft.SqlTools.EditorServices
return scriptFile;
}
private string ResolveFilePath(string filePath)
{
if (!IsPathInMemory(filePath))
{
if (filePath.StartsWith(@"file://"))
{
// Client sent the path in URI format, extract the local path and trim
// any extraneous slashes
Uri fileUri = new Uri(filePath);
filePath = fileUri.LocalPath.TrimStart('/');
}
// Some clients send paths with UNIX-style slashes, replace those if necessary
filePath = filePath.Replace('/', '\\');
// Clients could specify paths with escaped space, [ and ] characters which .NET APIs
// will not handle. These paths will get appropriately escaped just before being passed
// into the SqlTools engine.
filePath = UnescapePath(filePath);
// Get the absolute file path
filePath = Path.GetFullPath(filePath);
}
Logger.Write(LogLevel.Verbose, "Resolved path: " + filePath);
return filePath;
}
internal static bool IsPathInMemory(string filePath)
{
// When viewing SqlTools files in the Git diff viewer, VS Code
// sends the contents of the file at HEAD with a URI that starts
// with 'inmemory'. Untitled files which have been marked of
// type SqlTools have a path starting with 'untitled'.
return
filePath.StartsWith("inmemory") ||
filePath.StartsWith("untitled");
}
/// <summary>
/// Unescapes any escaped [, ] or space characters. Typically use this before calling a
/// .NET API that doesn't understand PowerShell escaped chars.
/// </summary>
/// <param name="path">The path to unescape.</param>
/// <returns>The path with the ` character before [, ] and spaces removed.</returns>
public static string UnescapePath(string path)
{
if (!path.Contains("`"))
{
return path;
}
return Regex.Replace(path, @"`(?=[ \[\]])", "");
}
#endregion
#if false
#region Public Methods
/// <summary>
/// Gets a new ScriptFile instance which is identified by the given file
/// path and initially contains the given buffer contents.
@@ -222,46 +285,6 @@ namespace Microsoft.SqlTools.EditorServices
}
}
private string ResolveFilePath(string filePath)
{
if (!IsPathInMemory(filePath))
{
if (filePath.StartsWith(@"file://"))
{
// Client sent the path in URI format, extract the local path and trim
// any extraneous slashes
Uri fileUri = new Uri(filePath);
filePath = fileUri.LocalPath.TrimStart('/');
}
// Some clients send paths with UNIX-style slashes, replace those if necessary
filePath = filePath.Replace('/', '\\');
// Clients could specify paths with escaped space, [ and ] characters which .NET APIs
// will not handle. These paths will get appropriately escaped just before being passed
// into the SqlTools engine.
filePath = SqlToolsContext.UnescapePath(filePath);
// Get the absolute file path
filePath = Path.GetFullPath(filePath);
}
Logger.Write(LogLevel.Verbose, "Resolved path: " + filePath);
return filePath;
}
internal static bool IsPathInMemory(string filePath)
{
// When viewing SqlTools files in the Git diff viewer, VS Code
// sends the contents of the file at HEAD with a URI that starts
// with 'inmemory'. Untitled files which have been marked of
// type SqlTools have a path starting with 'untitled'.
return
filePath.StartsWith("inmemory") ||
filePath.StartsWith("untitled");
}
private string GetBaseFilePath(string filePath)
{
if (IsPathInMemory(filePath))