diff --git a/src/Analysis/Ast/Impl/Analyzer/Symbols/ClassEvaluator.cs b/src/Analysis/Ast/Impl/Analyzer/Symbols/ClassEvaluator.cs index b095cf4a8..72ea6982e 100644 --- a/src/Analysis/Ast/Impl/Analyzer/Symbols/ClassEvaluator.cs +++ b/src/Analysis/Ast/Impl/Analyzer/Symbols/ClassEvaluator.cs @@ -18,6 +18,8 @@ using System.Linq; using Microsoft.Python.Analysis.Analyzer.Evaluation; using Microsoft.Python.Analysis.Diagnostics; +using Microsoft.Python.Analysis.Modules; +using Microsoft.Python.Analysis.Specializations.Typing; using Microsoft.Python.Analysis.Types; using Microsoft.Python.Analysis.Values; using Microsoft.Python.Core; @@ -117,17 +119,26 @@ private IEnumerable ProcessBases(Scope outerScope) { var expr = a.Expression; var m = Eval.GetValueFromExpression(expr); - switch (m?.MemberType) { - case PythonMemberType.Method: - case PythonMemberType.Function: - case PythonMemberType.Property: - case PythonMemberType.Instance: - case PythonMemberType.Variable when m is IPythonConstant: - // all invalid types to inherit from - ReportInvalidBase(a.ToCodeString(Eval.Ast, CodeFormattingOptions.Traditional)); + switch (m) { + // Allow any members from typing module + // TODO handle typing module specialization better: https://github.com/microsoft/python-language-server/issues/1367 + case ILocatedMember l when l.DeclaringModule is TypingModule: + TryAddBase(bases, a); break; default: - TryAddBase(bases, a); + switch (m?.MemberType) { + case PythonMemberType.Method: + case PythonMemberType.Function: + case PythonMemberType.Property: + case PythonMemberType.Instance: + case PythonMemberType.Variable when m is IPythonConstant: + // all invalid types to inherit from + ReportInvalidBase(a.ToCodeString(Eval.Ast, CodeFormattingOptions.Traditional)); + break; + default: + TryAddBase(bases, a); + break; + } break; } } diff --git a/src/Analysis/Ast/Test/LintInheritNonClassTests.cs b/src/Analysis/Ast/Test/LintInheritNonClassTests.cs index 3df2457e0..0399b2eba 100644 --- a/src/Analysis/Ast/Test/LintInheritNonClassTests.cs +++ b/src/Analysis/Ast/Test/LintInheritNonClassTests.cs @@ -146,13 +146,6 @@ def method(self): } - /// - /// Because typing module is specialized with functions instead of classes, - /// we think that we are extending a function instead of a class so we would erroneously - /// give a diagnostic message - /// - /// - [Ignore] [TestMethod, Priority(0)] public async Task InheritFromTypingModule() { const string code = @" @@ -166,6 +159,18 @@ def method(self): analysis.Diagnostics.Should().BeEmpty(); } + [TestMethod, Priority(0)] + public async Task InheritFromTypingModuleNamedTuple() { + const string code = @" +from typing import NamedTuple + +class X(NamedTuple): + y: str +"; + var analysis = await GetAnalysisAsync(code); + analysis.Diagnostics.Should().BeEmpty(); + } + [TestMethod, Priority(0)] public async Task InheritFromOtherModule() { var module1Code = @"