Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Build/18.0/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
<package id="Microsoft.Extensions.Logging.Abstractions" version = "8.0.2" /> <!-- 5.0.0 -> 8.0.2 -->
<package id="System.Threading.Tasks.Extensions" version="4.6.0"/>
<package id="System.Memory" version="4.6.0"/>
<package id="System.Text.Json" version="8.0.5"/>
<package id="Microsoft.VisualStudio.RpcContracts" version = "17.15.25-pre" /> <!-- 17.15.26-pre -->
<package id="Microsoft.DiaSymReader.Pdb2Pdb" version = "1.1.0-beta2-26280-01" /> <!-- 1.1.0-beta2-21181-01 -> 1.1.0-beta2-24172-02 -->
<package id="Microsoft.TestPlatform.ObjectModel" version = "17.14.1" /> <!-- 17.4.0-preview-20221003-03 -> 17.14.1 -->
Expand Down
5 changes: 5 additions & 0 deletions Python/Product/PythonTools/PythonTools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@
<Private>True</Private>
</Reference>
<Reference Include="System.Memory" />
<Reference Include="System.Text.Json, Version=8.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" Condition="'$(VSTarget)' == '18.0'">
<HintPath>$(PackagesPath)\System.Text.Json.8.0.5\lib\net462\System.Text.Json.dll</HintPath>
<Private>false</Private>
<SpecificVersion>false</SpecificVersion>
</Reference>
<Reference Include="Microsoft.VisualStudio.RpcContracts" />
</ItemGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,126 +53,126 @@ public class PythonAnalysisSettings {
/// <summary>
/// Paths to look for typeshed modules.
/// </summary>
public string[] typeshedPaths;
public string[] typeshedPaths { get; set; }

/// <summary>
/// Path to directory containing custom type stub files.
/// </summary>
public string stubPath;
public string stubPath { get; set; }

/// <summary>
/// Allows a user to override the severity levels for individual diagnostics.
/// Typically specified in mspythonconfig.json.
/// </summary>
public Dictionary<string, string> diagnosticSeverityOverrides;
public Dictionary<string, string> diagnosticSeverityOverrides { get; set; }

/// <summary>
/// Analyzes and reports errors on only open files or the entire workspace.
/// "enum": ["openFilesOnly", "workspace"]
/// </summary>
public string diagnosticMode;
public string diagnosticMode { get; set; }

/// <summary>
/// Specifies the level of logging for the Output panel.
/// "enum": ["Error", "Warning", "Information", "Trace"]
/// </summary>
public string logLevel;
public string logLevel { get; set; }

/// <summary>
/// Automatically add common search paths like 'src'.
/// </summary>
public bool? autoSearchPaths;
public bool? autoSearchPaths { get; set; }

/// <summary>
/// Defines the default rule set for type checking.
/// </summary>
public string typeCheckingMode;
public string typeCheckingMode { get; set; }

/// <summary>
/// Use library implementations to extract type information when type stub is not present.
/// </summary>
public bool? useLibraryCodeForTypes;
public bool? useLibraryCodeForTypes { get; set; }

/// <summary>
/// Additional import search resolution paths.
/// </summary>
public string[] extraPaths;
public string[] extraPaths { get; set; }

/// <summary>
/// Automatically add brackets for functions.
/// </summary>
public bool completeFunctionParens;
public bool completeFunctionParens { get; set; }

/// <summary>
/// Offer auto-import completions.
/// </summary>
public bool autoImportCompletions;
public bool autoImportCompletions { get; set; }

/// <summary>
/// Index installed third party libraries and user files for language features such as auto-import, add import, workspace symbols and etc.
/// </summary>
public bool? indexing;
public bool? indexing { get; set; }

/// <summary>
/// Allow using '.', '(' as commit characters when applicable.
/// </summary>
public bool? extraCommitChars;
public bool? extraCommitChars { get; set; }

public PythonAnalysisInlayHintsSettings inlayHints;
public PythonAnalysisInlayHintsSettings inlayHints { get; set; }

public string importFormat;
public string importFormat { get; set; }

/// <summary>
/// Tokens that identify comments that should show up in the task list pane
/// </summary>
public TaskListToken[] taskListTokens;
public TaskListToken[] taskListTokens { get; set; }

public class PythonAnalysisInlayHintsSettings {

/// <summary>
/// Enable/disable inlay hints for variable types:\n```python\nfoo ' :list[str] ' = [\"a\"]\n \n```\n
/// </summary>
public bool variableTypes;
public bool variableTypes { get; set; }

/// <summary>
/// Enable/disable inlay hints for function return types:\n```python\ndef foo(x:int) ' -> int ':\n\treturn x\n```\n"
/// </summary>
public bool functionReturnTypes;
public bool functionReturnTypes { get; set; }
}

public class TaskListToken {

/// <summary>
/// The text of the token.
/// </summary>
public string text;
public string text { get; set; }

/// <summary>
/// The priority of the token.
/// This comes from the CommentTaskPriority enum in Microsoft.VisualStudio.Shell
/// </summary>
public string priority;
public string priority { get; set; }
}

}
/// <summary>
/// Analysis settings.
/// </summary>
public PythonAnalysisSettings analysis;
public PythonAnalysisSettings analysis { get; set; }

