2
2
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
3
3
// See the LICENSE file in the project root for more information.
4
4
5
+ #nullable enable
6
+
7
+ using System ;
5
8
using System . Collections . Generic ;
6
9
using System . Diagnostics ;
10
+ using System . Diagnostics . CodeAnalysis ;
7
11
using System . Runtime . CompilerServices ;
8
12
9
13
using Microsoft . Scripting ;
15
19
namespace IronPython . Runtime {
16
20
[ PythonType ( "super" ) ]
17
21
public class Super : PythonTypeSlot , ICodeFormattable {
18
- private PythonType _thisClass ;
19
- private object _self ;
20
- private object _selfClass ;
22
+ [ DisallowNull ]
23
+ private PythonType ? _thisClass ; // set during __init__
24
+ private object ? _self ;
25
+ private object ? _selfClass ;
21
26
22
27
public Super ( ) {
23
28
}
@@ -28,12 +33,14 @@ public void __init__() {
28
33
throw PythonOps . RuntimeError ( "super(): no arguments" ) ;
29
34
}
30
35
31
- public void __init__ ( PythonType type ) {
36
+ public void __init__ ( [ NotNone ] PythonType type ) {
32
37
__init__ ( type , null ) ;
33
38
}
34
39
35
- public void __init__ ( PythonType type , object obj ) {
36
- if ( obj != null ) {
40
+ public void __init__ ( [ NotNone ] PythonType type , object ? obj ) {
41
+ if ( type is null ) throw new ArgumentNullException ( nameof ( type ) ) ;
42
+
43
+ if ( obj is not null ) {
37
44
if ( PythonOps . IsInstance ( obj , type ) ) {
38
45
_thisClass = type ;
39
46
_self = obj ;
@@ -52,22 +59,29 @@ public void __init__(PythonType type, object obj) {
52
59
}
53
60
}
54
61
55
- public PythonType __thisclass__ {
62
+ public PythonType ? __thisclass__ {
56
63
get { return _thisClass ; }
57
64
}
58
65
59
- public object __self__ {
66
+ public object ? __self__ {
60
67
get { return _self ; }
61
68
}
62
69
63
- public object __self_class__ {
70
+ public object ? __self_class__ {
64
71
get { return _selfClass ; }
65
72
}
66
73
67
- public new object __get__ ( CodeContext /*!*/ context , object instance , object owner ) {
74
+ public new object ? __get__ ( CodeContext /*!*/ context , object ? instance , object ? owner = null ) {
75
+ if ( instance is null && owner is null ) {
76
+ throw PythonOps . TypeError ( "__get__(None, None) is invalid" ) ;
77
+ }
78
+
68
79
PythonType selfType = PythonType ;
69
80
70
81
if ( selfType == TypeCache . Super ) {
82
+ if ( _thisClass is null ) {
83
+ throw PythonOps . TypeError ( "super(): __init__ not called" ) ;
84
+ }
71
85
Super res = new Super ( ) ;
72
86
res . __init__ ( _thisClass , instance ) ;
73
87
return res ;
@@ -81,10 +95,10 @@ public object __self_class__ {
81
95
#region Custom member access
82
96
83
97
[ SpecialName ]
84
- public object GetCustomMember ( CodeContext context , string name ) {
98
+ public object GetCustomMember ( CodeContext context , [ NotNone ] string name ) {
85
99
// first find where we are in the mro...
86
- object value ;
87
- if ( _selfClass is PythonType mroType ) { // can be null if the user does super.__new__
100
+ object ? value ;
101
+ if ( _selfClass is PythonType mroType && _thisClass is not null ) { // can be null if the user does super.__new__
88
102
IList < PythonType > mro = mroType . ResolutionOrder ;
89
103
90
104
int lookupType ;
@@ -105,7 +119,7 @@ public object GetCustomMember(CodeContext context, string name) {
105
119
}
106
120
107
121
// if we're super on a class then we have no self.
108
- object self = _self == _selfClass ? null : _self ;
122
+ object ? self = _self == _selfClass ? null : _self ;
109
123
110
124
// then skip our class, and lookup in everything
111
125
// above us until we get a hit.
@@ -127,16 +141,16 @@ public object GetCustomMember(CodeContext context, string name) {
127
141
}
128
142
129
143
[ SpecialName ]
130
- public void SetMember ( CodeContext context , string name , object value ) {
144
+ public void SetMember ( CodeContext context , [ NotNone ] string name , object ? value ) {
131
145
PythonType . SetMember ( context , this , name , value ) ;
132
146
}
133
147
134
148
[ SpecialName ]
135
- public void DeleteCustomMember ( CodeContext context , string name ) {
149
+ public void DeleteCustomMember ( CodeContext context , [ NotNone ] string name ) {
136
150
PythonType . DeleteMember ( context , this , name ) ;
137
151
}
138
152
139
- private bool TryLookupInBase ( CodeContext context , PythonType pt , string name , object self , out object value ) {
153
+ private bool TryLookupInBase ( CodeContext context , PythonType pt , string name , object ? self , [ NotNullWhen ( true ) ] out object ? value ) {
140
154
// new-style class, or reflected type, lookup slot
141
155
if ( pt . TryLookupSlot ( context , name , out PythonTypeSlot dts ) &&
142
156
dts . TryGetValue ( context , self , DescriptorContext , out value ) ) {
@@ -146,7 +160,7 @@ private bool TryLookupInBase(CodeContext context, PythonType pt, string name, ob
146
160
return false ;
147
161
}
148
162
149
- private PythonType DescriptorContext {
163
+ private PythonType ? DescriptorContext {
150
164
get {
151
165
if ( ! DynamicHelpers . GetPythonType ( _self ) . IsSubclassOf ( _thisClass ) ) {
152
166
if ( _self == _selfClass ) // Using @classmethod
@@ -164,16 +178,16 @@ private PythonType PythonType {
164
178
if ( GetType ( ) == typeof ( Super ) )
165
179
return TypeCache . Super ;
166
180
167
- IPythonObject sdo = this as IPythonObject ;
168
- Debug . Assert ( sdo != null ) ;
181
+ Debug . Assert ( this is IPythonObject ) ;
182
+ IPythonObject sdo = ( IPythonObject ) this ;
169
183
170
184
return sdo . PythonType ;
171
185
}
172
186
}
173
187
174
188
#endregion
175
189
176
- internal override bool TryGetValue ( CodeContext context , object instance , PythonType owner , out object value ) {
190
+ internal override bool TryGetValue ( CodeContext context , object ? instance , PythonType ? owner , out object ? value ) {
177
191
value = __get__ ( context , instance , owner ) ;
178
192
return true ;
179
193
}
0 commit comments