Skip to content
This repository has been archived by the owner on Apr 14, 2022. It is now read-only.

Treat None as its own type and instance #1626

Merged
merged 1 commit into from Oct 4, 2019
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Analysis/Ast/Impl/Analyzer/PythonInterpreter.cs
Expand Up @@ -22,6 +22,7 @@
using Microsoft.Python.Analysis.Modules.Resolution;
using Microsoft.Python.Analysis.Specializations.Typing;
using Microsoft.Python.Analysis.Types;
using Microsoft.Python.Analysis.Values;
using Microsoft.Python.Core;
using Microsoft.Python.Core.Collections;
using Microsoft.Python.Core.Services;
Expand Down Expand Up @@ -138,7 +139,7 @@ CancellationToken cancellationToken
}

if (id == BuiltinTypeId.NoneType) {
type = new PythonType("NoneType", new Location(_moduleResolution.BuiltinsModule), string.Empty, BuiltinTypeId.NoneType);
type = new PythonNone(_moduleResolution.BuiltinsModule);
} else {
var bm = _moduleResolution.BuiltinsModule;
var typeName = id.GetTypeName(LanguageVersion);
Expand Down
33 changes: 33 additions & 0 deletions src/Analysis/Ast/Impl/Values/PythonNone.cs
@@ -0,0 +1,33 @@
// Copyright(c) Microsoft Corporation
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the License); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABILITY OR NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing
// permissions and limitations under the License.

using Microsoft.Python.Analysis.Types;
using Microsoft.Python.Analysis.Values.Collections;

namespace Microsoft.Python.Analysis.Values {
internal sealed class PythonNone : PythonType, IPythonInstance {
public PythonNone(IBuiltinsPythonModule builtins) : base("None", new Location(builtins), string.Empty, BuiltinTypeId.NoneType) { }

public override IPythonInstance CreateInstance(IArgumentSet args) => this;

public IPythonType Type => this;

public IMember Call(string memberName, IArgumentSet args) => DeclaringModule.Interpreter.UnknownType;

public IPythonIterator GetIterator() => new EmptyIterator(DeclaringModule.Interpreter.UnknownType);

public IMember Index(IArgumentSet args) => DeclaringModule.Interpreter.UnknownType;
}
}
34 changes: 34 additions & 0 deletions src/Analysis/Ast/Test/LintInheritNonClassTests.cs
Expand Up @@ -489,5 +489,39 @@ class C(Enum): ...
var analysis = await GetAnalysisAsync(code);
analysis.Diagnostics.Should().BeEmpty();
}

[TestMethod, Priority(0)]
public async Task InheritFromNone() {
const string code = @"
class C(None):
def method(self):
return 'test'
";
var analysis = await GetAnalysisAsync(code);
analysis.Diagnostics.Should().HaveCount(1);

var diagnostic = analysis.Diagnostics.ElementAt(0);
diagnostic.SourceSpan.Should().Be(2, 9, 2, 13);
diagnostic.Message.Should().Be(Resources.InheritNonClass.FormatInvariant("None"));
diagnostic.ErrorCode.Should().Be(ErrorCodes.InheritNonClass);
}

[TestMethod, Priority(0)]
public async Task InheritFromNoneVar() {
const string code = @"
x = None

class C(x):
def method(self):
return 'test'
";
var analysis = await GetAnalysisAsync(code);
analysis.Diagnostics.Should().HaveCount(1);

var diagnostic = analysis.Diagnostics.ElementAt(0);
diagnostic.SourceSpan.Should().Be(4, 9, 4, 10);
diagnostic.Message.Should().Be(Resources.InheritNonClass.FormatInvariant("x"));
diagnostic.ErrorCode.Should().Be(ErrorCodes.InheritNonClass);
}
}
}
13 changes: 13 additions & 0 deletions src/Analysis/Ast/Test/TypingTests.cs
Expand Up @@ -329,6 +329,19 @@ class A:
.Which.Should().HaveType(BuiltinTypeId.Str);
}

[TestMethod, Priority(0)]
public async Task TupleOfNones() {
const string code = @"
from typing import Tuple

x: Tuple[None, None, None]
";
var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X);

analysis.Should().HaveVariable("x")
.Which.Should().HaveType("Tuple[None, None, None]");
}

[TestMethod, Priority(0)]
public void AnnotationParsing() {
AssertTransform("List", "NameOp:List");
Expand Down