/// <summary>
/// Path to Python, you can use a custom version of Python.
/// </summary>
public string pythonPath;
public string pythonPath { get; set; }

/// <summary>
/// Path to folder with a list of Virtual Environments.
/// </summary>
public string venvPath;
public string venvPath { get; set; }
}
/// <summary>
/// Python section.
/// </summary>
public PythonSettings python;
public PythonSettings python { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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() }
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -95,43 +96,39 @@ public PythonLanguageClientCustomTarget(IServiceProvider site, JoinableTaskConte
/// </summary>
internal event AsyncEventHandler<WorkspaceFoldersArgs> 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<PylanceTelemetryEvent>(arg);
} catch (JsonException) {
return;
}

Trace.WriteLine(telemetry.ToString());
try {
var te = telemetry.ToObject<PylanceTelemetryEvent>();
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();

Expand All @@ -143,43 +140,53 @@ 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
var statusBar = _site.GetService(typeof(SVsStatusbar)) as IVsStatusbar;
statusBar?.SetText("Python analysis done");
}

[JsonRpcMethod("client/registerCapability")]
public void OnRegisterCapability(JToken arg) {
var regParams = arg.ToObject<VisualStudio.LanguageServer.Protocol.RegistrationParams>();
[JsonRpcMethod("client/registerCapability", UseSingleObjectParameterDeserialization = true)]
public void OnRegisterCapability(object arg) {
var regParams = Deserialize<VisualStudio.LanguageServer.Protocol.RegistrationParams>(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<DidChangeWatchedFilesRegistrationOptions>();
if (options != null) {
_joinableTaskContext.Factory.RunAsync(async () => this.WatchedFilesRegistered.Invoke(this, options));
}
}
}
Comment on lines +152 to 168

[JsonRpcMethod("workspace/configuration")]
public async Task<object> OnWorkspaceConfiguration(JToken arg) {
try {
var reqParams = arg.ToObject<WorkspaceConfiguration.ConfigurationParams>();
if (this.WorkspaceConfiguration != null && reqParams != null) {
var eventArgs = new ConfigurationArgs { requestParams = reqParams, requestResult = null };
await this.WorkspaceConfiguration.InvokeAsync(this, eventArgs);
return eventArgs.requestResult;
}
return null;
} catch {
[JsonRpcMethod("workspace/configuration", UseSingleObjectParameterDeserialization = true)]
public async Task<object> OnWorkspaceConfiguration(object arg) {
var reqParams = Deserialize<WorkspaceConfiguration.ConfigurationParams>(arg);
if (this.WorkspaceConfiguration != null && reqParams != null) {
var eventArgs = new ConfigurationArgs { requestParams = reqParams, requestResult = null };
await this.WorkspaceConfiguration.InvokeAsync(this, eventArgs);
return eventArgs.requestResult;
}
return null;
}

private static T Deserialize<T>(object arg) where T : class {
if (arg == null) {
return null;
}

// Dev18 supplies System.Text.Json values; older formatters supply JToken.
return arg is JToken token
? token.ToObject<T>()
: JsonConvert.DeserializeObject<T>(arg.ToString());
}
Comment on lines +181 to 190

[JsonRpcMethod("workspace/workspaceFolders")]
Expand Down
Loading