rbs 0.18.1 → 1.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/Rakefile +12 -0
  4. data/Steepfile +2 -1
  5. data/bin/annotate-with-rdoc +0 -4
  6. data/core/builtin.rbs +4 -0
  7. data/core/file.rbs +3 -4
  8. data/core/hash.rbs +1 -3
  9. data/core/io.rbs +165 -7
  10. data/core/kernel.rbs +1 -1
  11. data/core/module.rbs +41 -0
  12. data/core/time.rbs +0 -12
  13. data/docs/syntax.md +0 -17
  14. data/goodcheck.yml +22 -2
  15. data/lib/rbs.rb +2 -0
  16. data/lib/rbs/ast/declarations.rb +7 -49
  17. data/lib/rbs/ast/members.rb +10 -4
  18. data/lib/rbs/cli.rb +10 -10
  19. data/lib/rbs/definition.rb +70 -3
  20. data/lib/rbs/definition_builder.rb +573 -984
  21. data/lib/rbs/definition_builder/ancestor_builder.rb +525 -0
  22. data/lib/rbs/definition_builder/method_builder.rb +217 -0
  23. data/lib/rbs/environment.rb +6 -8
  24. data/lib/rbs/environment_loader.rb +8 -4
  25. data/lib/rbs/errors.rb +88 -121
  26. data/lib/rbs/method_type.rb +1 -31
  27. data/lib/rbs/parser.rb +1082 -1014
  28. data/lib/rbs/parser.y +108 -76
  29. data/lib/rbs/prototype/rb.rb +18 -3
  30. data/lib/rbs/prototype/rbi.rb +6 -6
  31. data/lib/rbs/prototype/runtime.rb +71 -35
  32. data/lib/rbs/substitution.rb +4 -0
  33. data/lib/rbs/test.rb +3 -1
  34. data/lib/rbs/test/hook.rb +26 -8
  35. data/lib/rbs/types.rb +68 -7
  36. data/lib/rbs/validator.rb +4 -2
  37. data/lib/rbs/variance_calculator.rb +5 -1
  38. data/lib/rbs/version.rb +1 -1
  39. data/lib/rbs/writer.rb +13 -4
  40. data/schema/members.json +5 -1
  41. data/sig/ancestor_builder.rbs +98 -0
  42. data/sig/declarations.rbs +4 -16
  43. data/sig/definition.rbs +6 -1
  44. data/sig/definition_builder.rbs +15 -67
  45. data/sig/errors.rbs +159 -0
  46. data/sig/members.rbs +4 -1
  47. data/sig/method_builder.rbs +71 -0
  48. data/sig/method_types.rbs +3 -16
  49. data/sig/substitution.rbs +3 -0
  50. data/sig/type_name_resolver.rbs +4 -2
  51. data/sig/types.rbs +17 -15
  52. data/sig/validator.rbs +12 -0
  53. data/stdlib/csv/0/csv.rbs +3 -0
  54. data/stdlib/dbm/0/dbm.rbs +0 -2
  55. data/stdlib/logger/0/log_device.rbs +1 -2
  56. data/stdlib/monitor/0/monitor.rbs +119 -0
  57. data/stdlib/pathname/0/pathname.rbs +1 -1
  58. data/stdlib/prime/0/prime.rbs +6 -0
  59. data/stdlib/securerandom/0/securerandom.rbs +2 -0
  60. data/stdlib/time/0/time.rbs +327 -0
  61. data/stdlib/tsort/0/tsort.rbs +8 -0
  62. data/stdlib/uri/0/common.rbs +401 -0
  63. data/stdlib/uri/0/rfc2396_parser.rbs +9 -0
  64. data/stdlib/uri/0/rfc3986_parser.rbs +2 -0
  65. data/steep/Gemfile.lock +13 -14
  66. metadata +16 -5
@@ -65,10 +65,15 @@ module RBS
65
65
  type t = Instance | Singleton
66
66
 
67
67
  class Instance
68
+ type source = :super | nil
69
+ | AST::Members::Include | AST::Members::Extend | AST::Members::Prepend
70
+ | AST::Declarations::Module::Self
71
+
68
72
  attr_reader name: TypeName
69
73
  attr_reader args: Array[Types::t]
74
+ attr_reader source: source
70
75
 
