Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6bcc0f2

Browse files
authored
Add __init__ parameters to class completion documentation (microsoft#1704)
* Add __init__ parameters to class completion documentation * Remove class keyword prefix * Restore class keyword in hovers only
1 parent 1ee222e commit 6bcc0f2

File tree

9 files changed

+59
-22
lines changed

9 files changed

+59
-22
lines changed

src/Analysis/Ast/Impl/Caching/StubCache.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
namespace Microsoft.Python.Analysis.Caching {
2525
internal sealed class StubCache : IStubCache {
26-
private const int _stubCacheFormatVersion = 3;
26+
private const int _stubCacheFormatVersion = 4;
2727

2828
private readonly IFileSystem _fs;
2929
private readonly ILogger _log;

src/Analysis/Ast/Impl/scrape_module.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ def __init__(self,
309309
# We have a property
310310
self.decorators = '@property',
311311
self.fullsig = self.name + "(" + ", ".join(self._defaults) + ")"
312+
313+
if scope_alias == "__Object__" and name == "__init__":
314+
self.fullsig = "__init__(self)"
312315

313316
self.fullsig = (
314317
self.fullsig or

src/LanguageServer/Impl/Completion/CompletionItemSource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public CompletionItemEx CreateCompletionItem(string text, CompletionItemKind kin
5656
// Place regular items first, advanced entries last
5757
sortText = char.IsLetter(text, 0) ? "1" : "2",
5858
kind = kind,
59-
documentation = !t.IsUnknown() ? _docSource.GetHover(label ?? text, member, self) : null,
59+
documentation = !t.IsUnknown() ? _docSource.GetHover(label ?? text, member, self, true) : null,
6060
// Custom fields used by the LS extensions that may modify
6161
// the completion list. Not passed to the client.
6262
Member = member,

src/LanguageServer/Impl/Definitions/IDocumentationSource.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
namespace Microsoft.Python.LanguageServer {
2121
public interface IDocumentationSource {
2222
InsertTextFormat DocumentationFormat { get; }
23-
MarkupContent GetHover(string name, IMember member, IPythonType self = null);
24-
string GetSignatureString(IPythonFunctionType ft, IPythonType self, out (IndexSpan, IParameterInfo)[] parameterSpans, int overloadIndex = 0, string name = null);
23+
MarkupContent GetHover(string name, IMember member, IPythonType self = null, bool includeClassInit = false);
24+
string GetSignatureString(IPythonFunctionType ft, IPythonType self, out (IndexSpan, IParameterInfo)[] parameterSpans, int overloadIndex = 0, string name = null, bool noReturn = false);
2525
MarkupContent FormatParameterDocumentation(IParameterInfo parameter);
2626
MarkupContent FormatDocumentation(string documentation);
2727
}

src/LanguageServer/Impl/Sources/DocumentationSource.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
namespace Microsoft.Python.LanguageServer.Sources {
2525
internal abstract class DocumentationSource {
26-
public string GetSignatureString(IPythonFunctionType ft, IPythonType self, out (IndexSpan, IParameterInfo)[] parameterSpans, int overloadIndex = 0, string funcName = null) {
26+
public string GetSignatureString(IPythonFunctionType ft, IPythonType self, out (IndexSpan, IParameterInfo)[] parameterSpans, int overloadIndex = 0, string funcName = null, bool noReturn = false) {
2727
funcName = funcName ?? ft.Name;
2828
var o = ft.Overloads[overloadIndex];
2929

@@ -82,10 +82,12 @@ public string GetSignatureString(IPythonFunctionType ft, IPythonType self, out (
8282

8383
builder.Append(')');
8484

85-
var returnDoc = o.GetReturnDocumentation(self);
86-
if (!string.IsNullOrWhiteSpace(returnDoc)) {
87-
builder.Append(" -> ");
88-
builder.Append(returnDoc);
85+
if (!noReturn) {
86+
var returnDoc = o.GetReturnDocumentation(self);
87+
if (!string.IsNullOrWhiteSpace(returnDoc)) {
88+
builder.Append(" -> ");
89+
builder.Append(returnDoc);
90+
}
8991
}
9092

9193
parameterSpans = spans.ToArray();

src/LanguageServer/Impl/Sources/HoverSource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private bool IsInvalidClassMember(IVariable v, ScopeStatement scope, int hoverPo
165165
}
166166
switch (v.Value) {
167167
case IPythonClassType cls when cls.ClassDefinition == scope:
168-
return hoverPosition > cls.ClassDefinition.HeaderIndex;
168+
return hoverPosition > cls.ClassDefinition.HeaderIndex;
169169
case IPythonFunctionType ft when ft.FunctionDefinition == scope:
170170
return hoverPosition > ft.FunctionDefinition.HeaderIndex;
171171
case IPythonPropertyType prop when prop.FunctionDefinition == scope:

src/LanguageServer/Impl/Sources/MarkdownDocumentationSource.cs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace Microsoft.Python.LanguageServer.Sources {
2323
internal sealed class MarkdownDocumentationSource : DocumentationSource, IDocumentationSource {
2424
public InsertTextFormat DocumentationFormat => InsertTextFormat.PlainText;
2525

26-
public MarkupContent GetHover(string name, IMember member, IPythonType self) {
26+
public MarkupContent GetHover(string name, IMember member, IPythonType self, bool includeClassInit = false) {
2727
// We need to tell between instance and type.
2828
var type = member.GetPythonType();
2929
if (type.IsUnknown()) {
@@ -41,16 +41,30 @@ public MarkupContent GetHover(string name, IMember member, IPythonType self) {
4141
var typeDoc = !string.IsNullOrEmpty(type.Documentation) ? $"\n---\n{type.MarkdownDoc()}" : string.Empty;
4242
switch (type) {
4343
case IPythonPropertyType prop:
44-
text = GetPropertyHoverString(prop);
44+
text = GetPropertyString(prop);
4545
break;
4646

4747
case IPythonFunctionType ft:
48-
text = GetFunctionHoverString(ft, self);
48+
text = GetFunctionString(ft, self);
4949
break;
5050

5151
case IPythonClassType cls:
5252
var clsDoc = !string.IsNullOrEmpty(cls.Documentation) ? $"\n---\n{cls.MarkdownDoc()}" : string.Empty;
53-
text = $"```\nclass {cls.Name}\n```{clsDoc}";
53+
54+
string className;
55+
var sig = string.Empty;
56+
57+
if (includeClassInit) {
58+
className = cls.Name;
59+
var init = cls.GetMember<IPythonFunctionType>("__init__");
60+
if (init != null) {
61+
sig = GetSignatureString(init, null, out var _, 0, "", true);
62+
}
63+
} else {
64+
className = "class " + cls.Name;
65+
}
66+
67+
text = $"```\n{className}{sig}\n```{clsDoc}";
5468
break;
5569

5670
case IPythonModule mod:
@@ -67,7 +81,7 @@ public MarkupContent GetHover(string name, IMember member, IPythonType self) {
6781
};
6882
}
6983

70-
public MarkupContent FormatDocumentation(string documentation)
84+
public MarkupContent FormatDocumentation(string documentation)
7185
=> new MarkupContent { kind = MarkupKind.Markdown, value = DocstringConverter.ToMarkdown(documentation) };
7286

7387
public MarkupContent FormatParameterDocumentation(IParameterInfo parameter) {
@@ -79,13 +93,13 @@ public MarkupContent FormatParameterDocumentation(IParameterInfo parameter) {
7993
return new MarkupContent { kind = MarkupKind.Markdown, value = text };
8094
}
8195

82-
private string GetPropertyHoverString(IPythonPropertyType prop, int overloadIndex = 0) {
96+
private string GetPropertyString(IPythonPropertyType prop) {
8397
var decTypeString = prop.DeclaringType != null ? $"{prop.DeclaringType.Name}." : string.Empty;
8498
var propDoc = !string.IsNullOrEmpty(prop.Documentation) ? $"\n---\n{prop.MarkdownDoc()}" : string.Empty;
8599
return $"```\n{decTypeString}\n```{propDoc}";
86100
}
87101

88-
private string GetFunctionHoverString(IPythonFunctionType ft, IPythonType self, int overloadIndex = 0) {
102+
private string GetFunctionString(IPythonFunctionType ft, IPythonType self, int overloadIndex = 0) {
89103
var sigString = GetSignatureString(ft, self, out _, overloadIndex);
90104
var decTypeString = ft.DeclaringType != null ? $"{ft.DeclaringType.Name}." : string.Empty;
91105
var funcDoc = !string.IsNullOrEmpty(ft.Documentation) ? $"\n---\n{ft.MarkdownDoc()}" : string.Empty;

src/LanguageServer/Impl/Sources/PlainTextDocumentationSource.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace Microsoft.Python.LanguageServer.Sources {
2323
internal sealed class PlainTextDocumentationSource : DocumentationSource, IDocumentationSource {
2424
public InsertTextFormat DocumentationFormat => InsertTextFormat.PlainText;
2525

26-
public MarkupContent GetHover(string name, IMember member, IPythonType self) {
26+
public MarkupContent GetHover(string name, IMember member, IPythonType self, bool includeClassInit = false) {
2727
// We need to tell between instance and type.
2828
var type = member.GetPythonType();
2929
if (type.IsUnknown()) {
@@ -50,7 +50,21 @@ public MarkupContent GetHover(string name, IMember member, IPythonType self) {
5050

5151
case IPythonClassType cls:
5252
var clsDoc = !string.IsNullOrEmpty(cls.Documentation) ? $"\n\n{cls.PlaintextDoc()}" : string.Empty;
53-
text = $"class {cls.Name}{clsDoc}";
53+
54+
string className;
55+
var sig = string.Empty;
56+
57+
if (includeClassInit) {
58+
className = cls.Name;
59+
var init = cls.GetMember<IPythonFunctionType>("__init__");
60+
if (init != null) {
61+
sig = GetSignatureString(init, null, out var _, 0, "", true);
62+
}
63+
} else {
64+
className = "class " + cls.Name;
65+
}
66+
67+
text = $"{className}{sig}{clsDoc}";
5468
break;
5569

5670
case IPythonModule mod:
@@ -67,7 +81,7 @@ public MarkupContent GetHover(string name, IMember member, IPythonType self) {
6781
};
6882
}
6983

70-
public MarkupContent FormatDocumentation(string documentation)
84+
public MarkupContent FormatDocumentation(string documentation)
7185
=> new MarkupContent { kind = MarkupKind.PlainText, value = documentation };
7286

7387
public MarkupContent FormatParameterDocumentation(IParameterInfo parameter) {

src/LanguageServer/Test/CompletionTests.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,16 @@ class oar(list):
127127
[TestMethod]
128128
public async Task OverrideInit3X() {
129129
const string code = @"
130-
class Test():
130+
class A:
131+
def __init__(self, *args, **kwargs):
132+
pass
133+
134+
class Test(A):
131135
def __
132136
";
133137
var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X);
134138
var cs = new CompletionSource(new PlainTextDocumentationSource(), ServerSettings.completion, Services);
135-
var result = cs.GetCompletions(analysis, new SourceLocation(3, 10));
139+
var result = cs.GetCompletions(analysis, new SourceLocation(7, 10));
136140

137141
result.Should().HaveItem("__init__")
138142
.Which.Should().HaveInsertText($"__init__(self, *args, **kwargs):{Environment.NewLine} super().__init__(*args, **kwargs)")

0 commit comments

Comments
 (0)