diff --git a/Build/18.0/packages.config b/Build/18.0/packages.config
index 4e71b0f318..9ca1241570 100644
--- a/Build/18.0/packages.config
+++ b/Build/18.0/packages.config
@@ -85,6 +85,7 @@
+
diff --git a/Python/Product/PythonTools/PythonTools.csproj b/Python/Product/PythonTools/PythonTools.csproj
index 29515d8543..6648e150b6 100644
--- a/Python/Product/PythonTools/PythonTools.csproj
+++ b/Python/Product/PythonTools/PythonTools.csproj
@@ -243,6 +243,11 @@
True
+
+ $(PackagesPath)\System.Text.Json.8.0.5\lib\net462\System.Text.Json.dll
+ false
+ false
+
diff --git a/Python/Product/PythonTools/PythonTools/LanguageServerClient/LanguageServerSettings.cs b/Python/Product/PythonTools/PythonTools/LanguageServerClient/LanguageServerSettings.cs
index cd294d19cf..9b62f11d2a 100644
--- a/Python/Product/PythonTools/PythonTools/LanguageServerClient/LanguageServerSettings.cs
+++ b/Python/Product/PythonTools/PythonTools/LanguageServerClient/LanguageServerSettings.cs
@@ -53,91 +53,91 @@ public class PythonAnalysisSettings {
///
/// Paths to look for typeshed modules.
///
- public string[] typeshedPaths;
+ public string[] typeshedPaths { get; set; }
///
/// Path to directory containing custom type stub files.
///
- public string stubPath;
+ public string stubPath { get; set; }
///
/// Allows a user to override the severity levels for individual diagnostics.
/// Typically specified in mspythonconfig.json.
///
- public Dictionary diagnosticSeverityOverrides;
+ public Dictionary diagnosticSeverityOverrides { get; set; }
///
/// Analyzes and reports errors on only open files or the entire workspace.
/// "enum": ["openFilesOnly", "workspace"]
///
- public string diagnosticMode;
+ public string diagnosticMode { get; set; }
///
/// Specifies the level of logging for the Output panel.
/// "enum": ["Error", "Warning", "Information", "Trace"]
///
- public string logLevel;
+ public string logLevel { get; set; }
///
/// Automatically add common search paths like 'src'.
///
- public bool? autoSearchPaths;
+ public bool? autoSearchPaths { get; set; }
///
/// Defines the default rule set for type checking.
///
- public string typeCheckingMode;
+ public string typeCheckingMode { get; set; }
///
/// Use library implementations to extract type information when type stub is not present.
///
- public bool? useLibraryCodeForTypes;
+ public bool? useLibraryCodeForTypes { get; set; }
///
/// Additional import search resolution paths.
///
- public string[] extraPaths;
+ public string[] extraPaths { get; set; }
///
/// Automatically add brackets for functions.
///
- public bool completeFunctionParens;
+ public bool completeFunctionParens { get; set; }
///
/// Offer auto-import completions.
///
- public bool autoImportCompletions;
+ public bool autoImportCompletions { get; set; }
///
/// Index installed third party libraries and user files for language features such as auto-import, add import, workspace symbols and etc.
///
- public bool? indexing;
+ public bool? indexing { get; set; }
///
/// Allow using '.', '(' as commit characters when applicable.
///
- public bool? extraCommitChars;
+ public bool? extraCommitChars { get; set; }
- public PythonAnalysisInlayHintsSettings inlayHints;
+ public PythonAnalysisInlayHintsSettings inlayHints { get; set; }
- public string importFormat;
+ public string importFormat { get; set; }
///
/// Tokens that identify comments that should show up in the task list pane
///
- public TaskListToken[] taskListTokens;
+ public TaskListToken[] taskListTokens { get; set; }
public class PythonAnalysisInlayHintsSettings {
///
/// Enable/disable inlay hints for variable types:\n```python\nfoo ' :list[str] ' = [\"a\"]\n \n```\n
///
- public bool variableTypes;
+ public bool variableTypes { get; set; }
///
/// Enable/disable inlay hints for function return types:\n```python\ndef foo(x:int) ' -> int ':\n\treturn x\n```\n"
///
- public bool functionReturnTypes;
+ public bool functionReturnTypes { get; set; }
}
public class TaskListToken {
@@ -145,34 +145,34 @@ public class TaskListToken {
///
/// The text of the token.
///
- public string text;
+ public string text { get; set; }
///
/// The priority of the token.
/// This comes from the CommentTaskPriority enum in Microsoft.VisualStudio.Shell
///
- public string priority;
+ public string priority { get; set; }
}
}
///
/// Analysis settings.
///
- public PythonAnalysisSettings analysis;
+ public PythonAnalysisSettings analysis { get; set; }
///
/// Path to Python, you can use a custom version of Python.
///
- public string pythonPath;
+ public string pythonPath { get; set; }
///
/// Path to folder with a list of Virtual Environments.
///
- public string venvPath;
+ public string venvPath { get; set; }
}
///
/// Python section.
///
- public PythonSettings python;
+ public PythonSettings python { get; set; }
}
}
diff --git a/Python/Product/PythonTools/PythonTools/LanguageServerClient/PythonLanguageClient.cs b/Python/Product/PythonTools/PythonTools/LanguageServerClient/PythonLanguageClient.cs
index c5939c9e6e..0a0d00c377 100644
--- a/Python/Product/PythonTools/PythonTools/LanguageServerClient/PythonLanguageClient.cs
+++ b/Python/Product/PythonTools/PythonTools/LanguageServerClient/PythonLanguageClient.cs
@@ -258,8 +258,8 @@ private Task TriggerWorkspaceUpdateConfig() {
Debug.WriteLine("Settings Changed");
return InvokeDidChangeConfigurationAsync(new LSP.DidChangeConfigurationParams() {
// Pylance will ask us for per workspace configuration settings. We can send
- // default workspace settings here.
- Settings = GetSettings()
+ // section-keyed default settings here for clients without configuration support.
+ Settings = new { python = GetSettings() }
});
}
diff --git a/Python/Product/PythonTools/PythonTools/LanguageServerClient/PythonLanguageClientCustomTarget.cs b/Python/Product/PythonTools/PythonTools/LanguageServerClient/PythonLanguageClientCustomTarget.cs
index a09e6e6a00..5e2ef5b014 100644
--- a/Python/Product/PythonTools/PythonTools/LanguageServerClient/PythonLanguageClientCustomTarget.cs
+++ b/Python/Product/PythonTools/PythonTools/LanguageServerClient/PythonLanguageClientCustomTarget.cs
@@ -23,6 +23,7 @@
using Microsoft.PythonTools.Logging;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Threading;
+using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using StreamJsonRpc;
using Task = System.Threading.Tasks.Task;
@@ -95,43 +96,39 @@ public PythonLanguageClientCustomTarget(IServiceProvider site, JoinableTaskConte
///
internal event AsyncEventHandler WorkspaceFolders;
- [JsonRpcMethod("telemetry/event")]
- public void OnTelemetryEvent(JToken arg) {
- if (!(arg is JObject telemetry)) {
+ [JsonRpcMethod("telemetry/event", UseSingleObjectParameterDeserialization = true)]
+ public void OnTelemetryEvent(object arg) {
+ PylanceTelemetryEvent telemetry;
+ try {
+ telemetry = Deserialize(arg);
+ } catch (JsonException) {
return;
}
- Trace.WriteLine(telemetry.ToString());
- try {
- var te = telemetry.ToObject();
- if (te == null) {
- return;
- }
-
- if (te.Exception == null) {
- _logger.LogEvent(te.EventName, te.Properties, te.Measurements);
- } else {
- _logger.LogFault(new PylanceException(te.EventName, te.Exception.stack), te.EventName, false);
- }
+ if (telemetry == null) {
+ return;
+ }
- // Special case language_server/analysis_complete. We need this for testing so we
- // know when it's okay to try to bring up intellisense
- if (te.EventName == "language_server/analysis_complete") {
- AnalysisComplete.Invoke(this, EventArgs.Empty);
- }
- } catch {
+ Trace.WriteLine(arg);
+ if (telemetry.Exception == null) {
+ _logger?.LogEvent(telemetry.EventName, telemetry.Properties, telemetry.Measurements);
+ } else {
+ _logger?.LogFault(new PylanceException(telemetry.EventName, telemetry.Exception.stack), telemetry.EventName, false);
+ }
+ // Special case language_server/analysis_complete. We need this for testing so we
+ // know when it's okay to try to bring up intellisense
+ if (telemetry.EventName == "language_server/analysis_complete") {
+AnalysisComplete?.Invoke(this, EventArgs.Empty);
}
}
[JsonRpcMethod("python/beginProgress")]
-#pragma warning disable IDE0060 // Remove unused parameter
- public void OnBeginProgressAsync(JToken arg) {
-#pragma warning restore IDE0060 // Remove unused parameter
+ public void OnBeginProgressAsync() {
}
[JsonRpcMethod("python/reportProgress")]
- public async Task OnReportProgressAsync(JToken arg) {
+ public async Task OnReportProgressAsync(object arg) {
if (arg != null) {
await _joinableTaskContext.Factory.SwitchToMainThreadAsync();
@@ -143,7 +140,7 @@ public async Task OnReportProgressAsync(JToken arg) {
}
[JsonRpcMethod("python/endProgress")]
- public async Task OnEndProgressAsync(JToken arg) {
+ public async Task OnEndProgressAsync() {
await _joinableTaskContext.Factory.SwitchToMainThreadAsync();
// TODO: localize text
@@ -151,15 +148,18 @@ public async Task OnEndProgressAsync(JToken arg) {
statusBar?.SetText("Python analysis done");
}
- [JsonRpcMethod("client/registerCapability")]
- public void OnRegisterCapability(JToken arg) {
- var regParams = arg.ToObject();
+ [JsonRpcMethod("client/registerCapability", UseSingleObjectParameterDeserialization = true)]
+ public void OnRegisterCapability(object arg) {
+ var regParams = Deserialize(arg);
+ if (regParams?.Registrations == null) {
+ return;
+ }
+
if (regParams.Registrations.Any(p => p.Method == "workspace/didChangeWorkspaceFolders")) {
_joinableTaskContext.Factory.RunAsync(async () => this.WorkspaceFolderChangeRegistered.Invoke(this, EventArgs.Empty));
}
var watchedFilesReg = regParams.Registrations.FirstOrDefault(p => p.Method == "workspace/didChangeWatchedFiles");
- if (watchedFilesReg != null) {
- var optionsObj = watchedFilesReg.RegisterOptions as JObject;
+ if (watchedFilesReg?.RegisterOptions is JObject optionsObj) {
var options = optionsObj.ToObject();
if (options != null) {
_joinableTaskContext.Factory.RunAsync(async () => this.WatchedFilesRegistered.Invoke(this, options));
@@ -167,19 +167,26 @@ public void OnRegisterCapability(JToken arg) {
}
}
- [JsonRpcMethod("workspace/configuration")]
- public async Task