71
- def initialize: (name: TypeName, args: Array[Types::t]) -> void
76
+ def initialize: (name: TypeName, args: Array[Types::t], source: source) -> void
72
77
  end
73
78
 
74
79
  class Singleton
@@ -1,97 +1,45 @@
1
1
  module RBS
2
2
  class DefinitionBuilder
3
- class OneAncestors
4
- attr_reader type_name: TypeName
5
- attr_reader params: Array[Symbol]?
6
- attr_reader super_class: Definition::Ancestor::t?
7
- attr_reader self_types: Array[Definition::Ancestor::Instance]?
8
- attr_reader included_modules: Array[Definition::Ancestor::Instance]?
9
- attr_reader prepended_modules: Array[Definition::Ancestor::Instance]?
10
- attr_reader extended_modules: Array[Definition::Ancestor::Instance]?
11
-
12
- def initialize: (type_name: TypeName,
13
- params: Array[Symbol]?,
14
- super_class: Definition::Ancestor::t?,
15
- self_types: Array[Definition::Ancestor::Instance]?,
16
- included_modules: Array[Definition::Ancestor::Instance]?,
17
- prepended_modules: Array[Definition::Ancestor::Instance]?,
18
- extended_modules: Array[Definition::Ancestor::Instance]?) -> void
19
-
20
- def each_ancestor: { (Definition::Ancestor::t) -> void } -> void
21
- | -> Enumerator[Definition::Ancestor::t, void]
22
-
23
- def self.class_instance: (type_name: TypeName, params: Array[Symbol], super_class: Definition::Ancestor::t?) -> instance
24
-
25
- def self.singleton: (type_name: TypeName, super_class: Definition::Ancestor::t?) -> instance
26
-
27
- def self.module_instance: (type_name: TypeName, params: Array[Symbol]) -> instance
28
- end
29
-
30
3
  attr_reader env: Environment
31
4
  attr_reader type_name_resolver: TypeNameResolver
5
+ attr_reader ancestor_builder: AncestorBuilder
6
+ attr_reader method_builder: MethodBuilder
32
7
 
33
8
  attr_reader instance_cache: Hash[TypeName, Definition | false | nil]
34
9
  attr_reader singleton_cache: Hash[TypeName, Definition | false | nil]
10
+ attr_reader singleton0_cache: Hash[TypeName, Definition | false | nil]
35
11
  attr_reader interface_cache: Hash[TypeName, Definition | false | nil]
36
12
 
37
- attr_reader one_instance_cache: Hash[TypeName, Definition]
38
- attr_reader one_singleton_cache: Hash[TypeName, Definition]
39
-
40
- attr_reader instance_ancestors_cache: Hash[TypeName, Definition::InstanceAncestors]
41
- attr_reader singleton_ancestor_cache: Hash[TypeName, Definition::SingletonAncestors]
42
-
43
- attr_reader one_instance_ancestors_cache: Hash[TypeName, OneAncestors]
44
- attr_reader one_singleton_ancestors_cache: Hash[TypeName, OneAncestors]
45
-
46
13
  def initialize: (env: Environment) -> void
47
14
 
48
15
  def validate_super_class!: (TypeName, Environment::ClassEntry) -> void
49
16
 
50
- def one_instance_ancestors: (TypeName) -> OneAncestors
51
-
52
- def one_singleton_ancestors: (TypeName) -> OneAncestors
53
-
54
- def instance_ancestors: (TypeName, ?building_ancestors: Array[Definition::Ancestor::t]) -> Definition::InstanceAncestors
55
-
56
- def singleton_ancestors: (TypeName, ?building_ancestors: Array[Definition::Ancestor::t]) -> Definition::SingletonAncestors
57
-
58
- def mixin_ancestors: (Environment::ClassEntry | Environment::ModuleEntry, included_modules: Array[Definition::Ancestor::Instance]?, prepended_modules: Array[Definition::Ancestor::Instance]?, extended_modules: Array[Definition::Ancestor::Instance]?) -> void
59
-
60
- def each_member_with_accessibility: (Array[AST::Members::t | AST::Declarations::t], ?accessibility: Definition::accessibility) { (AST::Members::t | AST::Declarations::t, Definition::accessibility) -> void } -> void
61
-
62
17
  def ensure_namespace!: (Namespace, location: Location?) -> void
