Skip to content

Commit 7b15d10

Browse files
authored
Enable nullable annotations in ClassDefinition (#1171)
1 parent f0b690a commit 7b15d10

File tree

2 files changed

+34
-24
lines changed

2 files changed

+34
-24
lines changed

Src/IronPython/Compiler/Ast/ClassDefinition.cs

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Collections.Generic;
77
using System.Collections.ObjectModel;
8+
using System.Diagnostics.CodeAnalysis;
89
using System.Linq;
910
using System.Runtime.CompilerServices;
1011
using System.Threading;
@@ -19,6 +20,8 @@
1920
using LightLambdaExpression = Microsoft.Scripting.Ast.LightLambdaExpression;
2021
using MSAst = System.Linq.Expressions;
2122

23+
#nullable enable
24+
2225
namespace IronPython.Compiler.Ast {
2326
using Ast = MSAst.Expression;
2427

@@ -27,18 +30,18 @@ public class ClassDefinition : ScopeStatement {
2730
private readonly Arg[] _bases;
2831
private readonly Arg[] _keywords;
2932

30-
private LightLambdaExpression _dlrBody; // the transformed body including all of our initialization, etc...
33+
private LightLambdaExpression? _dlrBody; // the transformed body including all of our initialization, etc...
3134

3235
private static int _classId;
3336

3437
private static readonly MSAst.ParameterExpression _parentContextParam = Ast.Parameter(typeof(CodeContext), "$parentContext");
3538
private static readonly MSAst.Expression _tupleExpression = MSAst.Expression.Call(AstMethods.GetClosureTupleFromContext, _parentContextParam);
3639

37-
public ClassDefinition(string name, IReadOnlyList<Arg> bases, IReadOnlyList<Arg> keywords, Statement body = null) {
40+
public ClassDefinition(string name, IReadOnlyList<Arg>? bases, IReadOnlyList<Arg>? keywords, Statement? body = null) {
3841
_name = name;
3942
_bases = bases?.ToArray() ?? Array.Empty<Arg>();
4043
_keywords = keywords?.ToArray() ?? Array.Empty<Arg>();
41-
Body = body;
44+
Body = body ?? EmptyStatement.PreCompiledInstance;
4245
Metaclass = _keywords.Where(arg => arg.Name == "metaclass").Select(arg => arg.Expression).FirstOrDefault();
4346
}
4447

@@ -52,34 +55,41 @@ public ClassDefinition(string name, IReadOnlyList<Arg> bases, IReadOnlyList<Arg>
5255

5356
public IReadOnlyList<Arg> Keywords => _keywords;
5457

55-
public Expression Metaclass { get; }
58+
public Expression? Metaclass { get; }
5659

5760
public Statement Body { get; set; }
5861

59-
public IList<Expression> Decorators { get; internal set; }
62+
public IList<Expression>? Decorators { get; internal set; }
6063

6164
/// <summary>
62-
/// Variable corresponding to the class name
65+
/// Variable corresponding to the class name, set during name binding
6366
/// </summary>
64-
internal PythonVariable PythonVariable { get; set; }
67+
[DisallowNull]
68+
internal PythonVariable? PythonVariable { get; set; }
6569

6670
/// <summary>
67-
/// Variable for the the __module__ (module name)
71+
/// Variable for the the __module__ (module name), set during name binding
6872
/// </summary>
69-
internal PythonVariable ModVariable { get; set; }
73+
[DisallowNull]
74+
internal PythonVariable? ModVariable { get; set; }
7075

7176
/// <summary>
72-
/// Variable for the __doc__ attribute
77+
/// Variable for the __doc__ attribute, set during name binding
7378
/// </summary>
74-
internal PythonVariable DocVariable { get; set; }
79+
[DisallowNull]
80+
internal PythonVariable? DocVariable { get; set; }
7581

7682
/// <summary>
77-
/// Variable for the module's __name__
83+
/// Variable for the module's __name__, set during name binding
7884
/// </summary>
79-
internal PythonVariable ModuleNameVariable { get; set; }
85+
[DisallowNull]
86+
internal PythonVariable? ModuleNameVariable { get; set; }
8087

81-
private PythonVariable ClassCellVariable { get; set; }
82-
private PythonVariable ClassVariable { get; set; }
88+
// set during name binding
89+
[DisallowNull]
90+
private PythonVariable? ClassCellVariable { get; set; }
91+
[DisallowNull]
92+
private PythonVariable? ClassVariable { get; set; }
8393

8494
internal override bool HasLateBoundVariableSets {
8595
get {
@@ -111,8 +121,8 @@ internal override bool TryBindOuter(ScopeStatement from, PythonReference referen
111121
return base.TryBindOuter(from, reference, out variable);
112122
}
113123

114-
internal override PythonVariable BindReference(PythonNameBinder binder, PythonReference reference) {
115-
PythonVariable variable;
124+
internal override PythonVariable? BindReference(PythonNameBinder binder, PythonReference reference) {
125+
PythonVariable? variable;
116126

117127
// Python semantics: The variables bound local in the class
118128
// scope are accessed by name - the dictionary behavior of classes
@@ -187,7 +197,7 @@ public override MSAst.Expression Reduce() {
187197
classDef = AddDecorators(classDef, Decorators);
188198

189199
return GlobalParent.AddDebugInfoAndVoid(
190-
AssignValue(Parent.GetVariableExpression(PythonVariable), classDef),
200+
AssignValue(Parent.GetVariableExpression(PythonVariable!), classDef),
191201
new SourceSpan(
192202
GlobalParent.IndexToLocation(StartIndex),
193203
GlobalParent.IndexToLocation(HeaderIndex)
@@ -242,8 +252,8 @@ private Microsoft.Scripting.Ast.LightExpression<Func<CodeContext, CodeContext>>
242252
init.Add(Ast.Assign(LocalCodeContextVariable, createLocal));
243253
// __classcell__ == ClosureCell(__class__)
244254
if (needClassCell) {
245-
var exp = (ClosureExpression) GetVariableExpression(ClassVariable);
246-
MSAst.Expression assignClassCell = AssignValue(GetVariableExpression(ClassCellVariable), exp.ClosureCell);
255+
var exp = (ClosureExpression) GetVariableExpression(ClassVariable!);
256+
MSAst.Expression assignClassCell = AssignValue(GetVariableExpression(ClassCellVariable!), exp.ClosureCell);
247257
init.Add(assignClassCell);
248258
}
249259

@@ -253,13 +263,13 @@ private Microsoft.Scripting.Ast.LightExpression<Func<CodeContext, CodeContext>>
253263

254264

255265
// __module__ = __name__
256-
MSAst.Expression modStmt = AssignValue(GetVariableExpression(ModVariable), GetVariableExpression(ModuleNameVariable));
266+
MSAst.Expression modStmt = AssignValue(GetVariableExpression(ModVariable!), GetVariableExpression(ModuleNameVariable!));
257267

258268
string doc = GetDocumentation(Body);
259269
if (doc != null) {
260270
statements.Add(
261271
AssignValue(
262-
GetVariableExpression(DocVariable),
272+
GetVariableExpression(DocVariable!),
263273
AstUtils.Constant(doc)
264274
)
265275
);
@@ -325,7 +335,7 @@ public override void Walk(PythonWalker walker) {
325335
foreach (Arg b in _keywords) {
326336
b.Walk(walker);
327337
}
328-
Body?.Walk(walker);
338+
Body.Walk(walker);
329339
}
330340
walker.PostWalk(this);
331341
}

Src/IronPython/Compiler/Parser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,7 @@ private ClassDefinition ParseClassDef() {
10061006
string name = ReadName();
10071007
if (name == null) {
10081008
// no name, assume there's no class.
1009-
return new ClassDefinition(null, null, null, ErrorStmt());
1009+
return new ClassDefinition(string.Empty, null, null, ErrorStmt());
10101010
}
10111011

10121012
List<Arg> bases = null;

0 commit comments

Comments
 (0)