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 Python/Product/PythonTools/PythonTools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@
<Compile Include="PythonTools\Project\DeprecatedReferenceNode.cs" />
<Compile Include="PythonTools\PythonFeedbackDiagnosticFileProvider.cs" />
<Compile Include="PythonTools\LanguageServerClient\PythonLanguageClient.cs" />
<Compile Include="PythonTools\LanguageServerClient\PythonSignatureHelpMiddleLayer.cs" />
<Compile Include="PythonTools\LanguageServerClient\PythonLanguageClientCustomTarget.cs" />
<Compile Include="PythonTools\Intellisense\PythonMemberTypeExtensions.cs" />
<Compile Include="PythonTools\Editor\TokenCache.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ internal class LanguagePreferences : IVsTextManagerEvents2, IDisposable {
private readonly IVsTextManager _textMgr;
private readonly uint _cookie;
private LANGPREFERENCES _preferences;
private volatile bool _autoListParams;
private bool _isDisposed;

public LanguagePreferences(IServiceProvider site, Guid languageGuid) {
Expand All @@ -41,6 +42,7 @@ public LanguagePreferences(IServiceProvider site, Guid languageGuid) {
langPrefs[0].fLineNumbers = 1;
ErrorHandler.ThrowOnFailure(_textMgr.SetUserPreferences(null, null, langPrefs, null));
_preferences = langPrefs[0];
_autoListParams = _preferences.fAutoListParams != 0;

var guid = typeof(IVsTextManagerEvents2).GUID;
IConnectionPoint connectionPoint = null;
Expand Down Expand Up @@ -103,6 +105,7 @@ public int OnUserPreferencesChanged2(VIEWPREFERENCES2[] viewPrefs, FRAMEPREFEREN
_preferences.IndentStyle = langPrefs[0].IndentStyle;
_preferences.fAutoListMembers = langPrefs[0].fAutoListMembers;
_preferences.fAutoListParams = langPrefs[0].fAutoListParams;
_autoListParams = langPrefs[0].fAutoListParams != 0;
_preferences.fHideAdvancedAutoListMembers = langPrefs[0].fHideAdvancedAutoListMembers;
_preferences.fDropdownBar = langPrefs[0].fDropdownBar;
_preferences.fLineNumbers = langPrefs[0].fLineNumbers;
Expand All @@ -122,7 +125,7 @@ public int OnUserPreferencesChanged2(VIEWPREFERENCES2[] viewPrefs, FRAMEPREFEREN

public bool AutoListMembers => _preferences.fAutoListMembers != 0;

public bool AutoListParams => _preferences.fAutoListParams != 0;
public bool AutoListParams => _autoListParams;

#endregion
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ internal sealed class PythonLanguageClient : ILanguageClient, ILanguageClientCus
private List<WorkspaceFolder> _workspaceFolders = new List<WorkspaceFolder>();
private FileWatcher.Listener _fileListener;
private static TaskCompletionSource<int> _readyTcs = new TaskCompletionSource<int>();
private readonly PythonSignatureHelpMiddleLayer _signatureHelpMiddleLayer;
private bool _loaded = false;
// Set by the dispose action before any other cleanup; consulted by
// TriggerWorkspaceUpdateConfig and GetSettings so teardown cannot
Expand All @@ -106,6 +107,7 @@ internal sealed class PythonLanguageClient : ILanguageClient, ILanguageClientCus

public PythonLanguageClient() {
_disposables = new Common.Core.Disposables.DisposableBag(GetType().Name);
_signatureHelpMiddleLayer = new PythonSignatureHelpMiddleLayer();
}

public string ContentTypeName => PythonCoreConstants.ContentType;
Expand All @@ -118,7 +120,7 @@ public PythonLanguageClient() {
public object InitializationOptions { get; private set; }

public IEnumerable<string> FilesToWatch => null;
public object MiddleLayer => null;
public object MiddleLayer => _signatureHelpMiddleLayer;
public object CustomMessageTarget { get; private set; }
public bool IsInitialized { get; private set; }
public bool Loaded => this._loaded;
Expand Down Expand Up @@ -187,7 +189,8 @@ public async Task OnLoadedAsync() {
await JoinableTaskContext.Factory.SwitchToMainThreadAsync();
// Force the package to load, since this is a MEF component,
// there is no guarantee it has been loaded.
Site.GetPythonToolsService();
var pyService = Site.GetPythonToolsService();
_signatureHelpMiddleLayer.Initialize(await pyService.GetLangPrefsAsync());

// Indicate to python tools service we've loaded.
_loaded = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.PythonTools.Editor;
using Microsoft.VisualStudio.LanguageServer.Client;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Newtonsoft.Json.Linq;

namespace Microsoft.PythonTools.LanguageServerClient {
#if !DEV18_OR_LATER
#pragma warning disable CS0618
#endif
internal sealed class PythonSignatureHelpMiddleLayer :
#if DEV18_OR_LATER
ILanguageClientMiddleLayer2<JToken> {
#else
ILanguageClientMiddleLayer {
#endif
private LanguagePreferences _languagePreferences;

internal void Initialize(LanguagePreferences languagePreferences) {
Volatile.Write(ref _languagePreferences, languagePreferences ?? throw new ArgumentNullException(nameof(languagePreferences)));
}

public bool CanHandle(string methodName) =>
string.Equals(methodName, Methods.TextDocumentSignatureHelpName, StringComparison.Ordinal);

public Task<JToken> HandleRequestAsync(string methodName, JToken methodParam, Func<JToken, Task<JToken>> sendRequest) {
if (ShouldSuppressAutomaticSignatureHelp(methodParam)) {
return Task.FromResult<JToken>(JValue.CreateNull());
}

return sendRequest(methodParam);
}

public Task HandleNotificationAsync(string methodName, JToken methodParam, Func<JToken, Task> sendNotification) =>
sendNotification(methodParam);

private bool ShouldSuppressAutomaticSignatureHelp(JToken methodParam) {
var languagePreferences = Volatile.Read(ref _languagePreferences);
if (languagePreferences == null || languagePreferences.AutoListParams) {
return false;
}

if (!(methodParam is JObject request) ||
!(request["context"] is JObject context) ||
context["triggerKind"]?.Type != JTokenType.Integer ||
context["isRetrigger"]?.Type != JTokenType.Boolean ||
context["isRetrigger"].Value<bool>() ||
(context["activeSignatureHelp"] != null && context["activeSignatureHelp"].Type != JTokenType.Null)) {
return false;
}

if (!int.TryParse(
context["triggerKind"].ToString(),
NumberStyles.Integer,
CultureInfo.InvariantCulture,
out var triggerKind)) {
return false;
}

return triggerKind == (int)SignatureHelpTriggerKind.TriggerCharacter ||
triggerKind == (int)SignatureHelpTriggerKind.ContentChange;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add focused regression coverage for the signature-help suppression matrix. This predicate has several fail-open branches, and tests should distinguish disabled preferences for new automatic TriggerCharacter/ContentChange requests from explicit invocations, retriggers, active sessions, malformed contexts, and unavailable preferences.

}
}
#if !DEV18_OR_LATER
#pragma warning restore CS0618
#endif
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ public PythonAdvancedEditorOptionsControl() {
InitializeComponent();
}

internal void SyncControlWithPageSettings(PythonToolsService pyService) {
internal bool ParameterInformation => _parameterInformation.Checked;

internal void SyncControlWithPageSettings(PythonToolsService pyService, bool parameterInformation) {
_autoImportCompletions.Checked = pyService.AdvancedEditorOptions.AutoImportCompletions;
_completeFunctionParens.Checked = pyService.AdvancedEditorOptions.CompleteFunctionParens;
_parameterInformation.Checked = parameterInformation;
}

internal void SyncPageWithControlSettings(PythonToolsService pyService) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,39 @@
<data name="&gt;&gt;_autoImportCompletions.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="_parameterInformation.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Left</value>
</data>
<data name="_parameterInformation.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="_parameterInformation.Location" type="System.Drawing.Point, System.Drawing">
<value>11, 88</value>
</data>
<data name="_parameterInformation.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>11, 6, 11, 6</value>
</data>
<data name="_parameterInformation.Size" type="System.Drawing.Size, System.Drawing">
<value>237, 29</value>
</data>
<data name="_parameterInformation.TabIndex" type="System.Int32, mscorlib">
<value>3</value>
</data>
<data name="_parameterInformation.Text" xml:space="preserve">
<value>&amp;Parameter information</value>
</data>
<data name="&gt;&gt;_parameterInformation.Name" xml:space="preserve">
<value>_parameterInformation</value>
</data>
<data name="&gt;&gt;_parameterInformation.Type" xml:space="preserve">
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;_parameterInformation.Parent" xml:space="preserve">
<value>tableLayoutPanel1</value>
</data>
<data name="&gt;&gt;_parameterInformation.ZOrder" xml:space="preserve">
<value>2</value>
</data>
<data name="tableLayoutPanel1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
Expand All @@ -211,7 +244,7 @@
<value>6, 6, 6, 6</value>
</data>
<data name="tableLayoutPanel1.RowCount" type="System.Int32, mscorlib">
<value>3</value>
<value>4</value>
</data>
<data name="tableLayoutPanel1.Size" type="System.Drawing.Size, System.Drawing">
<value>699, 510</value>
Expand All @@ -232,7 +265,7 @@
<value>0</value>
</data>
<data name="tableLayoutPanel1.LayoutSettings" type="System.Windows.Forms.TableLayoutSettings, System.Windows.Forms">
<value>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="_completeFunctionParens" Row="1" RowSpan="1" Column="0" ColumnSpan="2" /&gt;&lt;Control Name="_autoImportCompletions" Row="0" RowSpan="1" Column="0" ColumnSpan="2" /&gt;&lt;/Controls&gt;&lt;Columns Styles="Percent,100,Absolute,545" /&gt;&lt;Rows Styles="AutoSize,0,AutoSize,0,Absolute,20" /&gt;&lt;/TableLayoutSettings&gt;</value>
<value>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="_completeFunctionParens" Row="1" RowSpan="1" Column="0" ColumnSpan="2" /&gt;&lt;Control Name="_autoImportCompletions" Row="0" RowSpan="1" Column="0" ColumnSpan="2" /&gt;&lt;Control Name="_parameterInformation" Row="2" RowSpan="1" Column="0" ColumnSpan="2" /&gt;&lt;/Controls&gt;&lt;Columns Styles="Percent,100,Absolute,545" /&gt;&lt;Rows Styles="AutoSize,0,AutoSize,0,AutoSize,0,Absolute,20" /&gt;&lt;/TableLayoutSettings&gt;</value>
</data>
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace Microsoft.PythonTools.Options {
[ComVisible(true)]
public class PythonAdvancedEditorOptionsPage : PythonDialogPage {
private PythonAdvancedEditorOptionsControl _window;
private bool _parameterInformation = true;

// replace the default UI of the dialog page w/ our own UI.
protected override IWin32Window Window {
Expand All @@ -38,18 +39,33 @@ protected override IWin32Window Window {
/// a call to <see cref="SaveSettingsToStorage"/> to commit the new
/// values.
/// </summary>
public override void ResetSettings() => PyService.AdvancedEditorOptions.Reset();
public override void ResetSettings() {
PyService.AdvancedEditorOptions.Reset();
_parameterInformation = true;
_window?.SyncControlWithPageSettings(PyService, _parameterInformation);
}

public override void LoadSettingsFromStorage() {
PyService.AdvancedEditorOptions.Load();
_parameterInformation = PyService.GetLanguagePreferences().fAutoListParams != 0;
// Synchronize UI with backing properties.
_window?.SyncControlWithPageSettings(PyService);
_window?.SyncControlWithPageSettings(PyService, _parameterInformation);
}

public override void SaveSettingsToStorage() {
// Synchronize backing properties with UI.
_window?.SyncPageWithControlSettings(PyService);
if (_window != null) {
_parameterInformation = _window.ParameterInformation;
}
PyService.AdvancedEditorOptions.Save();

var languagePreferences = PyService.GetLanguagePreferences();
var autoListParams = _parameterInformation ? 1u : 0u;
if (languagePreferences.fAutoListParams != autoListParams) {
languagePreferences.fAutoListParams = autoListParams;
PyService.SetLanguagePreferences(languagePreferences);
}
}
}
}