diff --git a/src/Analysis/Ast/Impl/Types/PythonClassType.cs b/src/Analysis/Ast/Impl/Types/PythonClassType.cs index 708f254d4..8f9712388 100644 --- a/src/Analysis/Ast/Impl/Types/PythonClassType.cs +++ b/src/Analysis/Ast/Impl/Types/PythonClassType.cs @@ -79,10 +79,8 @@ public override IEnumerable GetMemberNames() { } public override IMember GetMember(string name) { - IMember member; - lock (_membersLock) { - if (Members.TryGetValue(name, out member)) { + if (Members.TryGetValue(name, out var member)) { return member; } } @@ -101,12 +99,7 @@ public override IMember GetMember(string name) { using (_memberGuard.Push(this, out var reentered)) { if (!reentered) { - foreach (var m in Mro.Reverse()) { - if (m == this) { - return member; - } - member = member ?? m.GetMember(name); - } + return Mro.Skip(1).Select(c => c.GetMember(name)).ExcludeDefault().FirstOrDefault(); } return null; } @@ -348,7 +341,7 @@ private IEnumerable DisambiguateBases(IEnumerable base // Get locally declared variable, make sure it is a declaration // and that it declared a class. var lv = scope.Variables[b.Name]; - if (lv.Source != VariableSource.Import && lv.Value is IPythonClassType cls && cls.IsDeclaredAfterOrAt(this.Location)) { + if (lv.Source != VariableSource.Import && lv.Value is IPythonClassType cls && cls.IsDeclaredAfterOrAt(Location)) { // There is a declaration with the same name, but it appears later in the module. Use the import. if (!importedType.IsUnknown()) { newBases.Add(importedType); diff --git a/src/Analysis/Ast/Test/ClassesTests.cs b/src/Analysis/Ast/Test/ClassesTests.cs index 07cddf25c..d19407e24 100644 --- a/src/Analysis/Ast/Test/ClassesTests.cs +++ b/src/Analysis/Ast/Test/ClassesTests.cs @@ -270,6 +270,23 @@ def __init__(self, value): .Which.Should().HaveParameterAt(0).Which.Should().HaveName("self").And.HaveType("X"); } + [TestMethod, Priority(0)] + public async Task ClassBaseInit() { + const string code = @" +class A: + def __init__(self, value): + self.value = value + +class B(A): ... +"; + var analysis = await GetAnalysisAsync(code); + analysis.Should().HaveClass("B") + .Which.Should().HaveMethod("__init__") + .Which.Should().HaveSingleOverload() + .Which.Should().HaveParameterAt(1) + .Which.Name.Should().Be("value"); + } + [TestMethod, Priority(0)] public async Task ClassBase2X() { const string code = @" diff --git a/src/LanguageServer/Impl/Sources/MarkdownDocumentationSource.cs b/src/LanguageServer/Impl/Sources/MarkdownDocumentationSource.cs index 173aec8b0..63a9a7e56 100644 --- a/src/LanguageServer/Impl/Sources/MarkdownDocumentationSource.cs +++ b/src/LanguageServer/Impl/Sources/MarkdownDocumentationSource.cs @@ -13,6 +13,7 @@ // See the Apache Version 2.0 License for specific language governing // permissions and limitations under the License. +using System.Linq; using Microsoft.Python.Analysis; using Microsoft.Python.Analysis.Types; using Microsoft.Python.Analysis.Values; @@ -56,7 +57,7 @@ public MarkupContent GetHover(string name, IMember member, IPythonType self, boo if (includeClassInit) { className = cls.Name; - var init = cls.GetMember("__init__"); + var init = cls.TryGetFunctionType(); if (init != null) { sig = GetSignatureString(init, null, out var _, 0, "", true); }