63
18
 
64
- def build_singleton: (TypeName) -> Definition
19
+ def build_interface: (TypeName) -> Definition
65
20
 
66
21
  def build_instance: (TypeName) -> Definition
67
22
 
68
- def build_interface: (TypeName) -> Definition
23
+ def build_singleton0: (TypeName) -> Definition
69
24
 
70
- def build_one_instance: (TypeName) -> Definition
71
-
72
- def build_one_singleton: (TypeName) -> Definition
25
+ def build_singleton: (TypeName) -> Definition
73
26
 
74
- type ancestors = Definition::InstanceAncestors | Definition::SingletonAncestors | nil
75
- def merge_definitions: (TypeName,
76
- Array[[Definition::Ancestor::t, Definition]],
77
- entry: Environment::ModuleEntry | Environment::ClassEntry,
78
- self_type: Definition::self_type,
79
- ancestors: ancestors) -> Definition
27
+ def merge_definition: (src: Definition, dest: Definition, subst: Substitution, ?implemented_in: :keep | TypeName | nil, ?keep_super: bool) -> void
80
28
 
81
- type method_kind = :instance | :singleton
82
- def merge_method: (TypeName, Hash[Symbol, Definition::Method], Symbol, Definition::Method, Substitution, kind: method_kind) -> void
29
+ def merge_method: (TypeName, Hash[Symbol, Definition::Method], Symbol, Definition::Method, Substitution, ?implemented_in: :keep | TypeName | nil, ?keep_super: bool) -> void
83
30
 
84
- def merge_variable: (Hash[Symbol, Definition::Variable], Symbol, Definition::Variable) -> void
31
+ def merge_variable: (Hash[Symbol, Definition::Variable], Symbol, Definition::Variable, Substitution, ?keep_super: bool) -> void
85
32
 
86
33
  def try_cache: (TypeName, cache: Hash[TypeName, Definition | false | nil]) { () -> Definition } -> Definition
87
34
 
88
- type member_detail = [Definition::accessibility, Definition::Method?, AST::Members::MethodDefinition?, Array[AST::Members::MethodDefinition]]
89
- def method_definition_members: (TypeName, Environment::ClassEntry | Environment::ModuleEntry, kind: :singleton | :instance) -> Hash[Symbol, member_detail]
90
-
91
35
  def validate_params_with: (AST::Declarations::ModuleTypeParams, result: VarianceCalculator::Result) { (AST::Declarations::ModuleTypeParams::TypeParam) -> void } -> void
92
36
 
93
- def validate_parameter_variance: (decl: AST::Declarations::Class | AST::Declarations::Module | AST::Declarations::Interface, methods: Hash[Symbol, Definition::Method]) -> void
37
+ def validate_type_params: (Definition, ancestors: AncestorBuilder::OneAncestors, methods: MethodBuilder::Methods) -> void
38
+
39
+ def source_location: (Definition::Ancestor::Instance::source, AST::Declarations::t) -> Location?
40
+
41
+ def insert_variable: (TypeName, Hash[Symbol, Definition::Variable], name: Symbol, type: Types::t) -> void
94
42
 
95
- def expand_alias: (TypeName) -> Types::t
43
+ def define_methods: (Definition, interface_methods: Hash[Symbol, Definition::Method], methods: MethodBuilder::Methods, super_interface_method: bool) -> void
96
44
  end
97
45
  end
