diff --git a/core/process.rbs b/core/process.rbs index 35d18506b..0012cd345 100644 --- a/core/process.rbs +++ b/core/process.rbs @@ -2236,7 +2236,7 @@ end # # Placeholder for rusage # -class Process::Tms < Struct[Float] +class Process::Tms < Struct(utime: Float, stime: Float, cutime: Float, cstime: Float) end class Process::Waiter < Thread diff --git a/ext/rbs_extension/parser.c b/ext/rbs_extension/parser.c index db88ef57a..8065f727e 100644 --- a/ext/rbs_extension/parser.c +++ b/ext/rbs_extension/parser.c @@ -1747,6 +1747,8 @@ VALUE parse_member_def(parserstate *state, bool instance_only, bool accept_overl /** * class_instance_name ::= {} + * | {} Data `(` kwarg args `)` + * | {} Struct `(` kwarg args `)` * | {} class_name `[` type args <`]`> * * @param kind @@ -1756,7 +1758,19 @@ void class_instance_name(parserstate *state, TypeNameKind kind, VALUE *name, VAL *name = parse_type_name(state, kind, name_range); - if (state->next_token.type == pLBRACKET) { + if (CLASS_OF(*name) == RBS_TypeName && rb_funcall(*name, rb_intern("data?"), 0) == Qtrue) { + parser_advance_assert(state, pLPAREN); + args_range->start = state->current_token.range.start; + *args = parse_record_attributes(state); + parser_advance_assert(state, pRPAREN); + args_range->end = state->current_token.range.end; + } else if (CLASS_OF(*name) == RBS_TypeName && rb_funcall(*name, rb_intern("struct?"), 0) == Qtrue) { + parser_advance_assert(state, pLPAREN); + args_range->start = state->current_token.range.start; + *args = parse_record_attributes(state); + parser_advance_assert(state, pRPAREN); + args_range->end = state->current_token.range.end; + } else if (state->next_token.type == pLBRACKET) { parser_advance(state); args_range->start = state->current_token.range.start; parse_type_list(state, pRBRACKET, args); diff --git a/lib/rbs/ast/declarations.rb b/lib/rbs/ast/declarations.rb index bf9f0218f..629b38983 100644 --- a/lib/rbs/ast/declarations.rb +++ b/lib/rbs/ast/declarations.rb @@ -81,6 +81,22 @@ def to_json(state = _ = nil) location: location }.to_json(state) end + + def self.new(name: , args:, location:) + if name.data? + superclass = super(name: name, args: [], location: location) + + return DataDecl.new(superclass, args: args, location: location) + end + + if name.struct? + superclass = super(name: name, args: [], location: location) + + return StructDecl.new(superclass, args: args, location: location) + end + + super + end end include NestedDeclarationHelper @@ -462,6 +478,1145 @@ def to_json(state = _ = nil) }.to_json(state) end end + + class DataDecl < Class + + def initialize(superklass, args: , location:) + + args.transform_values! do |(type, required)| + required ? type : Types::Optional.new(type: type, location: type.location) + end + + # attribute readers + members = args.map do |k, type| + Members::AttrReader.new( + name: k, + type: type, + ivar_name: :"@#{type}", + kind: :instance, + location: location, + comment: nil, + annotations: [] + ) + end + + # initialize + members << Members::MethodDefinition.new( + name: :initialize, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: args.to_h { |k, type| + [ + k, + # set param + Types::Function::Param.new( + name: nil, + type: type, + location: location + ) + ] + }, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Bases::Void.new(location: location), + ), + location: location, + block: nil, + ), + annotations: [] + ), + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_positionals: args.map { |k, type| + # set param + Types::Function::Param.new( + name: k, + type: type, + location: location + ) + }, + required_keywords: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Bases::Void.new(location: location), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # members + members << Members::MethodDefinition.new( + name: :members, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::ClassInstance.new( + name: BuiltinNames::Array, + args: [RBS::Types::ClassInstance.new(name: BuiltinNames::Symbol, args: [], location: location)], + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # deconstruct + members << Members::MethodDefinition.new( + name: :deconstruct, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Tuple.new( + types: args.values.map do |type| + RBS::Types::ClassInstance.new(name:type, args: [], location: location) + end, + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # deconstruct_keys + members << Members::MethodDefinition.new( + name: :deconstruct_keys, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [ + Types::Function::Param.new( + name: nil, + type: RBS::Types::Bases::Nil.new(location: location), + location: location + ) + ], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Record.new( + all_fields: args.to_h do |k, v| + [ + k, + [ + RBS::Types::ClassInstance.new(name: v, args: [], location: location), + true + ] + ] + end, + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ), + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [ + Types::Function::Param.new( + name: :names, + type: RBS::Types::ClassInstance.new( + name: BuiltinNames::Array, + location: location, + args: [ + RBS::Types::ClassInstance.new( + name: BuiltinNames::Symbol, + args: [], + location: location + ) + ] + ), + location: location + ) + ], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::ClassInstance.new( + name: BuiltinNames::Hash, + location: location, + args: [ + RBS::Types::ClassInstance.new( + name: BuiltinNames::Symbol, + args: [], + location: location + ), + RBS::Types::ClassInstance.new( + name: RBS::Types::Bases::Any.new(location: location), + args: [], + location: location + ) + ] + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # with + members << Members::MethodDefinition.new( + name: :with, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: args.to_h do |k, v| + [ + k, + RBS::Types::Function::Param.new( + name: nil, + type: RBS::Types::ClassInstance.new( + name: v, + args: [], + location: location + ), + location: location + ) + ] + end, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Bases::Instance.new( + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # .[] + members << Members::MethodDefinition.new( + name: :[], + kind: :singleton, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: args.map do |k, v| + Types::Function::Param.new( + name: k, + type: RBS::Types::ClassInstance.new( + name: v, + args: [], + location: location + ), + location: location + ) + end, + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Bases::Instance.new( + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ), + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + optional_keywords: {}, + required_positionals: [], + required_keywords: args.to_h do |k, v| + [ + k, + RBS::Types::Function::Param.new( + name: nil, + type: RBS::Types::ClassInstance.new( + name: v, + args: [], + location: location + ), + location: location + ) + ] + end, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Bases::Instance.new( + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # .members + members << Members::MethodDefinition.new( + name: :members, + kind: :singleton, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::ClassInstance.new( + name: BuiltinNames::Array, + args: [RBS::Types::ClassInstance.new(name: BuiltinNames::Symbol, args: [], location: location)], + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + super( + name: nil, + type_params: nil, + super_class: superklass, + annotations: nil, + comment: nil, + location: location, + members: members + ) + end + end + + class StructDecl < Class + + def initialize(superklass, args: , location:) + + args.transform_values! do |(type, required)| + required ? type : Types::Optional.new(type: type, location: type.location) + end + + # attribute accessors + members = args.map do |k, type| + Members::AttrAccessor.new( + name: k, + type: type, + ivar_name: :"@#{type}", + kind: :instance, + location: location, + comment: nil, + annotations: [] + ) + end + + # initialize + members << Members::MethodDefinition.new( + name: :initialize, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: args.to_h { |k, type| + [ + k, + # set param + Types::Function::Param.new( + name: nil, + type: type, + location: location + ) + ] + }, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Bases::Void.new(location: location), + ), + location: location, + block: nil, + ), + annotations: [] + ), + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_positionals: args.map { |k, type| + # set param + Types::Function::Param.new( + name: k, + type: type, + location: location + ) + }, + required_keywords: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Bases::Void.new(location: location), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # [] + members << Members::MethodDefinition.new( + name: :[], + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: args.map do |k, type| + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_positionals: [ + Types::Function::Param.new( + name: :key, + type: RBS::Types::Union.new( + types: [ + RBS::Types::Literal.new(literal: k, location: location), + RBS::Types::Literal.new(literal: k.to_s, location: location), + ], + location: location + ), + location: location + ) + ], + required_keywords: {}, + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::ClassInstance.new(name: type, args: [], location: location) + ), + location: location, + block: nil + ), + annotations: [] + ) + end + ) + + # []= + members << Members::MethodDefinition.new( + name: :[]=, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: args.map do |k, type| + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_positionals: [ + Types::Function::Param.new( + name: :key, + type: RBS::Types::Union.new( + types: [ + RBS::Types::Literal.new(literal: k, location: location), + RBS::Types::Literal.new(literal: k.to_s, location: location), + ], + location: location + ), + location: location + ), + Types::Function::Param.new( + name: :value, + type: type, + location: location + ) + ], + required_keywords: {}, + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::ClassInstance.new(name: type, args: [], location: location) + ), + location: location, + block: nil + ), + annotations: [] + ) + end + ) + + # size + members << Members::MethodDefinition.new( + name: :size, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::ClassInstance.new( + name: BuiltinNames::Integer, + args: [], + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # to_a + members << Members::MethodDefinition.new( + name: :to_a, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Tuple.new( + types: args.values.map do |type| + RBS::Types::ClassInstance.new(name:type, args: [], location: location) + end, + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # dig + members << Members::MethodDefinition.new( + name: :dig, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_positionals: [ + Types::Function::Param.new( + name: :key, + type: RBS::Types::Union.new( + types: args.each_key.flat_map do |k| + [ + RBS::Types::Literal.new(literal: k, location: location), + RBS::Types::Literal.new(literal: k.to_s, location: location) + ] + end, + location: location + ), + location: location + ) + ], + required_keywords: {}, + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: RBS::Types::Function::Param.new( + name: nil, + location: location, + type: RBS::Types::Bases::Any.new(location: location) + ), + trailing_positionals: [], + return_type: RBS::Types::Bases::Any.new(location: location) + ), + location: location, + block: nil + ), + annotations: [] + ) + ] + ) + + # members + members << Members::MethodDefinition.new( + name: :members, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::ClassInstance.new( + name: BuiltinNames::Array, + args: [RBS::Types::ClassInstance.new(name: BuiltinNames::Symbol, args: [], location: location)], + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # values_at + members << Members::MethodDefinition.new( + name: :values_at, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: RBS::Types::Function::Param.new( + name: :keys, + location: location, + type: RBS::Types::Union.new( + location: location, + types: [ + RBS::Types::ClassInstance.new(args: [], location: location, name: BuiltinNames::Symbol), + RBS::Types::ClassInstance.new(args: [], location: location, name: BuiltinNames::String) + ] + ) + ), + trailing_positionals: [], + return_type: RBS::Types::ClassInstance.new( + name: BuiltinNames::Array, + args: [RBS::Types::Bases::Any.new(location: location)], + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # deconstruct + members << Members::MethodDefinition.new( + name: :deconstruct, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Tuple.new( + types: args.values.map do |type| + RBS::Types::ClassInstance.new(name:type, args: [], location: location) + end, + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # deconstruct_keys + members << Members::MethodDefinition.new( + name: :deconstruct_keys, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [ + Types::Function::Param.new( + name: nil, + type: RBS::Types::Bases::Nil.new(location: location), + location: location + ) + ], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Record.new( + all_fields: args.to_h do |k, v| + [ + k, + [ + RBS::Types::ClassInstance.new(name: v, args: [], location: location), + true + ] + ] + end, + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ), + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [ + Types::Function::Param.new( + name: :names, + type: RBS::Types::ClassInstance.new( + name: BuiltinNames::Array, + location: location, + args: [ + RBS::Types::ClassInstance.new( + name: BuiltinNames::Symbol, + args: [], + location: location + ) + ] + ), + location: location + ) + ], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::ClassInstance.new( + name: BuiltinNames::Hash, + location: location, + args: [ + RBS::Types::ClassInstance.new( + name: BuiltinNames::Symbol, + args: [], + location: location + ), + RBS::Types::ClassInstance.new( + name: RBS::Types::Bases::Any.new(location: location), + args: [], + location: location + ) + ] + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # with + members << Members::MethodDefinition.new( + name: :with, + kind: :instance, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: args.to_h do |k, v| + [ + k, + RBS::Types::Function::Param.new( + name: nil, + type: RBS::Types::ClassInstance.new( + name: v, + args: [], + location: location + ), + location: location + ) + ] + end, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Bases::Instance.new( + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # .[] + members << Members::MethodDefinition.new( + name: :[], + kind: :singleton, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: args.map do |k, v| + Types::Function::Param.new( + name: k, + type: RBS::Types::ClassInstance.new( + name: v, + args: [], + location: location + ), + location: location + ) + end, + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Bases::Instance.new( + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ), + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + optional_keywords: {}, + required_positionals: [], + required_keywords: args.to_h do |k, v| + [ + k, + RBS::Types::Function::Param.new( + name: nil, + type: RBS::Types::ClassInstance.new( + name: v, + args: [], + location: location + ), + location: location + ) + ] + end, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Bases::Instance.new( + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # .members + members << Members::MethodDefinition.new( + name: :members, + kind: :singleton, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::ClassInstance.new( + name: BuiltinNames::Array, + args: [RBS::Types::ClassInstance.new(name: BuiltinNames::Symbol, args: [], location: location)], + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + # .keyword_init? + members << Members::MethodDefinition.new( + name: :keyword_init?, + kind: :singleton, + location: location, + overloading: false, + comment: nil, + annotations: nil, + visibility: nil, + overloads: [ + Members::MethodDefinition::Overload.new( + method_type: MethodType.new( + type_params: [], + type: Types::Function.new( + required_keywords: {}, + required_positionals: [], + optional_keywords: {}, + optional_positionals: [], + rest_keywords: nil, + rest_positionals: nil, + trailing_positionals: [], + return_type: RBS::Types::Alias.new( + name: TypeName.new(name: :boolish, namespace: Namespace.root), + args: [], + location: location + ), + ), + location: location, + block: nil, + ), + annotations: [] + ) + ] + ) + + super( + name: nil, + type_params: nil, + super_class: superklass, + annotations: nil, + comment: nil, + location: location, + members: members + ) + end + end end end end diff --git a/lib/rbs/builtin_names.rb b/lib/rbs/builtin_names.rb index b36d898b0..a05fd2a9f 100644 --- a/lib/rbs/builtin_names.rb +++ b/lib/rbs/builtin_names.rb @@ -54,5 +54,6 @@ def self.define(name, namespace: Namespace.root) TrueClass = Name.define(:TrueClass) FalseClass = Name.define(:FalseClass) Numeric = Name.define(:Numeric) + Data = Name.define(:Data) end end diff --git a/lib/rbs/type_name.rb b/lib/rbs/type_name.rb index e2aa17cf9..2f6ee7717 100644 --- a/lib/rbs/type_name.rb +++ b/lib/rbs/type_name.rb @@ -52,6 +52,14 @@ def alias? kind == :alias end + def data? + class? && namespace.empty? && name == :Data + end + + def struct? + class? && namespace.empty? && name == :Struct + end + def absolute! self.class.new(namespace: namespace.absolute!, name: name) end diff --git a/test/rbs/parser_test.rb b/test/rbs/parser_test.rb index 89a7670f2..4a534d360 100644 --- a/test/rbs/parser_test.rb +++ b/test/rbs/parser_test.rb @@ -438,58 +438,228 @@ class Foo < Data(a: Integer) assert_equal TypeName("Foo"), decl.name assert_predicate decl.type_params, :empty? assert_nil decl.super_class.name - assert_equal TypeName("Data"), decl.super_class.superclass.name + assert_equal TypeName("Data"), decl.super_class.super_class.name - assert_equal 8, decl.members.size + members = decl.super_class.members - decl.members[0].tap do |member| + # assert_equal 8, members.size + + members[0].tap do |member| assert_instance_of RBS::AST::Members::AttrReader, member assert_equal :instance, member.kind assert_equal :a, member.name assert_equal "Integer", member.type.to_s end - decl.members[1].tap do |member| + members[1].tap do |member| assert_instance_of RBS::AST::Members::MethodDefinition, member - assert_equal :method, member.kind + assert_equal :instance, member.kind assert_equal :initialize, member.name - assert_equal ["(::Integer) -> void | (id: ::Integer) -> void"], member.method_types.map(&:to_s) + assert_equal 2, member.overloads.size + assert_equal "(a: Integer) -> void", member.overloads[0].method_type.to_s + assert_equal"(Integer a) -> void", member.overloads[1].method_type.to_s end - decl.members[2].tap do |member| + members[2].tap do |member| assert_instance_of RBS::AST::Members::MethodDefinition, member - assert_equal :method, member.kind + assert_equal :instance, member.kind assert_equal :members, member.name - assert_equal ["() -> Array[Symbol]"], member.method_types.map(&:to_s) + assert_equal 1, member.overloads.size + assert_equal "() -> ::Array[::Symbol]", member.overloads[0].method_type.to_s end - decl.members[3].tap do |member| + members[3].tap do |member| assert_instance_of RBS::AST::Members::MethodDefinition, member - assert_equal :method, member.kind + assert_equal :instance, member.kind assert_equal :deconstruct, member.name - assert_equal ["() -> [Integer]"], member.method_types.map(&:to_s) + assert_equal 1, member.overloads.size + assert_equal "() -> [ Integer ]", member.overloads[0].method_type.to_s end - decl.members[4].tap do |member| + members[4].tap do |member| assert_instance_of RBS::AST::Members::MethodDefinition, member - assert_equal :method, member.kind + assert_equal :instance, member.kind assert_equal :deconstruct_keys, member.name - assert_equal ["(nil) -> {a: Integer} | (Array(Symbol)) -> Hash[untyped]"], member.method_types.map(&:to_s) + assert_equal 2, member.overloads.size + assert_equal "(nil) -> { a: Integer }", member.overloads[0].method_type.to_s + assert_equal"(::Array[::Symbol] names) -> ::Hash[::Symbol, untyped]", member.overloads[1].method_type.to_s end - decl.members[5].tap do |member| + members[5].tap do |member| assert_instance_of RBS::AST::Members::MethodDefinition, member - assert_equal :method, member.kind + assert_equal :instance, member.kind assert_equal :with, member.name - assert_equal ["(?a: Integer) -> Foo"], member.method_types.map(&:to_s) + assert_equal 1, member.overloads.size + assert_equal "(?a: Integer) -> instance", member.overloads[0].method_type.to_s + end + + members[6].tap do |member| + # as funcall: Foo[1] + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :singleton, member.kind + assert_equal :[], member.name + assert_equal 2, member.overloads.size + assert_equal "(Integer a) -> instance", member.overloads[0].method_type.to_s + assert_equal "(a: Integer) -> instance", member.overloads[1].method_type.to_s + end + + members[7].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :singleton, member.kind + assert_equal :members, member.name + assert_equal 1, member.overloads.size + assert_equal "() -> ::Array[::Symbol]", member.overloads[0].method_type.to_s end end + end + end - decls[1].tap do |decl| - # as funcall: Foo[1] - assert_instance_of RBS::Types::UntypedFunction, decl.block.type + def test_struct_class_decl + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| + class Foo < Struct(a: Integer) + end + RBS + decls[0].tap do |decl| + assert_instance_of RBS::AST::Declarations::Class, decl assert_equal TypeName("Foo"), decl.name - assert_equal ["(::Integer a) -> Foo |(a: ::Integer) -> Foo"], member.method_types.map(&:to_s) + assert_predicate decl.type_params, :empty? + assert_nil decl.super_class.name + assert_equal TypeName("Struct"), decl.super_class.super_class.name + + members = decl.super_class.members + + # assert_equal 8, members.size + + members[0].tap do |member| + assert_instance_of RBS::AST::Members::AttrAccessor, member + assert_equal :instance, member.kind + assert_equal :a, member.name + assert_equal "Integer", member.type.to_s + end + + members[1].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :initialize, member.name + assert_equal 2, member.overloads.size + assert_equal "(a: Integer) -> void", member.overloads[0].method_type.to_s + assert_equal"(Integer a) -> void", member.overloads[1].method_type.to_s + end + + members[2].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :[], member.name + assert_equal 1, member.overloads.size + assert_equal "(:a | \"a\" key) -> Integer", member.overloads[0].method_type.to_s + end + + members[3].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :[]=, member.name + assert_equal 1, member.overloads.size + assert_equal "(:a | \"a\" key, Integer value) -> Integer", member.overloads[0].method_type.to_s + end + + members[4].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :size, member.name + assert_equal 1, member.overloads.size + assert_equal "() -> ::Integer", member.overloads[0].method_type.to_s + end + + members[5].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :to_a, member.name + assert_equal 1, member.overloads.size + assert_equal "() -> [ Integer ]", member.overloads[0].method_type.to_s + end + + members[6].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :dig, member.name + assert_equal 1, member.overloads.size + assert_equal "(:a | \"a\" key, *untyped) -> untyped", member.overloads[0].method_type.to_s + end + + members[7].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :members, member.name + assert_equal 1, member.overloads.size + assert_equal "() -> ::Array[::Symbol]", member.overloads[0].method_type.to_s + end + + # members[8].tap do |member| + # assert_instance_of RBS::AST::Members::MethodDefinition, member + # assert_equal :instance, member.kind + # assert_equal :select, member.name + # assert_equal 1, member.overloads.size + # assert_equal "() { (Integer) -> void } -> Array[untyped]", member.overloads[0].method_type.to_s + # end + + members[8].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :values_at, member.name + assert_equal 1, member.overloads.size + assert_equal "(*::Symbol | ::String keys) -> ::Array[untyped]", member.overloads[0].method_type.to_s + end + + members[9].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :deconstruct, member.name + assert_equal 1, member.overloads.size + assert_equal "() -> [ Integer ]", member.overloads[0].method_type.to_s + end + + members[10].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :deconstruct_keys, member.name + assert_equal 2, member.overloads.size + assert_equal "(nil) -> { a: Integer }", member.overloads[0].method_type.to_s + assert_equal"(::Array[::Symbol] names) -> ::Hash[::Symbol, untyped]", member.overloads[1].method_type.to_s + end + + members[11].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :instance, member.kind + assert_equal :with, member.name + assert_equal 1, member.overloads.size + assert_equal "(?a: Integer) -> instance", member.overloads[0].method_type.to_s + end + + members[12].tap do |member| + # as funcall: Foo[1] + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :singleton, member.kind + assert_equal :[], member.name + assert_equal 2, member.overloads.size + assert_equal "(Integer a) -> instance", member.overloads[0].method_type.to_s + assert_equal "(a: Integer) -> instance", member.overloads[1].method_type.to_s + end + + members[13].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :singleton, member.kind + assert_equal :members, member.name + assert_equal 1, member.overloads.size + assert_equal "() -> ::Array[::Symbol]", member.overloads[0].method_type.to_s + end + + members[14].tap do |member| + assert_instance_of RBS::AST::Members::MethodDefinition, member + assert_equal :singleton, member.kind + assert_equal :keyword_init?, member.name + assert_equal 1, member.overloads.size + assert_equal "() -> ::boolish", member.overloads[0].method_type.to_s + end end end end