Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 2 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
8 changes: 5 additions & 3 deletions src/LanguageServer/Impl/Completion/CompletionItemSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,23 @@ internal class CompletionItemSource {
public static readonly CompletionItem Star = CreateCompletionItem("*", CompletionItemKind.Keyword);

private readonly IDocumentationSource _docSource;
private readonly ServerSettings.PythonCompletionOptions _options;

public CompletionItemSource(IDocumentationSource docSource, ServerSettings.PythonCompletionOptions options) {
_docSource = docSource;
_options = options;
Options = options;
}

public ServerSettings.PythonCompletionOptions Options { get; set; }

public CompletionItem CreateCompletionItem(string text, IMember member, IPythonType self = null, string label = null)
=> CreateCompletionItem(text, ToCompletionItemKind(member?.MemberType ?? PythonMemberType.Class), member, self, label);

public CompletionItemEx CreateCompletionItem(string text, CompletionItemKind kind, IMember member, IPythonType self = null, string label = null) {
var t = member?.GetPythonType();
var docFormat = _docSource.DocumentationFormat;

if (_options.addBrackets && (kind == CompletionItemKind.Constructor || kind == CompletionItemKind.Function || kind == CompletionItemKind.Method)) {
if (Options.addBrackets && (kind == CompletionItemKind.Constructor || kind == CompletionItemKind.Function || kind == CompletionItemKind.Method)) {
label = text;
text += "($0)";
docFormat = InsertTextFormat.Snippet;
}
Expand Down
5 changes: 5 additions & 0 deletions src/LanguageServer/Impl/Completion/CompletionSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public CompletionSource(IDocumentationSource docSource, ServerSettings.PythonCom
_itemSource = new CompletionItemSource(docSource, completionSettings);
}

public ServerSettings.PythonCompletionOptions Options {
get => _itemSource.Options;
set => _itemSource.Options = value;
}

public CompletionResult GetCompletions(IDocumentAnalysis analysis, SourceLocation location) {
if(analysis.Document.ModuleType != ModuleType.User) {
return CompletionResult.Empty;
Expand Down
1 change: 1 addition & 0 deletions src/LanguageServer/Impl/Completion/ExpressionCompletion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ private static IEnumerable<CompletionItem> GetClassItems(IPythonClassType cls, E
if (m is IVariable v && v.Source != VariableSource.Declaration) {
continue;
}

// If this is class member completion, unmangle private member names.
var unmangledName = cls.UnmangleMemberName(t);
if (!string.IsNullOrEmpty(unmangledName)) {
Expand Down
1 change: 1 addition & 0 deletions src/LanguageServer/Impl/Implementation/Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ private bool HandleConfigurationChanges(ServerSettings newSettings) {
Settings = newSettings;

_symbolHierarchyMaxSymbols = Settings.analysis.symbolsHierarchyMaxSymbols;
_completionSource.Options = Settings.completion;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

PythonCompletionOptions is a class. Do we need to check Settings.completion for null here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It is poopulated in

        [JsonRpcMethod("workspace/didChangeConfiguration")]
        public async Task DidChangeConfiguration(JToken token, CancellationToken cancellationToken) {
            using (await _prioritizer.ConfigurationPriorityAsync(cancellationToken)) {
                var settings = new LanguageServerSettings();

                var rootSection = token["settings"];
                var pythonSection = rootSection?["python"];
                if (pythonSection == null) {
                    return;
                }

                var autoComplete = pythonSection["autoComplete"];
                settings.completion.showAdvancedMembers = GetSetting(autoComplete, "showAdvancedMembers", true);
                settings.completion.addBrackets = GetSetting(autoComplete, "addBrackets", false);

and GetSetting handles nulls/missing settings.


if (oldSettings == null) {
return true;
Expand Down
21 changes: 21 additions & 0 deletions src/LanguageServer/Test/CompletionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
using Microsoft.Python.Parsing;
using Microsoft.Python.Parsing.Tests;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NSubstitute;
Comment thread
MikhailArkhipov marked this conversation as resolved.
Outdated
using TestUtilities;

namespace Microsoft.Python.LanguageServer.Tests {
Expand Down Expand Up @@ -1194,5 +1195,25 @@ def test(x: Foo = func()):
var comps = cs.GetCompletions(analysis, new SourceLocation(13, 7));
comps.Should().HaveLabels("name", "z");
}

[TestMethod, Priority(0)]
public async Task AddBrackets() {
const string code = @"prin";
var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X);

ServerSettings.completion.addBrackets = true;
var cs = new CompletionSource(new PlainTextDocumentationSource(), ServerSettings.completion);

var comps = cs.GetCompletions(analysis, new SourceLocation(1, 5));
var print = comps.Completions.FirstOrDefault(x => x.label == "print");
print.Should().NotBeNull();
print.insertText.Should().Be("print($0)");

cs.Options.addBrackets = false;
comps = cs.GetCompletions(analysis, new SourceLocation(1, 5));
print = comps.Completions.FirstOrDefault(x => x.label == "print");
print.Should().NotBeNull();
print.insertText.Should().Be("print");
}
}
}