@@ -0,0 +1,159 @@
1
+ module RBS
2
+ interface _MethodName
3
+ def kind: () -> (:instance | :singleton)
4
+
5
+ def type_name: () -> TypeName
6
+
7
+ def method_name: () -> Symbol
8
+ end
9
+
10
+ module MethodNameHelper : _MethodName
11
+ def method_name_string: () -> String
12
+ end
13
+
14
+ class InvalidTypeApplicationError < StandardError
15
+ attr_reader type_name: TypeName
16
+ attr_reader args: Array[Types::t]
17
+ attr_reader params: Array[Symbol]
18
+ attr_reader location: Location?
19
+
20
+ def initialize: (type_name: TypeName, args: Array[Types::t], params: Array[Symbol], location: Location?) -> void
21
+
22
+ def self.check!: (type_name: TypeName, args: Array[Types::t], params: Array[Symbol], location: Location?) -> void
23
+ end
24
+
25
+ class RecursiveAncestorError < StandardError
26
+ attr_reader ancestors: Array[Definition::Ancestor::t]
27
+ attr_reader location: Location
28
+
29
+ def initialize: (ancestors: Array[Definition::Ancestor::t], location: Location?) -> void
30
+
31
+ def self.check!: (Definition::Ancestor::t, ancestors: Array[Definition::Ancestor::t], location: Location?) -> void
32
+ end
33
+
34
+ class NoTypeFoundError < StandardError
35
+ attr_reader type_name: TypeName
36
+ attr_reader location: Location?
37
+
38
+ def initialize: (type_name: TypeName, location: Location?) -> void
39
+
40
+ def self.check!: (TypeName, env: Environment, location: Location?) -> TypeName
41
+ end
42
+
43
+ class NoSuperclassFoundError < StandardError
44
+ attr_reader type_name: TypeName
45
+ attr_reader location: Location?
46
+
47
+ def initialize: (type_name: TypeName, location: Location?) -> void
48
+
49
+ def self.check!: (TypeName, env: Environment, location: Location?) -> void
50
+ end
51
+
52
+ class NoSelfTypeFoundError < StandardError
53
+ attr_reader type_name: TypeName
54
+ attr_reader location: Location?
55
+
56
+ def initialize: (type_name: TypeName, location: Location?) -> void
57
+
58
+ def self.check!: (AST::Declarations::Module::Self, env: Environment) -> void
59
+ end
60
+
61
+ class NoMixinFoundError < StandardError
62
+ attr_reader type_name: TypeName
63
+ attr_reader member: AST::Members::t
64
+
65
+ def initialize: (type_name: TypeName, member: AST::Members::t) -> void
66
+
67
+ def location: () -> Location?
68
+
69
+ def self.check!: (TypeName, env: Environment, member: AST::Members::t) -> void
70
+ end
71
+
72
+ class DuplicatedMethodDefinitionError < StandardError
73
+ type ty = Types::ClassSingleton | Types::ClassInstance | Types::Interface
74
+ type original = DefinitionBuilder::MethodBuilder::Methods::Definition::original
75
+
76
+ attr_reader type: ty
77
+ attr_reader method_name: Symbol
78
+ attr_reader members: Array[original]
79
+
80
+ def initialize: (type: ty, method_name: Symbol, members: Array[original]) -> void
81
+
82
+ def qualified_method_name: () -> String
83
+
84
+ def location: () -> Location?
85
+
86
+ def other_locations: () -> Array[Location?]
87
+ end
88
+
89
+ class DuplicatedInterfaceMethodDefinitionError < StandardError
90
+ type ty = Types::ClassSingleton | Types::ClassInstance | Types::Interface
91
+ type mixin_member = AST::Members::Include | AST::Members::Extend
92
+
93
+ attr_reader type: ty
94
+ attr_reader method_name: Symbol
95
+ attr_reader member: mixin_member
96
+
97
+ def initialize: (type: ty, method_name: Symbol, member: mixin_member) -> void
98
+
99
+ def qualified_method_name: () -> String
100
+ end
101
+
102
+ class UnknownMethodAliasError < StandardError
103
+ attr_reader original_name: Symbol
104
+ attr_reader aliased_name: Symbol
105
+ attr_reader location: Location?
106
+
107
+ def initialize: (original_name: Symbol, aliased_name: Symbol, location: Location?) -> void
108
+ end
109
+
110
+ class SuperclassMismatchError < StandardError
111
+ attr_reader name: TypeName
112
+ attr_reader entry: Environment::ClassEntry
113
+
114
+ def initialize: (name: TypeName, entry: Environment::ClassEntry) -> void
115
+ end
116
+
117
+ class InvalidOverloadMethodError < StandardError
118
+ attr_reader type_name: TypeName
119
+ attr_reader method_name: Symbol
120
+ attr_reader kind: :instance | :singleton
121
+ attr_reader members: Array[AST::Members::MethodDefinition]
122
+
123
+ def initialize: (type_name: TypeName, method_name: Symbol, kind: :instance | :singleton, members: Array[AST::Members::MethodDefinition]) -> void
124
+ end
125
+
126
+ class GenericParameterMismatchError < StandardError
127
+ attr_reader name: TypeName
128
+ attr_reader decl: AST::Declarations::Class | AST::Declarations::Module
129
+
130
+ def initialize: (name: TypeName, decl: AST::Declarations::Class | AST::Declarations::Module) -> void
131
+ end
132
+
133
+ class DuplicatedDeclarationError < StandardError
134
+ attr_reader name: TypeName | Symbol
135
+ attr_reader decls: Array[AST::Declarations::t]
136
+
137
+ def initialize: (TypeName | Symbol, *AST::Declarations::t) -> void
138
+ end
139
+
140
+ class InvalidVarianceAnnotationError < StandardError
141
+ attr_reader type_name: TypeName
142
+ attr_reader param: AST::Declarations::ModuleTypeParams::TypeParam
143
+ attr_reader location: Location?
144
+
145
+ def initialize: (type_name: TypeName, param: AST::Declarations::ModuleTypeParams::TypeParam, location: Location?) -> void
146
+ end
147
+
148
+ class RecursiveAliasDefinitionError < StandardError
149
+ type ty = Types::ClassInstance | Types::ClassSingleton | Types::Interface
150
+ type defn = DefinitionBuilder::MethodBuilder::Methods::Definition
151
+
152
+ attr_reader type: ty
153
+ attr_reader defs: Array[defn]
154
+
155
+ def initialize: (type: ty, defs: Array[defn]) -> void
156
+
157
+ def location: () -> Location?
158
+ end
159
+ end
@@ -91,14 +91,17 @@ module RBS
91
91
  end
92
92
 
93
93
  module Attribute
94
+ type kind = :instance | :singleton
95
+
94
96
  attr_reader name: Symbol
95
97
  attr_reader type: Types::t
98
+ attr_reader kind: kind
96
99
  attr_reader ivar_name: Symbol | false | nil
97
100
  attr_reader annotations: Array[Annotation]
98
101
  attr_reader location: Location?
99
102
  attr_reader comment: Comment?
100
103
 
101
- def initialize: (name: Symbol, type: Types::t, ivar_name: Symbol | false | nil, annotations: Array[Annotation], location: Location?, comment: Comment?) -> void
104
+ def initialize: (name: Symbol, type: Types::t, ivar_name: Symbol | false | nil, kind: kind, annotations: Array[Annotation], location: Location?, comment: Comment?) -> void
102
105
 
103
106
  include _HashEqual
104
107
  end
@@ -0,0 +1,71 @@
1
+ module RBS
2
+ class DefinitionBuilder
3
+ class MethodBuilder
4
+ class Methods
5
+ type instance_type = Types::ClassInstance | Types::ClassSingleton | Types::Interface
6
+
7
+ class Definition
8
+ type original = AST::Members::MethodDefinition | AST::Members::Alias | AST::Members::AttrAccessor | AST::Members::AttrWriter | AST::Members::AttrReader
9
+ type accessibility = :public | :private
10
+
11
+ attr_reader name: Symbol
12
+ attr_reader type: instance_type
13
+ attr_reader originals: Array[original]
14
+ attr_reader overloads: Array[AST::Members::MethodDefinition]
15
+ attr_reader accessibilities: Array[accessibility]
16
+
17
+ def initialize: (name: Symbol, type: instance_type, originals: Array[original], overloads: Array[AST::Members::MethodDefinition], accessibilities: Array[accessibility]) -> void
18
+
19
+ def original: () -> original?
20
+
21
+ def accessibility: () -> accessibility
22
+
23
+ def self.empty: (name: Symbol, type: instance_type) -> instance
24
+ end
25
+
26
+ attr_reader type: instance_type
27
+ attr_reader methods: Hash[Symbol, Definition]
28
+
29
+ def initialize: (type: instance_type) -> void
30
+
31
+ def validate!: () -> self
32
+
33
+ def each: () { (Definition) -> void } -> void
34
+ | () -> Enumerator[Definition, void]
35
+
36
+ class Sorter
37
+ include TSort[Definition]
38
+
39
+ attr_reader methods: Hash[Symbol, Definition]
40
+
41
+ def initialize: (Hash[Symbol, Definition]) -> void
42
+
43
+ def tsort_each_node: { (Definition) -> void } -> void
44
+
45
+ def tsort_each_child: (Definition) { (Definition) -> void } -> void
46
+ end
47
+ end
48
+
49
+ attr_reader env: Environment
50
+ attr_reader instance_methods: Hash[TypeName, Methods]
51
+ attr_reader singleton_methods: Hash[TypeName, Methods]
52
+ attr_reader interface_methods: Hash[TypeName, Methods]
53
+
54
+ def initialize: (env: Environment) -> void
55
+
56
+ def build_instance: (TypeName) -> Methods
57
+
58
+ def build_singleton: (TypeName) -> Methods
59
+
60
+ def build_interface: (TypeName) -> Methods
61
+
62
+ def build_alias: (Methods, Methods::instance_type, member: AST::Members::Alias, accessibility: Methods::Definition::accessibility) -> void
63
+
64
+ def build_attribute: (Methods, Methods::instance_type, member: AST::Members::AttrAccessor | AST::Members::AttrReader | AST::Members::AttrWriter, accessibility: Methods::Definition::accessibility) -> void
65
+
66
+ def build_method: (Methods, Methods::instance_type, member: AST::Members::MethodDefinition, accessibility: Methods::Definition::accessibility) -> void
67
+
68
+ def each_member_with_accessibility: (Array[AST::Members::t | AST::Declarations::t], ?accessibility: Definition::accessibility) { (AST::Members::t | AST::Declarations::t, Definition::accessibility) -> void } -> void
69
+ end
70
+ end
71
+ end
@@ -1,24 +1,11 @@
1
1
  module RBS
2
2
  class MethodType
3
- class Block
4
- attr_reader type: Types::Function
5
- attr_reader required: bool
6
-
7
- def initialize: (type: Types::Function, required: boolish) -> void
8
-
9
- def ==: (untyped other) -> bool
10
-
11
- def to_json: (*untyped) -> String
12
-
13
- def sub: (Substitution) -> Block
14
- end
15
-
16
3
  attr_reader type_params: Array[Symbol]
17
4
  attr_reader type: Types::Function
18
- attr_reader block: Block?
5
+ attr_reader block: Types::Block?
19
6
  attr_reader location: Location?
20
7
 
21
- def initialize: (type_params: Array[Symbol], type: Types::Function, block: Block?, location: Location?) -> void
8
+ def initialize: (type_params: Array[Symbol], type: Types::Function, block: Types::Block?, location: Location?) -> void
22
9
 
23
10
  def ==: (untyped other) -> bool
24
11
 
@@ -26,7 +13,7 @@ module RBS
26
13
 
27
14
  def sub: (Substitution) -> MethodType
28
15
 
29
- def update: (?type_params: Array[Symbol], ?type: Types::Function, ?block: Block?, ?location: Location?) -> MethodType
16
+ def update: (?type_params: Array[Symbol], ?type: Types::Function, ?block: Types::Block?, ?location: Location?) -> MethodType
30
17
 
31
18
  def free_variables: (?Set[Symbol] set) -> Set[Symbol]
32
19
 
@@ -35,5 +35,8 @@ module RBS
35
35
 
36
36
  # Returns a substitution without variables given in `vars`.
37
37
  def without: (*Symbol vars) -> Substitution
38
+
39
+ # Returns true if given substitution is identity.
40
+ def empty?: () -> bool
38
41
  end
39
42
  end
@@ -1,10 +1,12 @@
1
1
  module RBS
2
2
  class TypeNameResolver
3
+ type context = Array[Namespace]
4
+
3
5
  class Query
4
6
  attr_reader type_name: TypeName
5
7
  attr_reader context: Array[Namespace]
6
8
 
7
- def initialize: (type_name: TypeName, context: Array[Namespace]) -> void
9
+ def initialize: (type_name: TypeName, context: context) -> void
8
10
  end
9
11
 
10
12
  attr_reader all_names: Set[TypeName]
@@ -15,7 +17,7 @@ module RBS
15
17
 
16
18
  def add_names: (Array[TypeName]) -> self
17
19
 
18
- def resolve: (TypeName, context: Array[Namespace]) -> TypeName?
20
+ def resolve: (TypeName, context: context) -> TypeName?
19
21
 
20
22
  def has_name?: (TypeName) -> TypeName?
21
23