From 145dcc29f65afdd1051889f1b40da51e6432e067 Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Thu, 2 Feb 2023 16:42:37 +0900 Subject: [PATCH 1/7] Add AST --- lib/rbs.rb | 1 + lib/rbs/ast/directives.rb | 39 +++++++++++++++++++++++++++ sig/directives.rbs | 57 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 lib/rbs/ast/directives.rb create mode 100644 sig/directives.rbs diff --git a/lib/rbs.rb b/lib/rbs.rb index 11a9c3290..a49650b4a 100644 --- a/lib/rbs.rb +++ b/lib/rbs.rb @@ -17,6 +17,7 @@ require "rbs/types" require "rbs/method_type" require "rbs/ast/type_param" +require "rbs/ast/directives" require "rbs/ast/declarations" require "rbs/ast/members" require "rbs/ast/annotation" diff --git a/lib/rbs/ast/directives.rb b/lib/rbs/ast/directives.rb new file mode 100644 index 000000000..d99828809 --- /dev/null +++ b/lib/rbs/ast/directives.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module RBS + module AST + module Directives + class Base + end + + class Use < Base + class SingleClause + attr_reader :type_name, :new_name, :location + + def initialize(type_name:, new_name:, location:) + @type_name = type_name + @new_name = new_name + @location = location + end + end + + class WildcardClause + attr_reader :namespace, :location + + def initialize(namespace:, location:) + @location = location + @namespace = namespace + end + end + + attr_reader :clauses, :location + + def initialize(clauses:, location:) + @clauses = clauses + @location = location + end + end + + end + end +end diff --git a/sig/directives.rbs b/sig/directives.rbs new file mode 100644 index 000000000..38597e545 --- /dev/null +++ b/sig/directives.rbs @@ -0,0 +1,57 @@ +module RBS + module AST + module Directives + type t = Use + + class Base + end + + class Use < Base + type clause = SingleClause | WildcardClause + + class SingleClause + # Foo::Bar + # ^^^^^^^^ type_name + # + # Foo::Bar as X + # ^^ keyword + # ^ new_name + # + type loc = Location[:type_name, :keyword | :new_name] + + attr_reader type_name: TypeName + + attr_reader new_name: Symbol? + + attr_reader location: loc? + + def initialize: (type_name: TypeName, new_name: Symbol?, location: loc?) -> void + end + + class WildcardClause + # Foo::Bar::* + # ^^^^^^^^^^ namespace + # ^ star + # + type loc = Location[:namespace | :star, bot] + + attr_reader namespace: Namespace + + attr_reader location: loc? + + def initialize: (namespace: Namespace, location: loc?) -> void + end + + # use Foo + # ^^^ keyword + type loc = Location[:keyword, bot] + + attr_reader clauses: Array[clause] + + attr_reader location: loc? + + def initialize: (clauses: Array[clause], location: loc?) -> void + end + end + end +end From 398f38db5a3413fb374adbdb7d97ad4577812929 Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Thu, 2 Feb 2023 17:07:54 +0900 Subject: [PATCH 2/7] Fix parser type --- ext/rbs_extension/parser.c | 26 +++--- lib/rbs/annotate/rdoc_annotator.rb | 2 +- lib/rbs/environment_loader.rb | 4 +- lib/rbs/parser_aux.rb | 14 +-- lib/rbs/sorter.rb | 2 +- lib/rdoc_plugin/parser.rb | 4 +- sig/parser.rbs | 23 ++--- test/rbs/annotate/rdoc_annotator_test.rb | 3 +- test/rbs/definition_builder_test.rb | 6 +- test/rbs/environment_test.rb | 36 ++++---- test/rbs/locator_test.rb | 2 +- test/rbs/parser_test.rb | 38 ++++---- test/rbs/schema_test.rb | 18 ++-- test/rbs/signature_parsing_test.rb | 110 +++++++++++------------ test/rbs/type_parsing_test.rb | 4 +- test/rbs/writer_test.rb | 6 +- 16 files changed, 147 insertions(+), 151 deletions(-) diff --git a/ext/rbs_extension/parser.c b/ext/rbs_extension/parser.c index c3cf0a5ef..321a133fc 100644 --- a/ext/rbs_extension/parser.c +++ b/ext/rbs_extension/parser.c @@ -2561,17 +2561,21 @@ VALUE parse_decl(parserstate *state) { } VALUE parse_signature(parserstate *state) { + VALUE dirs = rb_ary_new(); VALUE decls = rb_ary_new(); while (state->next_token.type != pEOF) { rb_ary_push(decls, parse_decl(state)); } - return decls; + VALUE ret = rb_ary_new(); + rb_ary_push(ret, dirs); + rb_ary_push(ret, decls); + return ret; } static VALUE -rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE requires_eof) +rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables) { parserstate *parser = alloc_parser(buffer, FIX2INT(start_pos), FIX2INT(end_pos), variables); @@ -2581,17 +2585,13 @@ rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, V VALUE type = parse_type(parser); - if (RTEST(requires_eof)) { - parser_advance_assert(parser, pEOF); - } - free_parser(parser); return type; } static VALUE -rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE requires_eof) +rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables) { parserstate *parser = alloc_parser(buffer, FIX2INT(start_pos), FIX2INT(end_pos), variables); @@ -2601,10 +2601,6 @@ rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end VALUE method_type = parse_method_type(parser); - if (RTEST(requires_eof)) { - parser_advance_assert(parser, pEOF); - } - free_parser(parser); return method_type; @@ -2614,15 +2610,15 @@ static VALUE rbsparser_parse_signature(VALUE self, VALUE buffer, VALUE end_pos) { parserstate *parser = alloc_parser(buffer, 0, FIX2INT(end_pos), Qnil); - VALUE signature = parse_signature(parser); + VALUE pair = parse_signature(parser); free_parser(parser); - return signature; + return pair; } void rbs__init_parser(void) { RBS_Parser = rb_define_class_under(RBS, "Parser", rb_cObject); - rb_define_singleton_method(RBS_Parser, "_parse_type", rbsparser_parse_type, 5); - rb_define_singleton_method(RBS_Parser, "_parse_method_type", rbsparser_parse_method_type, 5); + rb_define_singleton_method(RBS_Parser, "_parse_type", rbsparser_parse_type, 4); + rb_define_singleton_method(RBS_Parser, "_parse_method_type", rbsparser_parse_method_type, 4); rb_define_singleton_method(RBS_Parser, "_parse_signature", rbsparser_parse_signature, 2); } diff --git a/lib/rbs/annotate/rdoc_annotator.rb b/lib/rbs/annotate/rdoc_annotator.rb index a1dffd518..68c06241b 100644 --- a/lib/rbs/annotate/rdoc_annotator.rb +++ b/lib/rbs/annotate/rdoc_annotator.rb @@ -16,7 +16,7 @@ def initialize(source:) def annotate_file(path, preserve:) content = path.read() - decls = Parser.parse_signature(content) + _, _, decls = Parser.parse_signature(content) annotate_decls(decls) diff --git a/lib/rbs/environment_loader.rb b/lib/rbs/environment_loader.rb index 1216cbd04..0de0b1b01 100644 --- a/lib/rbs/environment_loader.rb +++ b/lib/rbs/environment_loader.rb @@ -160,7 +160,9 @@ def each_decl files << path buffer = Buffer.new(name: path.to_s, content: path.read(encoding: "UTF-8")) - Parser.parse_signature(buffer).each do |decl| + _, _dirs, decls = Parser.parse_signature(buffer) + + decls.each do |decl| yield decl, buffer, source, path end end diff --git a/lib/rbs/parser_aux.rb b/lib/rbs/parser_aux.rb index 731c3fbf3..19e5e0840 100644 --- a/lib/rbs/parser_aux.rb +++ b/lib/rbs/parser_aux.rb @@ -2,19 +2,21 @@ module RBS class Parser - def self.parse_type(source, line: nil, column: nil, range: nil, variables: []) + def self.parse_type(source, range: 0..., variables: []) buf = buffer(source) - _parse_type(buf, range&.begin || 0, range&.end || buf.last_position, variables, range.nil?) + _parse_type(buf, range.begin || 0, range.end || buf.last_position, variables) end - def self.parse_method_type(source, line: nil, column: nil, range: nil, variables: []) + def self.parse_method_type(source, range: 0..., variables: []) buf = buffer(source) - _parse_method_type(buf, range&.begin || 0, range&.end || buf.last_position, variables, range.nil?) + _parse_method_type(buf, range.begin || 0, range.end || buf.last_position, variables) end - def self.parse_signature(source, line: nil, column: nil) + def self.parse_signature(source) buf = buffer(source) - _parse_signature(buf, buf.last_position) + dirs, decls = _parse_signature(buf, buf.last_position) + + [buf, dirs, decls] end def self.buffer(source) diff --git a/lib/rbs/sorter.rb b/lib/rbs/sorter.rb index e351ada01..59bcf17d7 100644 --- a/lib/rbs/sorter.rb +++ b/lib/rbs/sorter.rb @@ -15,7 +15,7 @@ def run stdout.puts "Opening #{path}..." buffer = Buffer.new(name: path, content: path.read) - sigs = Parser.parse_signature(buffer) + _, _, sigs = Parser.parse_signature(buffer) sigs.each do |m| sort_decl! m diff --git a/lib/rdoc_plugin/parser.rb b/lib/rdoc_plugin/parser.rb index 71793af24..12006780b 100644 --- a/lib/rdoc_plugin/parser.rb +++ b/lib/rdoc_plugin/parser.rb @@ -14,8 +14,8 @@ def initialize(top_level, content) end def scan - ast = ::RBS::Parser.parse_signature(@content) - ast.each do |decl| + _, _, decls = ::RBS::Parser.parse_signature(@content) + decls.each do |decl| parse_member(decl: decl, context: @top_level) end @top_level diff --git a/sig/parser.rbs b/sig/parser.rbs index cd64735f5..1a8695607 100644 --- a/sig/parser.rbs +++ b/sig/parser.rbs @@ -6,15 +6,13 @@ module RBS # If no token is left in the input, it returns `nil`. # # ```ruby + # RBS::Parser.parse_method_type("() -> void") # => `() -> void` # RBS::Parser.parse_method_type("() -> void", range: 0...) # => `() -> void` # RBS::Parser.parse_method_type("() -> void () -> String", range: 11...) # => `() -> String` # RBS::Parser.parse_method_type("() -> void () -> String", range: 23...) # => nil # ``` # - # `line` and `column` is deprecated and are ignored. - # - def self.parse_method_type: (Buffer | String, range: Range[Integer?], ?variables: Array[Symbol]) -> MethodType? - | (Buffer | String, ?line: top, ?column: top, ?variables: Array[Symbol]) -> MethodType + def self.parse_method_type: (Buffer | String, ?range: Range[Integer?], ?variables: Array[Symbol]) -> MethodType? # Parse a type and return it # @@ -22,22 +20,17 @@ module RBS # If no token is left in the input, it returns `nil`. # # ```ruby + # RBS::Parser.parse_type("String") # => `String` # RBS::Parser.parse_type("String", range: 0...) # => `String` # RBS::Parser.parse_type("String Integer", pos: 7...) # => `Integer` # RBS::Parser.parse_type("String Integer", pos: 14...) # => nil # ``` # - # `line` and `column` is deprecated and are ignored. - # - def self.parse_type: (Buffer | String, range: Range[Integer?], ?variables: Array[Symbol]) -> Types::t? - | (Buffer | String, ?line: top, ?column: top, ?variables: Array[Symbol]) -> Types::t + def self.parse_type: (Buffer | String, ?range: Range[Integer?], ?variables: Array[Symbol]) -> Types::t? # Parse whole RBS file and return an array of declarations # - # `line` and `column` is deprecated and are ignored. - # - def self.parse_signature: (Buffer | String) -> Array[AST::Declarations::t] - | (Buffer | String, ?line: top, ?column: top) -> Array[AST::Declarations::t] + def self.parse_signature: (Buffer | String) -> [Buffer, Array[AST::Directives::t], Array[AST::Declarations::t]] KEYWORDS: Hash[String, bot] @@ -45,11 +38,11 @@ module RBS def self.buffer: (String | Buffer source) -> Buffer - def self._parse_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, boolish eof) -> Types::t? + def self._parse_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables) -> Types::t? - def self._parse_method_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, boolish eof) -> MethodType? + def self._parse_method_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables) -> MethodType? - def self._parse_signature: (Buffer, Integer end_pos) -> Array[AST::Declarations::t] + def self._parse_signature: (Buffer, Integer end_pos) -> [Array[AST::Directives::t], Array[AST::Declarations::t]] class LocatedValue end diff --git a/test/rbs/annotate/rdoc_annotator_test.rb b/test/rbs/annotate/rdoc_annotator_test.rb index 1ef3b808c..6d7102d30 100644 --- a/test/rbs/annotate/rdoc_annotator_test.rb +++ b/test/rbs/annotate/rdoc_annotator_test.rb @@ -28,7 +28,8 @@ def load_source(files) end def parse_rbs(src) - RBS::Parser.parse_signature(src) + _, _, decls = RBS::Parser.parse_signature(src) + decls end def tester(*false_paths) diff --git a/test/rbs/definition_builder_test.rb b/test/rbs/definition_builder_test.rb index f29752bec..1896db103 100644 --- a/test/rbs/definition_builder_test.rb +++ b/test/rbs/definition_builder_test.rb @@ -2228,8 +2228,10 @@ class Foo include Mod end DEF - RBS::Parser.parse_signature(rbs).each do |decl| - env << decl + RBS::Parser.parse_signature(rbs).tap do |_, _, decls| + decls.each do |decl| + env << decl + end end definition_builder = RBS::DefinitionBuilder.new(env: env.resolve_type_names) definition_builder.build_instance(TypeName("::Foo")).tap do |defn| diff --git a/test/rbs/environment_test.rb b/test/rbs/environment_test.rb index fe0ee8168..14a1dddfb 100644 --- a/test/rbs/environment_test.rb +++ b/test/rbs/environment_test.rb @@ -8,7 +8,7 @@ class RBS::EnvironmentTest < Test::Unit::TestCase InvalidTypeApplicationError = RBS::InvalidTypeApplicationError def test_entry_context - decls = RBS::Parser.parse_signature(< void end @@ -312,7 +312,7 @@ module Bar : _Animal def test_absolute_type env = Environment.new - decls = RBS::Parser.parse_signature(< Integer end EOF - RBS::Parser.parse_signature(foo).each do |decl| + RBS::Parser.parse_signature(foo)[2].each do |decl| env << decl end @@ -460,7 +460,7 @@ def world: () -> void end EOF - RBS::Parser.parse_signature(bar).each do |decl| + RBS::Parser.parse_signature(bar)[2].each do |decl| env << decl end @@ -478,7 +478,7 @@ def world: () -> void def test_absolute_type_generics_upper_bound env = Environment.new - decls = RBS::Parser.parse_signature(< bool end @@ -516,7 +516,7 @@ def test: [B < ::Bar[::_Equatable]] (A, B) -> bool end def test_normalize_module_name - decls = RBS::Parser.parse_signature(<<~EOF) + _, _, decls = RBS::Parser.parse_signature(<<~EOF) class Foo module Bar module Baz diff --git a/test/rbs/locator_test.rb b/test/rbs/locator_test.rb index c50840bfc..0b1bac287 100644 --- a/test/rbs/locator_test.rb +++ b/test/rbs/locator_test.rb @@ -5,7 +5,7 @@ class RBS::LocatorTest < Test::Unit::TestCase include TestHelper def locator(src) - decls = Parser.parse_signature(src) + _, _, decls = Parser.parse_signature(src) Locator.new(decls: decls) end diff --git a/test/rbs/parser_test.rb b/test/rbs/parser_test.rb index 3b7481700..00c7c6356 100644 --- a/test/rbs/parser_test.rb +++ b/test/rbs/parser_test.rb @@ -6,7 +6,7 @@ def buffer(source) end def test_interface - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| interface _Foo[unchecked in A] def bar: [A] () -> A @@ -72,7 +72,7 @@ def test_type_error_for_variables end def test_interface_alias - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| interface _Foo[unchecked in A] alias hello world end @@ -90,7 +90,7 @@ def test_interface_alias end def test_module_decl - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo[X] : String, _Array[Symbol] end RBS @@ -109,7 +109,7 @@ module Foo[X] : String, _Array[Symbol] end def test_module_decl_def - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo[X] : String, _Array[Symbol] def foo: () -> void @@ -125,7 +125,7 @@ def self?.baz: () -> void end def test_module_decl_vars - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo[X] : String, _Array[Symbol] @foo: Integer @@ -141,7 +141,7 @@ module Foo[X] : String, _Array[Symbol] end def test_module_decl_attributes - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo attr_reader string: String attr_writer self.name (): Integer @@ -196,7 +196,7 @@ module Foo end def test_module_decl_public_private - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo public private @@ -212,7 +212,7 @@ module Foo end def test_module_decl_nested - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo type foo = bar @@ -226,7 +226,7 @@ module Foo end def test_module_type_var_decl - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo[A] type t = A @@ -250,7 +250,7 @@ module Foo[A] end def test_module_type_var_ivar - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo[A] @x: A @@x: A @@ -279,7 +279,7 @@ module Foo[A] end def test_module_type_var_attr - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo[A] attr_reader foo: A attr_writer self.bar: A @@ -302,7 +302,7 @@ module Foo[A] end def test_module_type_var_method - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo[A] def foo: () -> A @@ -333,7 +333,7 @@ def self?.baz: () -> A end def test_module_type_var_mixin - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| module Foo[A] include X[A] @@ -364,7 +364,7 @@ module Foo[A] end def test_class_decl - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| class Foo end RBS @@ -376,7 +376,7 @@ class Foo end end - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| class Foo[A] < Bar[A] end RBS @@ -390,7 +390,7 @@ class Foo[A] < Bar[A] end def test_method_name - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| class Foo def |: () -> void def ^: () -> void @@ -436,7 +436,7 @@ def test_parse_type end def test_parse_comment - RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |decls| + RBS::Parser.parse_signature(buffer(<<-RBS)).tap do |_, _, decls| # Hello # World #Yes @@ -466,7 +466,7 @@ def test_type_var end def test_parse_global - RBS::Parser.parse_signature(buffer(< $? $@ $DEBUG $FILENAME $LOAD_PATH $LOADED_FEATURES $PROGRAM_NAME $VERBOSE $\\ $_ $` $stderr $stdin $stdout $~) names.each do |name| - RBS::Parser.parse_signature(buffer("#{name}: untyped")).tap do |decls| + RBS::Parser.parse_signature(buffer("#{name}: untyped")).tap do |_, _, decls| decls[0].tap do |decl| assert_instance_of RBS::AST::Declarations::Global, decl assert_equal name.to_sym, decl.name diff --git a/test/rbs/schema_test.rb b/test/rbs/schema_test.rb index ee6ae3d4a..457c7a8b9 100644 --- a/test/rbs/schema_test.rb +++ b/test/rbs/schema_test.rb @@ -123,12 +123,12 @@ def test_method_type_schema end def test_decls - assert_decl RBS::Parser.parse_signature("type Steep::foo = untyped")[0], :alias - assert_decl RBS::Parser.parse_signature("type Steep::foo[A] = A")[0], :alias + assert_decl RBS::Parser.parse_signature("type Steep::foo = untyped")[2][0], :alias + assert_decl RBS::Parser.parse_signature("type Steep::foo[A] = A")[2][0], :alias - assert_decl RBS::Parser.parse_signature('Steep::VERSION: "1.2.3"')[0], :constant + assert_decl RBS::Parser.parse_signature('Steep::VERSION: "1.2.3"')[2][0], :constant - assert_decl RBS::Parser.parse_signature('$SIZE: Integer?')[0], :global + assert_decl RBS::Parser.parse_signature('$SIZE: Integer?')[2][0], :global end def assert_member(member, name=nil) @@ -143,7 +143,7 @@ def assert_member(member, name=nil) end def test_members - members = RBS::Parser.parse_signature(< Integer end def test_class_decl - decl, = RBS::Parser.parse_signature(< Integer end def test_module_decl - decl, = RBS::Parser.parse_signature(< Integer end def test_interface_decl - decl, = RBS::Parser.parse_signature(< Integer end def test_nested - decl, = RBS::Parser.parse_signature(< void type y[unchecked out T] = ^(T) -> void @@ -95,7 +95,7 @@ def test_type_alias_generic_variance end def test_constant - Parser.parse_signature("FOO: untyped").yield_self do |decls| + Parser.parse_signature("FOO: untyped").tap do |_, _, decls| assert_equal 1, decls.size const_decl = decls[0] @@ -106,7 +106,7 @@ def test_constant assert_equal "FOO: untyped", const_decl.location.source end - Parser.parse_signature("::BAR: untyped").yield_self do |decls| + Parser.parse_signature("::BAR: untyped").tap do |_, _, decls| assert_equal 1, decls.size const_decl = decls[0] @@ -117,7 +117,7 @@ def test_constant assert_equal "::BAR: untyped", const_decl.location.source end - Parser.parse_signature("FOO : untyped").yield_self do |decls| + Parser.parse_signature("FOO : untyped").tap do |_, _, decls| assert_equal 1, decls.size const_decl = decls[0] @@ -128,7 +128,7 @@ def test_constant assert_equal "FOO : untyped", const_decl.location.source end - Parser.parse_signature("::BAR : untyped").yield_self do |decls| + Parser.parse_signature("::BAR : untyped").tap do |_, _, decls| assert_equal 1, decls.size const_decl = decls[0] @@ -141,7 +141,7 @@ def test_constant end def test_global - Parser.parse_signature("$FOO: untyped").yield_self do |decls| + Parser.parse_signature("$FOO: untyped").tap do |_, _, decls| assert_equal 1, decls.size global_decl = decls[0] @@ -154,7 +154,7 @@ def test_global end def test_interface - Parser.parse_signature("interface _Each[A, B] end").yield_self do |decls| + Parser.parse_signature("interface _Each[A, B] end").tap do |_, _, decls| assert_equal 1, decls.size interface_decl = decls[0] @@ -166,7 +166,7 @@ def test_interface assert_equal "interface _Each[A, B] end", interface_decl.location.source end - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| interface _Each[A, B] # # Yield all elements included in `self`. @@ -240,7 +240,7 @@ def self.foo: -> void end def test_module - Parser.parse_signature("module Enumerable[A, B] end").yield_self do |decls| + Parser.parse_signature("module Enumerable[A, B] end").tap do |_, _, decls| assert_equal 1, decls.size module_decl = decls[0] @@ -253,7 +253,7 @@ def test_module assert_equal "module Enumerable[A, B] end", module_decl.location.source end - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| module Enumerable[A, B] : _Each @foo: String self.@bar: Integer @@ -430,7 +430,7 @@ def self?.three: -> bool end def test_module_selfs - Parser.parse_signature(<<-RBS).yield_self do |decls| + Parser.parse_signature(<<-RBS).tap do |_, _, decls| module Enumerable[A, B] : _Each, Object end RBS @@ -451,7 +451,7 @@ module Enumerable[A, B] : _Each, Object end def test_class - Parser.parse_signature("class Array[A] end").yield_self do |decls| + Parser.parse_signature("class Array[A] end").tap do |_, _, decls| assert_equal 1, decls.size decls[0].yield_self do |class_decl| @@ -462,7 +462,7 @@ def test_class end end - Parser.parse_signature("class ::Array[A] < Object[A] end").yield_self do |decls| + Parser.parse_signature("class ::Array[A] < Object[A] end").tap do |_, _, decls| assert_equal 1, decls.size decls[0].yield_self do |class_decl| @@ -478,7 +478,7 @@ def test_class end def test_method_definition - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| class Foo[X, Y] def foo: -> Integer | ?{ -> void } -> Integer @@ -530,7 +530,7 @@ def foo: -> void end def test_private_public - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| class Foo public private @@ -554,7 +554,7 @@ class Foo end def test_private_public_def - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| class Foo public def foo: () -> void private def bar: () -> void @@ -599,7 +599,7 @@ class Foo end def test_private_public_attr - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| class Foo public attr_reader foo: String private attr_reader bar: String @@ -656,7 +656,7 @@ class Foo end def test_alias - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| class Foo def foo: -> String alias bar foo @@ -687,7 +687,7 @@ def foo: -> String end def test_method_names - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| interface _Foo def class: -> String def void: -> String @@ -779,7 +779,7 @@ def _foo!: -> untyped end def test_annotation_on_declaration - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| %a(foo) %a[hello world] class Hello end @@ -828,7 +828,7 @@ module Foo end end def test_attributes - Parser.parse_signature(<<~SIG).tap do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| class Hello attr_reader a: Integer attr_writer b(@B): String @@ -899,7 +899,7 @@ class Hello end def test_annotations_on_members - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| class Hello %a{noreturn} def foo: () -> untyped @@ -946,7 +946,7 @@ def foo: () -> untyped end def test_annotations_on_overload - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| class Hello def foo: %a{noreturn} () -> void | %a{implicitly-returns-nil} %a{primitive:is_a?} (Class) -> bool @@ -966,7 +966,7 @@ def foo: %a{noreturn} () -> void end def test_prepend - Parser.parse_signature(<<~SIG).yield_self do |decls| + Parser.parse_signature(<<~SIG).tap do |_, _, decls| class Foo prepend Foo end @@ -1013,7 +1013,7 @@ def bar: (untyped `type`, void: untyped `void`) -> untyped end def test_class_comment - Parser.parse_signature(<<-EOF).yield_self do |foo_decl,bar_decl| + Parser.parse_signature(<<-EOF).yield_self do |_, _, (foo_decl,bar_decl)| # This is a class. # Foo Bar Baz. class Foo @@ -1041,7 +1041,7 @@ module Bar end def test_member_comment - Parser.parse_signature(<<-EOF).yield_self do |foo_decl,| + Parser.parse_signature(<<-EOF).yield_self do |_, _, (foo_decl)| # This is a class. # Foo Bar Baz. class Foo @@ -1087,7 +1087,7 @@ def hello: () -> void end def test_code_comment - Parser.parse_signature(<<-EOF).yield_self do |foo_decl,| + Parser.parse_signature(<<-EOF).yield_self do |_, _, (foo_decl)| # Passes each element of the collection to the given block. The method # returns `true` if the block never returns `false` or `nil` . If the # block is not given, Ruby adds an implicit block of `{ |obj| obj }` which @@ -1129,7 +1129,7 @@ class Foo end def test_comment_without_leading_space - Parser.parse_signature(<<-EOF).yield_self do |foo_decl,| + Parser.parse_signature(<<-EOF).yield_self do |_, _, (foo_decl)| #This is a class. class Foo #This is a method. @@ -1178,7 +1178,7 @@ def binding: () -> Binding end def test_module_type_param_variance - Parser.parse_signature("interface _Each[A, out B, unchecked in C] end").yield_self do |decls| + Parser.parse_signature("interface _Each[A, out B, unchecked in C] end").tap do |_, _, decls| assert_equal 1, decls.size interface_decl = decls[0] @@ -1204,7 +1204,7 @@ def test_module_type_param_variance end def test_mame - Parser.parse_signature(< String | ... def to_i: () -> Integer @@ -1266,7 +1266,7 @@ def to_i: () -> Integer end def test_generics_type_parameter - Parser.parse_signature(< void @@ -1283,7 +1283,7 @@ def bar: () -> T end def test_proc - Parser.parse_signature(< ^->Integer end @@ -1311,13 +1311,13 @@ class Foo end def test_empty - Parser.parse_signature("").tap do |decls| + Parser.parse_signature("").tap do |_, _, decls| assert_empty decls end end def test_module_self_syntax - Parser.parse_signature(< void @@ -1371,7 +1371,7 @@ def self?.bar: () -> void end def test_var_location - Parser.parse_signature(<<-EOF).tap do |decls| + Parser.parse_signature(<<-EOF).tap do |_, _, decls| module A @foo: Integer self.@bar: String @@ -1406,7 +1406,7 @@ module A end def test_attribute_location - Parser.parse_signature(<<-RBS).tap do |decls| + Parser.parse_signature(<<-RBS).tap do |_, _, decls| module A attr_reader reader1: String attr_reader reader2 : String @@ -1484,7 +1484,7 @@ module A end end - Parser.parse_signature(<<-RBS).tap do |decls| + Parser.parse_signature(<<-RBS).tap do |_, _, decls| module A attr_writer attr1: String attr_writer attr2 : String @@ -1562,7 +1562,7 @@ module A end end - Parser.parse_signature(<<-RBS).tap do |decls| + Parser.parse_signature(<<-RBS).tap do |_, _, decls| module A attr_accessor attr1: String attr_accessor attr2 : String @@ -1642,7 +1642,7 @@ module A end def test_alias_location - Parser.parse_signature(<<-RBS).tap do |decls| + Parser.parse_signature(<<-RBS).tap do |_, _, decls| module A alias foo bar alias self.foo self.bar @@ -1672,7 +1672,7 @@ module A end def test_mixin_location - Parser.parse_signature(<<-EOF).tap do |decls| + Parser.parse_signature(<<-EOF).tap do |_, _, decls| module A include _Foo include _Bar[String] @@ -1735,7 +1735,7 @@ module A end def test_interface_location - Parser.parse_signature(<<-EOF).tap do |decls| + Parser.parse_signature(<<-EOF).tap do |_, _, decls| interface _A end @@ -1779,7 +1779,7 @@ def test_interface_location end def test_module_location - Parser.parse_signature(<<-EOF).tap do |decls| + Parser.parse_signature(<<-EOF).tap do |_, _, decls| module A end @@ -1824,7 +1824,7 @@ module C: BasicObject end end def test_class_location - Parser.parse_signature(<<-EOF).tap do |decls| + Parser.parse_signature(<<-EOF).tap do |_, _, decls| class A end @@ -1877,7 +1877,7 @@ class C < Bar end def test_constant_global_location - Parser.parse_signature(<<-EOF).tap do |decls| + Parser.parse_signature(<<-EOF).tap do |_, _, decls| X: String A::B : String $B: Integer @@ -1906,7 +1906,7 @@ def test_constant_global_location end def test_type_alias_location - Parser.parse_signature(<<-EOF).tap do |decls| + Parser.parse_signature(<<-EOF).tap do |_, _, decls| type foo = Integer EOF decls[0].tap do |decl| @@ -1960,7 +1960,7 @@ def test_underscore_qualified_name end def test_singleton_member_type_variables - Parser.parse_signature(<<-EOF).tap do |decls| + Parser.parse_signature(<<-EOF).tap do |_, _, decls| class Foo[A] @foo: A @@ -2010,7 +2010,7 @@ def self?.foo3: -> A end def test_generics_bound - Parser.parse_signature(<<-EOF).tap do |decls| + Parser.parse_signature(<<-EOF).tap do |_, _, decls| class Foo[X < _Each[Y], Y] def foo: [X < Array[Y]] (X) -> X end @@ -2055,7 +2055,7 @@ class Foo[X < string] end def test_module_alias_decl - Parser.parse_signature(<<~EOF).yield_self do |decls| + Parser.parse_signature(<<~EOF).tap do |_, _, decls| module RBS::Kernel = Kernel EOF @@ -2073,7 +2073,7 @@ module RBS::Kernel = Kernel end def test_class_alias_decl - Parser.parse_signature(<<~EOF).yield_self do |decls| + Parser.parse_signature(<<~EOF).tap do |_, _, decls| class RBS::Object = Object EOF diff --git a/test/rbs/type_parsing_test.rb b/test/rbs/type_parsing_test.rb index 03f14e1e2..6c23fee6b 100644 --- a/test/rbs/type_parsing_test.rb +++ b/test/rbs/type_parsing_test.rb @@ -578,7 +578,7 @@ def test_literal end assert_raises RBS::ParsingError do - Parser.parse_type(":+foo") + Parser.parse_type("[:+foo]") end assert_raises RBS::ParsingError do @@ -692,7 +692,7 @@ def test_type_var end assert_raises RBS::ParsingError do - Parser.parse_type("Array[A]", variables: [:A, :Array]) + Parser.parse_type("(Array[A])", variables: [:A, :Array]) end end diff --git a/test/rbs/writer_test.rb b/test/rbs/writer_test.rb index b1e1a6245..15a8542e7 100644 --- a/test/rbs/writer_test.rb +++ b/test/rbs/writer_test.rb @@ -7,7 +7,7 @@ class RBS::WriterTest < Test::Unit::TestCase Writer = RBS::Writer def format(sig, preserve: false) - Parser.parse_signature(sig).then do |decls| + Parser.parse_signature(sig).then do |_, _, decls| writer = Writer.new(out: StringIO.new).preserve!(preserve: preserve) writer.write(decls) @@ -233,14 +233,14 @@ def foo: [A < _Each[Foo], B < singleton(::Bar)] () -> A def test_smoke Pathname.glob('{stdlib,core,sig}/**/*.rbs').each do |path| - orig_decls = RBS::Parser.parse_signature( + _, _, orig_decls = RBS::Parser.parse_signature( RBS::Buffer.new(name: path, content: path.read) ) io = StringIO.new w = RBS::Writer.new(out: io) w.write(orig_decls) - decls = RBS::Parser.parse_signature(RBS::Buffer.new(name: path, content: io.string)) + _, _, decls = RBS::Parser.parse_signature(RBS::Buffer.new(name: path, content: io.string)) assert_equal orig_decls, decls, "(#{path})" end From c20a24a0b923933a3762b9124b8444ada89a9893 Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Mon, 6 Feb 2023 11:47:03 +0900 Subject: [PATCH 3/7] Implement parser --- ext/rbs_extension/constants.c | 10 + ext/rbs_extension/constants.h | 5 + ext/rbs_extension/lexer.c | 1129 +++++++++++++++------------- ext/rbs_extension/lexer.h | 2 + ext/rbs_extension/lexer.re | 2 + ext/rbs_extension/lexstate.c | 2 + ext/rbs_extension/parser.c | 167 +++- ext/rbs_extension/ruby_objs.c | 26 + ext/rbs_extension/ruby_objs.h | 4 + sig/directives.rbs | 4 + test/rbs/signature_parsing_test.rb | 32 + 11 files changed, 846 insertions(+), 537 deletions(-) diff --git a/ext/rbs_extension/constants.c b/ext/rbs_extension/constants.c index 8bed6de71..7bc6137dc 100644 --- a/ext/rbs_extension/constants.c +++ b/ext/rbs_extension/constants.c @@ -21,6 +21,11 @@ VALUE RBS_AST_Declarations_Class_Super; VALUE RBS_AST_Declarations_ModuleAlias; VALUE RBS_AST_Declarations_ClassAlias; +VALUE RBS_AST_Directives; +VALUE RBS_AST_Directives_Use; +VALUE RBS_AST_Directives_Use_SingleClause; +VALUE RBS_AST_Directives_Use_WildcardClause; + VALUE RBS_AST_Members; VALUE RBS_AST_Members_Alias; VALUE RBS_AST_Members_AttrAccessor; @@ -93,6 +98,11 @@ void rbs__init_constants(void) { RBS_AST_Declarations_ClassAlias = rb_const_get(RBS_AST_Declarations, rb_intern("ClassAlias")); RBS_AST_Declarations_ModuleAlias = rb_const_get(RBS_AST_Declarations, rb_intern("ModuleAlias")); + RBS_AST_Directives = rb_const_get(RBS_AST, rb_intern("Directives")); + RBS_AST_Directives_Use = rb_const_get(RBS_AST_Directives, rb_intern("Use")); + RBS_AST_Directives_Use_SingleClause = rb_const_get(RBS_AST_Directives_Use, rb_intern("SingleClause")); + RBS_AST_Directives_Use_WildcardClause = rb_const_get(RBS_AST_Directives_Use, rb_intern("WildcardClause")); + RBS_AST_Members = rb_const_get(RBS_AST, rb_intern("Members")); RBS_AST_Members_Alias = rb_const_get(RBS_AST_Members, rb_intern("Alias")); RBS_AST_Members_AttrAccessor = rb_const_get(RBS_AST_Members, rb_intern("AttrAccessor")); diff --git a/ext/rbs_extension/constants.h b/ext/rbs_extension/constants.h index d757b4ea1..978bc32d0 100644 --- a/ext/rbs_extension/constants.h +++ b/ext/rbs_extension/constants.h @@ -20,6 +20,11 @@ extern VALUE RBS_AST_Declarations_Module; extern VALUE RBS_AST_Declarations_ModuleAlias; extern VALUE RBS_AST_Declarations_ClassAlias; +extern VALUE RBS_AST_Directives; +extern VALUE RBS_AST_Directives_Use; +extern VALUE RBS_AST_Directives_Use_SingleClause; +extern VALUE RBS_AST_Directives_Use_WildcardClause; + extern VALUE RBS_AST_Members; extern VALUE RBS_AST_Members_Alias; extern VALUE RBS_AST_Members_AttrAccessor; diff --git a/ext/rbs_extension/lexer.c b/ext/rbs_extension/lexer.c index 143822deb..af6c3a254 100644 --- a/ext/rbs_extension/lexer.c +++ b/ext/rbs_extension/lexer.c @@ -116,13 +116,13 @@ token rbsparser_next_token(lexstate *state) { } yy1: rbs_skip(state); -#line 138 "ext/rbs_extension/lexer.re" +#line 140 "ext/rbs_extension/lexer.re" { return next_token(state, pEOF); } #line 122 "ext/rbs_extension/lexer.c" yy2: rbs_skip(state); yy3: -#line 139 "ext/rbs_extension/lexer.re" +#line 141 "ext/rbs_extension/lexer.re" { return next_token(state, ErrorToken); } #line 128 "ext/rbs_extension/lexer.c" yy4: @@ -136,7 +136,7 @@ token rbsparser_next_token(lexstate *state) { if (yych == ' ') goto yy4; } yy5: -#line 137 "ext/rbs_extension/lexer.re" +#line 139 "ext/rbs_extension/lexer.re" { state->start = state->current; goto start; } #line 142 "ext/rbs_extension/lexer.c" yy6: @@ -453,7 +453,7 @@ token rbsparser_next_token(lexstate *state) { } } yy36: -#line 123 "ext/rbs_extension/lexer.re" +#line 125 "ext/rbs_extension/lexer.re" { return next_token(state, tUIDENT); } #line 459 "ext/rbs_extension/lexer.c" yy37: @@ -493,7 +493,7 @@ token rbsparser_next_token(lexstate *state) { } } yy41: -#line 126 "ext/rbs_extension/lexer.re" +#line 128 "ext/rbs_extension/lexer.re" { return next_token(state, tULLIDENT); } #line 499 "ext/rbs_extension/lexer.c" yy42: @@ -514,38 +514,43 @@ token rbsparser_next_token(lexstate *state) { yy44: rbs_skip(state); yych = peek(state); - if (yych == 'l') goto yy112; - if (yych == 't') goto yy113; - goto yy52; + if (yych <= 'r') { + if (yych == 'l') goto yy112; + goto yy52; + } else { + if (yych <= 's') goto yy113; + if (yych <= 't') goto yy115; + goto yy52; + } yy45: -#line 122 "ext/rbs_extension/lexer.re" +#line 124 "ext/rbs_extension/lexer.re" { return next_token(state, tLIDENT); } -#line 524 "ext/rbs_extension/lexer.c" +#line 529 "ext/rbs_extension/lexer.c" yy46: rbs_skip(state); yych = peek(state); - if (yych == 'o') goto yy114; + if (yych == 'o') goto yy116; goto yy52; yy47: rbs_skip(state); yych = peek(state); - if (yych == 'l') goto yy115; + if (yych == 'l') goto yy117; goto yy52; yy48: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy116; + if (yych == 'e') goto yy118; goto yy52; yy49: rbs_skip(state); yych = peek(state); - if (yych == 'n') goto yy117; - if (yych == 'x') goto yy118; + if (yych == 'n') goto yy119; + if (yych == 'x') goto yy120; goto yy52; yy50: rbs_skip(state); yych = peek(state); - if (yych == 'a') goto yy119; + if (yych == 'a') goto yy121; goto yy52; yy51: rbs_skip(state); @@ -574,71 +579,72 @@ token rbsparser_next_token(lexstate *state) { yy53: rbs_skip(state); yych = peek(state); - if (yych == 'n') goto yy120; + if (yych == 'n') goto yy122; goto yy52; yy54: rbs_skip(state); yych = peek(state); - if (yych == 'o') goto yy122; + if (yych == 'o') goto yy124; goto yy52; yy55: rbs_skip(state); yych = peek(state); - if (yych == 'i') goto yy123; + if (yych == 'i') goto yy125; goto yy52; yy56: rbs_skip(state); yych = peek(state); - if (yych == 'u') goto yy124; + if (yych == 'u') goto yy126; goto yy52; yy57: rbs_skip(state); yych = peek(state); - if (yych == 'r') goto yy125; - if (yych == 'u') goto yy126; + if (yych == 'r') goto yy127; + if (yych == 'u') goto yy128; goto yy52; yy58: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy127; - if (yych == 'i') goto yy128; + if (yych == 'e') goto yy129; + if (yych == 'i') goto yy130; goto yy52; yy59: rbs_skip(state); yych = peek(state); if (yych <= 'q') { - if (yych == 'o') goto yy129; + if (yych == 'o') goto yy131; goto yy52; } else { - if (yych <= 'r') goto yy130; - if (yych == 'y') goto yy131; + if (yych <= 'r') goto yy132; + if (yych == 'y') goto yy133; goto yy52; } yy60: rbs_skip(state); yych = peek(state); - if (yych == 'n') goto yy132; + if (yych == 'n') goto yy134; + if (yych == 's') goto yy135; goto yy52; yy61: rbs_skip(state); yych = peek(state); - if (yych == 'o') goto yy133; + if (yych == 'o') goto yy136; goto yy52; yy62: rbs_skip(state); #line 29 "ext/rbs_extension/lexer.re" { return next_token(state, pLBRACE); } -#line 632 "ext/rbs_extension/lexer.c" +#line 638 "ext/rbs_extension/lexer.c" yy63: rbs_skip(state); #line 32 "ext/rbs_extension/lexer.re" { return next_token(state, pBAR); } -#line 637 "ext/rbs_extension/lexer.c" +#line 643 "ext/rbs_extension/lexer.c" yy64: rbs_skip(state); #line 30 "ext/rbs_extension/lexer.re" { return next_token(state, pRBRACE); } -#line 642 "ext/rbs_extension/lexer.c" +#line 648 "ext/rbs_extension/lexer.c" yy65: rbs_skip(state); yych = peek(state); @@ -675,14 +681,14 @@ token rbsparser_next_token(lexstate *state) { goto yy77; } } else { - goto yy147; + goto yy150; } } yy68: rbs_skip(state); -#line 100 "ext/rbs_extension/lexer.re" +#line 102 "ext/rbs_extension/lexer.re" { return next_token(state, tDQSTRING); } -#line 686 "ext/rbs_extension/lexer.c" +#line 692 "ext/rbs_extension/lexer.c" yy69: rbs_skip(state); yych = peek(state); @@ -737,9 +743,9 @@ token rbsparser_next_token(lexstate *state) { } } yy71: -#line 133 "ext/rbs_extension/lexer.re" +#line 135 "ext/rbs_extension/lexer.re" { return next_token(state, tGIDENT); } -#line 743 "ext/rbs_extension/lexer.c" +#line 749 "ext/rbs_extension/lexer.c" yy72: rbs_skip(state); goto yy71; @@ -749,18 +755,18 @@ token rbsparser_next_token(lexstate *state) { if (yych <= 'Z') { if (yych <= '(') { if (yych <= '\'') goto yy67; - goto yy134; + goto yy137; } else { - if (yych == '<') goto yy135; + if (yych == '<') goto yy138; goto yy67; } } else { if (yych <= 'z') { - if (yych <= '[') goto yy136; + if (yych <= '[') goto yy139; goto yy67; } else { - if (yych <= '{') goto yy137; - if (yych <= '|') goto yy138; + if (yych <= '{') goto yy140; + if (yych <= '|') goto yy141; goto yy67; } } @@ -778,16 +784,16 @@ token rbsparser_next_token(lexstate *state) { yy76: rbs_skip(state); yy77: -#line 101 "ext/rbs_extension/lexer.re" +#line 103 "ext/rbs_extension/lexer.re" { return next_token(state, tSQSTRING); } -#line 784 "ext/rbs_extension/lexer.c" +#line 790 "ext/rbs_extension/lexer.c" yy78: rbs_skip(state); yych = peek(state); if (yych <= '\'') { if (yych <= 0x00000000) goto yy67; if (yych <= '&') goto yy74; - goto yy139; + goto yy142; } else { if (yych == '\\') goto yy78; goto yy74; @@ -796,16 +802,16 @@ token rbsparser_next_token(lexstate *state) { rbs_skip(state); #line 37 "ext/rbs_extension/lexer.re" { return next_token(state, pSTAR2); } -#line 800 "ext/rbs_extension/lexer.c" +#line 806 "ext/rbs_extension/lexer.c" yy80: rbs_skip(state); #line 42 "ext/rbs_extension/lexer.re" { return next_token(state, pARROW); } -#line 805 "ext/rbs_extension/lexer.c" +#line 811 "ext/rbs_extension/lexer.c" yy81: rbs_skip(state); yych = peek(state); - if (yych == '.') goto yy140; + if (yych == '.') goto yy143; goto yy67; yy82: rbs_skip(state); @@ -813,18 +819,18 @@ token rbsparser_next_token(lexstate *state) { if (yych == '=') goto yy86; if (yych == '~') goto yy86; yy83: -#line 120 "ext/rbs_extension/lexer.re" +#line 122 "ext/rbs_extension/lexer.re" { return next_token(state, tSYMBOL); } -#line 819 "ext/rbs_extension/lexer.c" +#line 825 "ext/rbs_extension/lexer.c" yy84: rbs_skip(state); yych = peek(state); if (yych <= '"') { if (yych <= 0x00000000) goto yy67; if (yych <= '!') goto yy84; - goto yy141; + goto yy144; } else { - if (yych == '\\') goto yy142; + if (yych == '\\') goto yy145; goto yy84; } yy85: @@ -834,42 +840,42 @@ token rbsparser_next_token(lexstate *state) { if (yych <= 0x0000001F) { if (yych <= '\n') { if (yych <= 0x00000000) goto yy67; - if (yych <= 0x00000008) goto yy143; + if (yych <= 0x00000008) goto yy146; goto yy67; } else { if (yych == '\r') goto yy67; - goto yy143; + goto yy146; } } else { if (yych <= '#') { if (yych <= ' ') goto yy67; - if (yych <= '"') goto yy145; - goto yy143; + if (yych <= '"') goto yy148; + goto yy146; } else { if (yych == '%') goto yy67; - if (yych <= '\'') goto yy145; + if (yych <= '\'') goto yy148; goto yy67; } } } else { if (yych <= 'Z') { if (yych <= '/') { - if (yych == '-') goto yy143; - goto yy145; + if (yych == '-') goto yy146; + goto yy148; } else { - if (yych <= '9') goto yy143; - if (yych <= '>') goto yy145; - goto yy143; + if (yych <= '9') goto yy146; + if (yych <= '>') goto yy148; + goto yy146; } } else { if (yych <= '^') { - if (yych == '\\') goto yy145; + if (yych == '\\') goto yy148; goto yy67; } else { - if (yych <= 'z') goto yy143; + if (yych <= 'z') goto yy146; if (yych <= '}') goto yy67; - if (yych <= '~') goto yy145; - goto yy143; + if (yych <= '~') goto yy148; + goto yy146; } } } @@ -882,9 +888,9 @@ token rbsparser_next_token(lexstate *state) { if (yych <= '\'') { if (yych <= 0x00000000) goto yy67; if (yych <= '&') goto yy87; - goto yy146; + goto yy149; } else { - if (yych == '\\') goto yy148; + if (yych == '\\') goto yy151; goto yy87; } yy88: @@ -901,18 +907,18 @@ token rbsparser_next_token(lexstate *state) { rbs_skip(state); #line 46 "ext/rbs_extension/lexer.re" { return next_token(state, pCOLON2); } -#line 905 "ext/rbs_extension/lexer.c" +#line 911 "ext/rbs_extension/lexer.c" yy91: rbs_skip(state); yych = peek(state); if (yych <= ';') goto yy83; if (yych <= '<') goto yy86; - if (yych <= '=') goto yy149; + if (yych <= '=') goto yy152; goto yy83; yy92: rbs_skip(state); yych = peek(state); - if (yych == '=') goto yy150; + if (yych == '=') goto yy153; if (yych == '~') goto yy86; goto yy67; yy93: @@ -926,12 +932,12 @@ token rbsparser_next_token(lexstate *state) { yych = peek(state); if (yych <= '^') { if (yych <= '?') goto yy67; - if (yych <= '@') goto yy151; - if (yych <= 'Z') goto yy152; + if (yych <= '@') goto yy154; + if (yych <= 'Z') goto yy155; goto yy67; } else { if (yych == '`') goto yy67; - if (yych <= 'z') goto yy152; + if (yych <= 'z') goto yy155; goto yy67; } yy95: @@ -939,14 +945,14 @@ token rbsparser_next_token(lexstate *state) { yych = peek(state); if (yych <= '>') { if (yych <= '/') { - if (yych == '!') goto yy154; + if (yych == '!') goto yy157; } else { if (yych <= '9') goto yy95; - if (yych == '=') goto yy154; + if (yych == '=') goto yy157; } } else { if (yych <= '^') { - if (yych <= '?') goto yy154; + if (yych <= '?') goto yy157; if (yych <= '@') goto yy96; if (yych <= 'Z') goto yy95; } else { @@ -955,13 +961,13 @@ token rbsparser_next_token(lexstate *state) { } } yy96: -#line 116 "ext/rbs_extension/lexer.re" +#line 118 "ext/rbs_extension/lexer.re" { return next_token(state, tSYMBOL); } -#line 961 "ext/rbs_extension/lexer.c" +#line 967 "ext/rbs_extension/lexer.c" yy97: rbs_skip(state); yych = peek(state); - if (yych == ']') goto yy150; + if (yych == ']') goto yy153; goto yy67; yy98: rbs_skip(state); @@ -977,17 +983,17 @@ token rbsparser_next_token(lexstate *state) { rbs_skip(state); #line 43 "ext/rbs_extension/lexer.re" { return next_token(state, pFATARROW); } -#line 981 "ext/rbs_extension/lexer.c" +#line 987 "ext/rbs_extension/lexer.c" yy101: rbs_skip(state); yych = peek(state); if (yych <= '^') { if (yych <= '@') goto yy67; - if (yych <= 'Z') goto yy155; + if (yych <= 'Z') goto yy158; goto yy67; } else { if (yych == '`') goto yy67; - if (yych <= 'z') goto yy155; + if (yych <= 'z') goto yy158; goto yy67; } yy102: @@ -1006,26 +1012,26 @@ token rbsparser_next_token(lexstate *state) { } } yy103: -#line 130 "ext/rbs_extension/lexer.re" +#line 132 "ext/rbs_extension/lexer.re" { return next_token(state, tAIDENT); } -#line 1012 "ext/rbs_extension/lexer.c" +#line 1018 "ext/rbs_extension/lexer.c" yy104: rbs_skip(state); -#line 127 "ext/rbs_extension/lexer.re" +#line 129 "ext/rbs_extension/lexer.re" { return next_token(state, tBANGIDENT); } -#line 1017 "ext/rbs_extension/lexer.c" +#line 1023 "ext/rbs_extension/lexer.c" yy105: rbs_skip(state); -#line 128 "ext/rbs_extension/lexer.re" +#line 130 "ext/rbs_extension/lexer.re" { return next_token(state, tEQIDENT); } -#line 1022 "ext/rbs_extension/lexer.c" +#line 1028 "ext/rbs_extension/lexer.c" yy106: rbs_skip(state); yych = peek(state); if (yych == '=') goto yy23; #line 48 "ext/rbs_extension/lexer.re" { return next_token(state, pAREF_OPR); } -#line 1029 "ext/rbs_extension/lexer.c" +#line 1035 "ext/rbs_extension/lexer.c" yy107: rbs_skip(state); yych = peek(state); @@ -1046,9 +1052,9 @@ token rbsparser_next_token(lexstate *state) { } } yy108: -#line 124 "ext/rbs_extension/lexer.re" +#line 126 "ext/rbs_extension/lexer.re" { return next_token(state, tULLIDENT); } -#line 1052 "ext/rbs_extension/lexer.c" +#line 1058 "ext/rbs_extension/lexer.c" yy109: rbs_skip(state); yych = peek(state); @@ -1069,57 +1075,80 @@ token rbsparser_next_token(lexstate *state) { } } yy110: -#line 125 "ext/rbs_extension/lexer.re" +#line 127 "ext/rbs_extension/lexer.re" { return next_token(state, tULIDENT); } -#line 1075 "ext/rbs_extension/lexer.c" +#line 1081 "ext/rbs_extension/lexer.c" yy111: rbs_skip(state); yych = peek(state); if (yych <= 0x00000000) goto yy67; - if (yych == '`') goto yy157; + if (yych == '`') goto yy160; goto yy111; yy112: rbs_skip(state); yych = peek(state); - if (yych == 'i') goto yy158; + if (yych == 'i') goto yy161; goto yy52; yy113: rbs_skip(state); yych = peek(state); - if (yych == 't') goto yy159; - goto yy52; + if (yych <= '=') { + if (yych <= '/') { + if (yych == '!') goto yy104; + } else { + if (yych <= '9') goto yy51; + if (yych >= '=') goto yy105; + } + } else { + if (yych <= '^') { + if (yych <= '@') goto yy114; + if (yych <= 'Z') goto yy51; + } else { + if (yych == '`') goto yy114; + if (yych <= 'z') goto yy51; + } + } yy114: - rbs_skip(state); - yych = peek(state); - if (yych == 'o') goto yy160; - if (yych == 't') goto yy161; - goto yy52; +#line 97 "ext/rbs_extension/lexer.re" + { return next_token(state, kAS); } +#line 1115 "ext/rbs_extension/lexer.c" yy115: rbs_skip(state); yych = peek(state); - if (yych == 'a') goto yy163; + if (yych == 't') goto yy162; goto yy52; yy116: rbs_skip(state); yych = peek(state); - if (yych == 'f') goto yy164; + if (yych == 'o') goto yy163; + if (yych == 't') goto yy164; goto yy52; yy117: rbs_skip(state); yych = peek(state); - if (yych == 'd') goto yy166; + if (yych == 'a') goto yy166; goto yy52; yy118: rbs_skip(state); yych = peek(state); - if (yych == 't') goto yy168; + if (yych == 'f') goto yy167; goto yy52; yy119: rbs_skip(state); yych = peek(state); - if (yych == 'l') goto yy169; + if (yych == 'd') goto yy169; goto yy52; yy120: + rbs_skip(state); + yych = peek(state); + if (yych == 't') goto yy171; + goto yy52; +yy121: + rbs_skip(state); + yych = peek(state); + if (yych == 'l') goto yy172; + goto yy52; +yy122: rbs_skip(state); yych = peek(state); if (yych <= '^') { @@ -1130,74 +1159,64 @@ token rbsparser_next_token(lexstate *state) { if (yych <= '=') { if (yych >= '=') goto yy105; } else { - if (yych <= '@') goto yy121; + if (yych <= '@') goto yy123; if (yych <= 'Z') goto yy51; } } } else { if (yych <= 'c') { - if (yych == '`') goto yy121; + if (yych == '`') goto yy123; if (yych <= 'b') goto yy51; - goto yy170; + goto yy173; } else { if (yych <= 's') { if (yych <= 'r') goto yy51; - goto yy171; + goto yy174; } else { - if (yych <= 't') goto yy172; + if (yych <= 't') goto yy175; if (yych <= 'z') goto yy51; } } } -yy121: +yy123: #line 78 "ext/rbs_extension/lexer.re" { return next_token(state, kIN); } -#line 1156 "ext/rbs_extension/lexer.c" -yy122: - rbs_skip(state); - yych = peek(state); - if (yych == 'd') goto yy173; - goto yy52; -yy123: - rbs_skip(state); - yych = peek(state); - if (yych == 'l') goto yy174; - goto yy52; +#line 1185 "ext/rbs_extension/lexer.c" yy124: rbs_skip(state); yych = peek(state); - if (yych == 't') goto yy176; + if (yych == 'd') goto yy176; goto yy52; yy125: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy178; - if (yych == 'i') goto yy179; + if (yych == 'l') goto yy177; goto yy52; yy126: rbs_skip(state); yych = peek(state); - if (yych == 'b') goto yy180; + if (yych == 't') goto yy179; goto yy52; yy127: rbs_skip(state); yych = peek(state); - if (yych == 'l') goto yy181; + if (yych == 'e') goto yy181; + if (yych == 'i') goto yy182; goto yy52; yy128: rbs_skip(state); yych = peek(state); - if (yych == 'n') goto yy182; + if (yych == 'b') goto yy183; goto yy52; yy129: rbs_skip(state); yych = peek(state); - if (yych == 'p') goto yy183; + if (yych == 'l') goto yy184; goto yy52; yy130: rbs_skip(state); yych = peek(state); - if (yych == 'u') goto yy185; + if (yych == 'n') goto yy185; goto yy52; yy131: rbs_skip(state); @@ -1207,45 +1226,60 @@ token rbsparser_next_token(lexstate *state) { yy132: rbs_skip(state); yych = peek(state); - if (yych == 'c') goto yy187; - if (yych == 't') goto yy188; + if (yych == 'u') goto yy188; goto yy52; yy133: rbs_skip(state); yych = peek(state); - if (yych == 'i') goto yy189; + if (yych == 'p') goto yy189; goto yy52; yy134: rbs_skip(state); yych = peek(state); - if (yych <= 0x00000000) goto yy67; - if (yych == ')') goto yy190; - goto yy134; + if (yych == 'c') goto yy190; + if (yych == 't') goto yy191; + goto yy52; yy135: rbs_skip(state); yych = peek(state); - if (yych <= 0x00000000) goto yy67; - if (yych == '>') goto yy191; - goto yy135; + if (yych == 'e') goto yy192; + goto yy52; yy136: rbs_skip(state); yych = peek(state); - if (yych <= 0x00000000) goto yy67; - if (yych == ']') goto yy192; - goto yy136; + if (yych == 'i') goto yy194; + goto yy52; yy137: rbs_skip(state); yych = peek(state); if (yych <= 0x00000000) goto yy67; - if (yych == '}') goto yy193; + if (yych == ')') goto yy195; goto yy137; yy138: rbs_skip(state); yych = peek(state); if (yych <= 0x00000000) goto yy67; - if (yych == '|') goto yy194; + if (yych == '>') goto yy196; goto yy138; yy139: + rbs_skip(state); + yych = peek(state); + if (yych <= 0x00000000) goto yy67; + if (yych == ']') goto yy197; + goto yy139; +yy140: + rbs_skip(state); + yych = peek(state); + if (yych <= 0x00000000) goto yy67; + if (yych == '}') goto yy198; + goto yy140; +yy141: + rbs_skip(state); + yych = peek(state); + if (yych <= 0x00000000) goto yy67; + if (yych == '|') goto yy199; + goto yy141; +yy142: yyaccept = 5; rbs_skip(state); backup = *state; @@ -1258,17 +1292,17 @@ token rbsparser_next_token(lexstate *state) { if (yych == '\\') goto yy78; goto yy74; } -yy140: +yy143: rbs_skip(state); #line 39 "ext/rbs_extension/lexer.re" { return next_token(state, pDOT3); } -#line 1266 "ext/rbs_extension/lexer.c" -yy141: +#line 1300 "ext/rbs_extension/lexer.c" +yy144: rbs_skip(state); -#line 102 "ext/rbs_extension/lexer.re" +#line 104 "ext/rbs_extension/lexer.re" { return next_token(state, tDQSYMBOL); } -#line 1271 "ext/rbs_extension/lexer.c" -yy142: +#line 1305 "ext/rbs_extension/lexer.c" +yy145: rbs_skip(state); yych = peek(state); if (yych <= 'd') { @@ -1292,148 +1326,148 @@ token rbsparser_next_token(lexstate *state) { goto yy67; } } -yy143: +yy146: rbs_skip(state); yych = peek(state); if (yych <= ',') { if (yych <= '\f') { - if (yych <= 0x00000000) goto yy144; - if (yych <= 0x00000008) goto yy143; - if (yych >= '\v') goto yy143; + if (yych <= 0x00000000) goto yy147; + if (yych <= 0x00000008) goto yy146; + if (yych >= '\v') goto yy146; } else { if (yych <= 0x0000001F) { - if (yych >= 0x0000000E) goto yy143; + if (yych >= 0x0000000E) goto yy146; } else { - if (yych == '#') goto yy143; + if (yych == '#') goto yy146; } } } else { if (yych <= '>') { - if (yych <= '-') goto yy143; - if (yych <= '/') goto yy144; - if (yych <= '9') goto yy143; + if (yych <= '-') goto yy146; + if (yych <= '/') goto yy147; + if (yych <= '9') goto yy146; } else { if (yych <= '^') { - if (yych <= 'Z') goto yy143; + if (yych <= 'Z') goto yy146; } else { - if (yych <= 'z') goto yy143; - if (yych >= 0x0000007F) goto yy143; + if (yych <= 'z') goto yy146; + if (yych >= 0x0000007F) goto yy146; } } } -yy144: -#line 119 "ext/rbs_extension/lexer.re" +yy147: +#line 121 "ext/rbs_extension/lexer.re" { return next_token(state, tSYMBOL); } -#line 1328 "ext/rbs_extension/lexer.c" -yy145: +#line 1362 "ext/rbs_extension/lexer.c" +yy148: rbs_skip(state); - goto yy144; -yy146: + goto yy147; +yy149: rbs_skip(state); -yy147: -#line 103 "ext/rbs_extension/lexer.re" +yy150: +#line 105 "ext/rbs_extension/lexer.re" { return next_token(state, tSQSYMBOL); } -#line 1337 "ext/rbs_extension/lexer.c" -yy148: +#line 1371 "ext/rbs_extension/lexer.c" +yy151: rbs_skip(state); yych = peek(state); if (yych <= '\'') { if (yych <= 0x00000000) goto yy67; if (yych <= '&') goto yy87; - goto yy195; + goto yy200; } else { - if (yych == '\\') goto yy148; + if (yych == '\\') goto yy151; goto yy87; } -yy149: +yy152: rbs_skip(state); yych = peek(state); if (yych == '>') goto yy86; goto yy83; -yy150: +yy153: rbs_skip(state); yych = peek(state); if (yych == '=') goto yy86; goto yy83; -yy151: +yy154: rbs_skip(state); yych = peek(state); if (yych <= '^') { if (yych <= '@') goto yy67; - if (yych <= 'Z') goto yy196; + if (yych <= 'Z') goto yy201; goto yy67; } else { if (yych == '`') goto yy67; - if (yych <= 'z') goto yy196; + if (yych <= 'z') goto yy201; goto yy67; } -yy152: +yy155: rbs_skip(state); yych = peek(state); if (yych <= '>') { if (yych <= '/') { - if (yych == '!') goto yy198; + if (yych == '!') goto yy203; } else { - if (yych <= '9') goto yy152; - if (yych == '=') goto yy198; + if (yych <= '9') goto yy155; + if (yych == '=') goto yy203; } } else { if (yych <= '^') { - if (yych <= '?') goto yy198; - if (yych <= '@') goto yy153; - if (yych <= 'Z') goto yy152; + if (yych <= '?') goto yy203; + if (yych <= '@') goto yy156; + if (yych <= 'Z') goto yy155; } else { - if (yych == '`') goto yy153; - if (yych <= 'z') goto yy152; + if (yych == '`') goto yy156; + if (yych <= 'z') goto yy155; } } -yy153: -#line 117 "ext/rbs_extension/lexer.re" +yy156: +#line 119 "ext/rbs_extension/lexer.re" { return next_token(state, tSYMBOL); } -#line 1394 "ext/rbs_extension/lexer.c" -yy154: +#line 1428 "ext/rbs_extension/lexer.c" +yy157: rbs_skip(state); goto yy96; -yy155: +yy158: rbs_skip(state); yych = peek(state); if (yych <= 'Z') { - if (yych <= '/') goto yy156; - if (yych <= '9') goto yy155; - if (yych >= 'A') goto yy155; + if (yych <= '/') goto yy159; + if (yych <= '9') goto yy158; + if (yych >= 'A') goto yy158; } else { if (yych <= '_') { - if (yych >= '_') goto yy155; + if (yych >= '_') goto yy158; } else { - if (yych <= '`') goto yy156; - if (yych <= 'z') goto yy155; + if (yych <= '`') goto yy159; + if (yych <= 'z') goto yy158; } } -yy156: -#line 131 "ext/rbs_extension/lexer.re" +yy159: +#line 133 "ext/rbs_extension/lexer.re" { return next_token(state, tA2IDENT); } -#line 1416 "ext/rbs_extension/lexer.c" -yy157: +#line 1450 "ext/rbs_extension/lexer.c" +yy160: rbs_skip(state); #line 41 "ext/rbs_extension/lexer.re" { return next_token(state, tQIDENT); } -#line 1421 "ext/rbs_extension/lexer.c" -yy158: +#line 1455 "ext/rbs_extension/lexer.c" +yy161: rbs_skip(state); yych = peek(state); - if (yych == 'a') goto yy199; + if (yych == 'a') goto yy204; goto yy52; -yy159: +yy162: rbs_skip(state); yych = peek(state); - if (yych == 'r') goto yy200; + if (yych == 'r') goto yy205; goto yy52; -yy160: +yy163: rbs_skip(state); yych = peek(state); - if (yych == 'l') goto yy201; + if (yych == 'l') goto yy206; goto yy52; -yy161: +yy164: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1445,23 +1479,23 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy162; + if (yych <= '@') goto yy165; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy162; + if (yych == '`') goto yy165; if (yych <= 'z') goto yy51; } } -yy162: +yy165: #line 72 "ext/rbs_extension/lexer.re" { return next_token(state, kBOT); } -#line 1459 "ext/rbs_extension/lexer.c" -yy163: +#line 1493 "ext/rbs_extension/lexer.c" +yy166: rbs_skip(state); yych = peek(state); - if (yych == 's') goto yy203; + if (yych == 's') goto yy208; goto yy52; -yy164: +yy167: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1473,18 +1507,18 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy165; + if (yych <= '@') goto yy168; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy165; + if (yych == '`') goto yy168; if (yych <= 'z') goto yy51; } } -yy165: +yy168: #line 74 "ext/rbs_extension/lexer.re" { return next_token(state, kDEF); } -#line 1487 "ext/rbs_extension/lexer.c" -yy166: +#line 1521 "ext/rbs_extension/lexer.c" +yy169: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1496,48 +1530,48 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy167; + if (yych <= '@') goto yy170; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy167; + if (yych == '`') goto yy170; if (yych <= 'z') goto yy51; } } -yy167: +yy170: #line 75 "ext/rbs_extension/lexer.re" { return next_token(state, kEND); } -#line 1510 "ext/rbs_extension/lexer.c" -yy168: +#line 1544 "ext/rbs_extension/lexer.c" +yy171: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy204; + if (yych == 'e') goto yy209; goto yy52; -yy169: +yy172: rbs_skip(state); yych = peek(state); - if (yych == 's') goto yy205; + if (yych == 's') goto yy210; goto yy52; -yy170: +yy173: rbs_skip(state); yych = peek(state); - if (yych == 'l') goto yy206; + if (yych == 'l') goto yy211; goto yy52; -yy171: +yy174: rbs_skip(state); yych = peek(state); - if (yych == 't') goto yy207; + if (yych == 't') goto yy212; goto yy52; -yy172: +yy175: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy208; + if (yych == 'e') goto yy213; goto yy52; -yy173: +yy176: rbs_skip(state); yych = peek(state); - if (yych == 'u') goto yy209; + if (yych == 'u') goto yy214; goto yy52; -yy174: +yy177: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1549,18 +1583,18 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy175; + if (yych <= '@') goto yy178; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy175; + if (yych == '`') goto yy178; if (yych <= 'z') goto yy51; } } -yy175: +yy178: #line 83 "ext/rbs_extension/lexer.re" { return next_token(state, kNIL); } -#line 1563 "ext/rbs_extension/lexer.c" -yy176: +#line 1597 "ext/rbs_extension/lexer.c" +yy179: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1572,43 +1606,43 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy177; + if (yych <= '@') goto yy180; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy177; + if (yych == '`') goto yy180; if (yych <= 'z') goto yy51; } } -yy177: +yy180: #line 84 "ext/rbs_extension/lexer.re" { return next_token(state, kOUT); } -#line 1586 "ext/rbs_extension/lexer.c" -yy178: +#line 1620 "ext/rbs_extension/lexer.c" +yy181: rbs_skip(state); yych = peek(state); - if (yych == 'p') goto yy210; + if (yych == 'p') goto yy215; goto yy52; -yy179: +yy182: rbs_skip(state); yych = peek(state); - if (yych == 'v') goto yy211; + if (yych == 'v') goto yy216; goto yy52; -yy180: +yy183: rbs_skip(state); yych = peek(state); - if (yych == 'l') goto yy212; + if (yych == 'l') goto yy217; goto yy52; -yy181: +yy184: rbs_skip(state); yych = peek(state); - if (yych == 'f') goto yy213; + if (yych == 'f') goto yy218; goto yy52; -yy182: +yy185: rbs_skip(state); yych = peek(state); - if (yych == 'g') goto yy215; + if (yych == 'g') goto yy220; goto yy52; -yy183: +yy186: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1620,118 +1654,141 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy184; + if (yych <= '@') goto yy187; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy184; + if (yych == '`') goto yy187; if (yych <= 'z') goto yy51; } } -yy184: +yy187: #line 90 "ext/rbs_extension/lexer.re" { return next_token(state, kTOP); } -#line 1634 "ext/rbs_extension/lexer.c" -yy185: +#line 1668 "ext/rbs_extension/lexer.c" +yy188: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy216; + if (yych == 'e') goto yy221; goto yy52; -yy186: +yy189: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy218; + if (yych == 'e') goto yy223; goto yy52; -yy187: +yy190: rbs_skip(state); yych = peek(state); - if (yych == 'h') goto yy220; + if (yych == 'h') goto yy225; goto yy52; -yy188: +yy191: rbs_skip(state); yych = peek(state); - if (yych == 'y') goto yy221; + if (yych == 'y') goto yy226; goto yy52; -yy189: +yy192: + rbs_skip(state); + yych = peek(state); + if (yych <= '=') { + if (yych <= '/') { + if (yych == '!') goto yy104; + } else { + if (yych <= '9') goto yy51; + if (yych >= '=') goto yy105; + } + } else { + if (yych <= '^') { + if (yych <= '@') goto yy193; + if (yych <= 'Z') goto yy51; + } else { + if (yych == '`') goto yy193; + if (yych <= 'z') goto yy51; + } + } +yy193: +#line 96 "ext/rbs_extension/lexer.re" + { return next_token(state, kUSE); } +#line 1711 "ext/rbs_extension/lexer.c" +yy194: rbs_skip(state); yych = peek(state); - if (yych == 'd') goto yy222; + if (yych == 'd') goto yy227; goto yy52; -yy190: +yy195: rbs_skip(state); #line 55 "ext/rbs_extension/lexer.re" { return next_token(state, tANNOTATION); } -#line 1664 "ext/rbs_extension/lexer.c" -yy191: +#line 1721 "ext/rbs_extension/lexer.c" +yy196: rbs_skip(state); #line 58 "ext/rbs_extension/lexer.re" { return next_token(state, tANNOTATION); } -#line 1669 "ext/rbs_extension/lexer.c" -yy192: +#line 1726 "ext/rbs_extension/lexer.c" +yy197: rbs_skip(state); #line 56 "ext/rbs_extension/lexer.re" { return next_token(state, tANNOTATION); } -#line 1674 "ext/rbs_extension/lexer.c" -yy193: +#line 1731 "ext/rbs_extension/lexer.c" +yy198: rbs_skip(state); #line 54 "ext/rbs_extension/lexer.re" { return next_token(state, tANNOTATION); } -#line 1679 "ext/rbs_extension/lexer.c" -yy194: +#line 1736 "ext/rbs_extension/lexer.c" +yy199: rbs_skip(state); #line 57 "ext/rbs_extension/lexer.re" { return next_token(state, tANNOTATION); } -#line 1684 "ext/rbs_extension/lexer.c" -yy195: +#line 1741 "ext/rbs_extension/lexer.c" +yy200: yyaccept = 6; rbs_skip(state); backup = *state; yych = peek(state); if (yych <= '\'') { - if (yych <= 0x00000000) goto yy147; + if (yych <= 0x00000000) goto yy150; if (yych <= '&') goto yy87; - goto yy146; + goto yy149; } else { - if (yych == '\\') goto yy148; + if (yych == '\\') goto yy151; goto yy87; } -yy196: +yy201: rbs_skip(state); yych = peek(state); if (yych <= '>') { if (yych <= '/') { - if (yych == '!') goto yy224; + if (yych == '!') goto yy229; } else { - if (yych <= '9') goto yy196; - if (yych == '=') goto yy224; + if (yych <= '9') goto yy201; + if (yych == '=') goto yy229; } } else { if (yych <= '^') { - if (yych <= '?') goto yy224; - if (yych <= '@') goto yy197; - if (yych <= 'Z') goto yy196; + if (yych <= '?') goto yy229; + if (yych <= '@') goto yy202; + if (yych <= 'Z') goto yy201; } else { - if (yych == '`') goto yy197; - if (yych <= 'z') goto yy196; + if (yych == '`') goto yy202; + if (yych <= 'z') goto yy201; } } -yy197: -#line 118 "ext/rbs_extension/lexer.re" +yy202: +#line 120 "ext/rbs_extension/lexer.re" { return next_token(state, tSYMBOL); } -#line 1721 "ext/rbs_extension/lexer.c" -yy198: +#line 1778 "ext/rbs_extension/lexer.c" +yy203: rbs_skip(state); - goto yy153; -yy199: + goto yy156; +yy204: rbs_skip(state); yych = peek(state); - if (yych == 's') goto yy225; + if (yych == 's') goto yy230; goto yy52; -yy200: +yy205: rbs_skip(state); yych = peek(state); - if (yych == '_') goto yy227; + if (yych == '_') goto yy232; goto yy52; -yy201: +yy206: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1743,68 +1800,68 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy202; + if (yych <= '@') goto yy207; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy202; + if (yych == '`') goto yy207; if (yych <= 'z') goto yy51; } } -yy202: +yy207: #line 71 "ext/rbs_extension/lexer.re" { return next_token(state, kBOOL); } -#line 1757 "ext/rbs_extension/lexer.c" -yy203: +#line 1814 "ext/rbs_extension/lexer.c" +yy208: rbs_skip(state); yych = peek(state); - if (yych == 's') goto yy228; + if (yych == 's') goto yy233; goto yy52; -yy204: +yy209: rbs_skip(state); yych = peek(state); - if (yych == 'n') goto yy230; + if (yych == 'n') goto yy235; goto yy52; -yy205: +yy210: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy231; + if (yych == 'e') goto yy236; goto yy52; -yy206: +yy211: rbs_skip(state); yych = peek(state); - if (yych == 'u') goto yy233; + if (yych == 'u') goto yy238; goto yy52; -yy207: +yy212: rbs_skip(state); yych = peek(state); - if (yych == 'a') goto yy234; + if (yych == 'a') goto yy239; goto yy52; -yy208: +yy213: rbs_skip(state); yych = peek(state); - if (yych == 'r') goto yy235; + if (yych == 'r') goto yy240; goto yy52; -yy209: +yy214: rbs_skip(state); yych = peek(state); - if (yych == 'l') goto yy236; + if (yych == 'l') goto yy241; goto yy52; -yy210: +yy215: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy237; + if (yych == 'e') goto yy242; goto yy52; -yy211: +yy216: rbs_skip(state); yych = peek(state); - if (yych == 'a') goto yy238; + if (yych == 'a') goto yy243; goto yy52; -yy212: +yy217: rbs_skip(state); yych = peek(state); - if (yych == 'i') goto yy239; + if (yych == 'i') goto yy244; goto yy52; -yy213: +yy218: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1816,23 +1873,23 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy214; + if (yych <= '@') goto yy219; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy214; + if (yych == '`') goto yy219; if (yych <= 'z') goto yy51; } } -yy214: +yy219: #line 88 "ext/rbs_extension/lexer.re" { return next_token(state, kSELF); } -#line 1830 "ext/rbs_extension/lexer.c" -yy215: +#line 1887 "ext/rbs_extension/lexer.c" +yy220: rbs_skip(state); yych = peek(state); - if (yych == 'l') goto yy240; + if (yych == 'l') goto yy245; goto yy52; -yy216: +yy221: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1844,18 +1901,18 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy217; + if (yych <= '@') goto yy222; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy217; + if (yych == '`') goto yy222; if (yych <= 'z') goto yy51; } } -yy217: +yy222: #line 91 "ext/rbs_extension/lexer.re" { return next_token(state, kTRUE); } -#line 1858 "ext/rbs_extension/lexer.c" -yy218: +#line 1915 "ext/rbs_extension/lexer.c" +yy223: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1867,28 +1924,28 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy219; + if (yych <= '@') goto yy224; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy219; + if (yych == '`') goto yy224; if (yych <= 'z') goto yy51; } } -yy219: +yy224: #line 92 "ext/rbs_extension/lexer.re" { return next_token(state, kTYPE); } -#line 1881 "ext/rbs_extension/lexer.c" -yy220: +#line 1938 "ext/rbs_extension/lexer.c" +yy225: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy241; + if (yych == 'e') goto yy246; goto yy52; -yy221: +yy226: rbs_skip(state); yych = peek(state); - if (yych == 'p') goto yy242; + if (yych == 'p') goto yy247; goto yy52; -yy222: +yy227: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1900,21 +1957,21 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy223; + if (yych <= '@') goto yy228; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy223; + if (yych == '`') goto yy228; if (yych <= 'z') goto yy51; } } -yy223: +yy228: #line 95 "ext/rbs_extension/lexer.re" { return next_token(state, kVOID); } -#line 1914 "ext/rbs_extension/lexer.c" -yy224: +#line 1971 "ext/rbs_extension/lexer.c" +yy229: rbs_skip(state); - goto yy197; -yy225: + goto yy202; +yy230: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1926,29 +1983,29 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy226; + if (yych <= '@') goto yy231; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy226; + if (yych == '`') goto yy231; if (yych <= 'z') goto yy51; } } -yy226: +yy231: #line 67 "ext/rbs_extension/lexer.re" { return next_token(state, kALIAS); } -#line 1940 "ext/rbs_extension/lexer.c" -yy227: +#line 1997 "ext/rbs_extension/lexer.c" +yy232: rbs_skip(state); yych = peek(state); if (yych <= 'q') { - if (yych == 'a') goto yy243; + if (yych == 'a') goto yy248; goto yy52; } else { - if (yych <= 'r') goto yy244; - if (yych == 'w') goto yy245; + if (yych <= 'r') goto yy249; + if (yych == 'w') goto yy250; goto yy52; } -yy228: +yy233: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1960,23 +2017,23 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy229; + if (yych <= '@') goto yy234; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy229; + if (yych == '`') goto yy234; if (yych <= 'z') goto yy51; } } -yy229: +yy234: #line 73 "ext/rbs_extension/lexer.re" { return next_token(state, kCLASS); } -#line 1974 "ext/rbs_extension/lexer.c" -yy230: +#line 2031 "ext/rbs_extension/lexer.c" +yy235: rbs_skip(state); yych = peek(state); - if (yych == 'd') goto yy246; + if (yych == 'd') goto yy251; goto yy52; -yy231: +yy236: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -1988,83 +2045,83 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy232; + if (yych <= '@') goto yy237; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy232; + if (yych == '`') goto yy237; if (yych <= 'z') goto yy51; } } -yy232: +yy237: #line 77 "ext/rbs_extension/lexer.re" { return next_token(state, kFALSE); } -#line 2002 "ext/rbs_extension/lexer.c" -yy233: +#line 2059 "ext/rbs_extension/lexer.c" +yy238: rbs_skip(state); yych = peek(state); - if (yych == 'd') goto yy248; + if (yych == 'd') goto yy253; goto yy52; -yy234: +yy239: rbs_skip(state); yych = peek(state); - if (yych == 'n') goto yy249; + if (yych == 'n') goto yy254; goto yy52; -yy235: +yy240: rbs_skip(state); yych = peek(state); - if (yych == 'f') goto yy250; + if (yych == 'f') goto yy255; goto yy52; -yy236: +yy241: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy251; + if (yych == 'e') goto yy256; goto yy52; -yy237: +yy242: rbs_skip(state); yych = peek(state); - if (yych == 'n') goto yy253; + if (yych == 'n') goto yy258; goto yy52; -yy238: +yy243: rbs_skip(state); yych = peek(state); - if (yych == 't') goto yy254; + if (yych == 't') goto yy259; goto yy52; -yy239: +yy244: rbs_skip(state); yych = peek(state); - if (yych == 'c') goto yy255; + if (yych == 'c') goto yy260; goto yy52; -yy240: +yy245: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy257; + if (yych == 'e') goto yy262; goto yy52; -yy241: +yy246: rbs_skip(state); yych = peek(state); - if (yych == 'c') goto yy258; + if (yych == 'c') goto yy263; goto yy52; -yy242: +yy247: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy259; + if (yych == 'e') goto yy264; goto yy52; -yy243: +yy248: rbs_skip(state); yych = peek(state); - if (yych == 'c') goto yy260; + if (yych == 'c') goto yy265; goto yy52; -yy244: +yy249: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy261; + if (yych == 'e') goto yy266; goto yy52; -yy245: +yy250: rbs_skip(state); yych = peek(state); - if (yych == 'r') goto yy262; + if (yych == 'r') goto yy267; goto yy52; -yy246: +yy251: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2076,33 +2133,33 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy247; + if (yych <= '@') goto yy252; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy247; + if (yych == '`') goto yy252; if (yych <= 'z') goto yy51; } } -yy247: +yy252: #line 76 "ext/rbs_extension/lexer.re" { return next_token(state, kEXTEND); } -#line 2090 "ext/rbs_extension/lexer.c" -yy248: +#line 2147 "ext/rbs_extension/lexer.c" +yy253: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy263; + if (yych == 'e') goto yy268; goto yy52; -yy249: +yy254: rbs_skip(state); yych = peek(state); - if (yych == 'c') goto yy265; + if (yych == 'c') goto yy270; goto yy52; -yy250: +yy255: rbs_skip(state); yych = peek(state); - if (yych == 'a') goto yy266; + if (yych == 'a') goto yy271; goto yy52; -yy251: +yy256: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2114,28 +2171,28 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy252; + if (yych <= '@') goto yy257; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy252; + if (yych == '`') goto yy257; if (yych <= 'z') goto yy51; } } -yy252: +yy257: #line 82 "ext/rbs_extension/lexer.re" { return next_token(state, kMODULE); } -#line 2128 "ext/rbs_extension/lexer.c" -yy253: +#line 2185 "ext/rbs_extension/lexer.c" +yy258: rbs_skip(state); yych = peek(state); - if (yych == 'd') goto yy267; + if (yych == 'd') goto yy272; goto yy52; -yy254: +yy259: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy269; + if (yych == 'e') goto yy274; goto yy52; -yy255: +yy260: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2147,48 +2204,48 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy256; + if (yych <= '@') goto yy261; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy256; + if (yych == '`') goto yy261; if (yych <= 'z') goto yy51; } } -yy256: +yy261: #line 87 "ext/rbs_extension/lexer.re" { return next_token(state, kPUBLIC); } -#line 2161 "ext/rbs_extension/lexer.c" -yy257: +#line 2218 "ext/rbs_extension/lexer.c" +yy262: rbs_skip(state); yych = peek(state); - if (yych == 't') goto yy271; + if (yych == 't') goto yy276; goto yy52; -yy258: +yy263: rbs_skip(state); yych = peek(state); - if (yych == 'k') goto yy272; + if (yych == 'k') goto yy277; goto yy52; -yy259: +yy264: rbs_skip(state); yych = peek(state); - if (yych == 'd') goto yy273; + if (yych == 'd') goto yy278; goto yy52; -yy260: +yy265: rbs_skip(state); yych = peek(state); - if (yych == 'c') goto yy275; + if (yych == 'c') goto yy280; goto yy52; -yy261: +yy266: rbs_skip(state); yych = peek(state); - if (yych == 'a') goto yy276; + if (yych == 'a') goto yy281; goto yy52; -yy262: +yy267: rbs_skip(state); yych = peek(state); - if (yych == 'i') goto yy277; + if (yych == 'i') goto yy282; goto yy52; -yy263: +yy268: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2200,28 +2257,28 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy264; + if (yych <= '@') goto yy269; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy264; + if (yych == '`') goto yy269; if (yych <= 'z') goto yy51; } } -yy264: +yy269: #line 79 "ext/rbs_extension/lexer.re" { return next_token(state, kINCLUDE); } -#line 2214 "ext/rbs_extension/lexer.c" -yy265: +#line 2271 "ext/rbs_extension/lexer.c" +yy270: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy278; + if (yych == 'e') goto yy283; goto yy52; -yy266: +yy271: rbs_skip(state); yych = peek(state); - if (yych == 'c') goto yy280; + if (yych == 'c') goto yy285; goto yy52; -yy267: +yy272: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2233,18 +2290,18 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy268; + if (yych <= '@') goto yy273; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy268; + if (yych == '`') goto yy273; if (yych <= 'z') goto yy51; } } -yy268: +yy273: #line 85 "ext/rbs_extension/lexer.re" { return next_token(state, kPREPEND); } -#line 2247 "ext/rbs_extension/lexer.c" -yy269: +#line 2304 "ext/rbs_extension/lexer.c" +yy274: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2256,28 +2313,28 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy270; + if (yych <= '@') goto yy275; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy270; + if (yych == '`') goto yy275; if (yych <= 'z') goto yy51; } } -yy270: +yy275: #line 86 "ext/rbs_extension/lexer.re" { return next_token(state, kPRIVATE); } -#line 2270 "ext/rbs_extension/lexer.c" -yy271: +#line 2327 "ext/rbs_extension/lexer.c" +yy276: rbs_skip(state); yych = peek(state); - if (yych == 'o') goto yy281; + if (yych == 'o') goto yy286; goto yy52; -yy272: +yy277: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy282; + if (yych == 'e') goto yy287; goto yy52; -yy273: +yy278: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2289,33 +2346,33 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy274; + if (yych <= '@') goto yy279; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy274; + if (yych == '`') goto yy279; if (yych <= 'z') goto yy51; } } -yy274: +yy279: #line 94 "ext/rbs_extension/lexer.re" { return next_token(state, kUNTYPED); } -#line 2303 "ext/rbs_extension/lexer.c" -yy275: +#line 2360 "ext/rbs_extension/lexer.c" +yy280: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy283; + if (yych == 'e') goto yy288; goto yy52; -yy276: +yy281: rbs_skip(state); yych = peek(state); - if (yych == 'd') goto yy284; + if (yych == 'd') goto yy289; goto yy52; -yy277: +yy282: rbs_skip(state); yych = peek(state); - if (yych == 't') goto yy285; + if (yych == 't') goto yy290; goto yy52; -yy278: +yy283: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2327,48 +2384,48 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy279; + if (yych <= '@') goto yy284; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy279; + if (yych == '`') goto yy284; if (yych <= 'z') goto yy51; } } -yy279: +yy284: #line 80 "ext/rbs_extension/lexer.re" { return next_token(state, kINSTANCE); } -#line 2341 "ext/rbs_extension/lexer.c" -yy280: +#line 2398 "ext/rbs_extension/lexer.c" +yy285: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy286; + if (yych == 'e') goto yy291; goto yy52; -yy281: +yy286: rbs_skip(state); yych = peek(state); - if (yych == 'n') goto yy288; + if (yych == 'n') goto yy293; goto yy52; -yy282: +yy287: rbs_skip(state); yych = peek(state); - if (yych == 'd') goto yy290; + if (yych == 'd') goto yy295; goto yy52; -yy283: +yy288: rbs_skip(state); yych = peek(state); - if (yych == 's') goto yy292; + if (yych == 's') goto yy297; goto yy52; -yy284: +yy289: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy293; + if (yych == 'e') goto yy298; goto yy52; -yy285: +yy290: rbs_skip(state); yych = peek(state); - if (yych == 'e') goto yy294; + if (yych == 'e') goto yy299; goto yy52; -yy286: +yy291: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2380,18 +2437,18 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy287; + if (yych <= '@') goto yy292; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy287; + if (yych == '`') goto yy292; if (yych <= 'z') goto yy51; } } -yy287: +yy292: #line 81 "ext/rbs_extension/lexer.re" { return next_token(state, kINTERFACE); } -#line 2394 "ext/rbs_extension/lexer.c" -yy288: +#line 2451 "ext/rbs_extension/lexer.c" +yy293: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2403,18 +2460,18 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy289; + if (yych <= '@') goto yy294; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy289; + if (yych == '`') goto yy294; if (yych <= 'z') goto yy51; } } -yy289: +yy294: #line 89 "ext/rbs_extension/lexer.re" { return next_token(state, kSINGLETON); } -#line 2417 "ext/rbs_extension/lexer.c" -yy290: +#line 2474 "ext/rbs_extension/lexer.c" +yy295: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2426,38 +2483,38 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy291; + if (yych <= '@') goto yy296; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy291; + if (yych == '`') goto yy296; if (yych <= 'z') goto yy51; } } -yy291: +yy296: #line 93 "ext/rbs_extension/lexer.re" { return next_token(state, kUNCHECKED); } -#line 2440 "ext/rbs_extension/lexer.c" -yy292: +#line 2497 "ext/rbs_extension/lexer.c" +yy297: rbs_skip(state); yych = peek(state); - if (yych == 's') goto yy295; + if (yych == 's') goto yy300; goto yy52; -yy293: +yy298: rbs_skip(state); yych = peek(state); - if (yych == 'r') goto yy296; + if (yych == 'r') goto yy301; goto yy52; -yy294: +yy299: rbs_skip(state); yych = peek(state); - if (yych == 'r') goto yy298; + if (yych == 'r') goto yy303; goto yy52; -yy295: +yy300: rbs_skip(state); yych = peek(state); - if (yych == 'o') goto yy300; + if (yych == 'o') goto yy305; goto yy52; -yy296: +yy301: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2469,18 +2526,18 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy297; + if (yych <= '@') goto yy302; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy297; + if (yych == '`') goto yy302; if (yych <= 'z') goto yy51; } } -yy297: +yy302: #line 69 "ext/rbs_extension/lexer.re" { return next_token(state, kATTRREADER); } -#line 2483 "ext/rbs_extension/lexer.c" -yy298: +#line 2540 "ext/rbs_extension/lexer.c" +yy303: rbs_skip(state); yych = peek(state); if (yych <= '=') { @@ -2492,18 +2549,18 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy299; + if (yych <= '@') goto yy304; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy299; + if (yych == '`') goto yy304; if (yych <= 'z') goto yy51; } } -yy299: +yy304: #line 70 "ext/rbs_extension/lexer.re" { return next_token(state, kATTRWRITER); } -#line 2506 "ext/rbs_extension/lexer.c" -yy300: +#line 2563 "ext/rbs_extension/lexer.c" +yy305: rbs_skip(state); yych = peek(state); if (yych != 'r') goto yy52; @@ -2518,18 +2575,18 @@ token rbsparser_next_token(lexstate *state) { } } else { if (yych <= '^') { - if (yych <= '@') goto yy301; + if (yych <= '@') goto yy306; if (yych <= 'Z') goto yy51; } else { - if (yych == '`') goto yy301; + if (yych == '`') goto yy306; if (yych <= 'z') goto yy51; } } -yy301: +yy306: #line 68 "ext/rbs_extension/lexer.re" { return next_token(state, kATTRACCESSOR); } -#line 2532 "ext/rbs_extension/lexer.c" +#line 2589 "ext/rbs_extension/lexer.c" } -#line 140 "ext/rbs_extension/lexer.re" +#line 142 "ext/rbs_extension/lexer.re" } diff --git a/ext/rbs_extension/lexer.h b/ext/rbs_extension/lexer.h index 2959139f2..efbed661b 100644 --- a/ext/rbs_extension/lexer.h +++ b/ext/rbs_extension/lexer.h @@ -58,6 +58,8 @@ enum TokenType { kUNCHECKED, /* unchecked */ kUNTYPED, /* untyped */ kVOID, /* void */ + kUSE, /* use */ + kAS, /* as */ tLIDENT, /* Identifiers starting with lower case */ tUIDENT, /* Identifiers starting with upper case */ diff --git a/ext/rbs_extension/lexer.re b/ext/rbs_extension/lexer.re index 2dac3c4d8..e45afcd29 100644 --- a/ext/rbs_extension/lexer.re +++ b/ext/rbs_extension/lexer.re @@ -93,6 +93,8 @@ start: "unchecked" { return next_token(state, kUNCHECKED); } "untyped" { return next_token(state, kUNTYPED); } "void" { return next_token(state, kVOID); } + "use" { return next_token(state, kUSE); } + "as" { return next_token(state, kAS); } dqstring = ["] ("\\"[abefnrstv"\\] | [^"\\\x00])* ["]; sqstring = ['] ("\\"['\\] | [^'\x00])* [']; diff --git a/ext/rbs_extension/lexstate.c b/ext/rbs_extension/lexstate.c index 7781968f6..3335074a8 100644 --- a/ext/rbs_extension/lexstate.c +++ b/ext/rbs_extension/lexstate.c @@ -57,6 +57,8 @@ static const char *RBS_TOKENTYPE_NAMES[] = { "kUNCHECKED", /* unchecked */ "kUNTYPED", /* untyped */ "kVOID", /* void */ + "kUSE", /* use */ + "kAS", /* as */ "tLIDENT", /* Identifiers starting with lower case */ "tUIDENT", /* Identifiers starting with upper case */ diff --git a/ext/rbs_extension/parser.c b/ext/rbs_extension/parser.c index 321a133fc..8c9da0a59 100644 --- a/ext/rbs_extension/parser.c +++ b/ext/rbs_extension/parser.c @@ -37,6 +37,8 @@ case kPUBLIC: \ case kPRIVATE: \ case kUNTYPED: \ + case kUSE: \ + case kAS: \ /* nop */ typedef struct { @@ -2560,12 +2562,175 @@ VALUE parse_decl(parserstate *state) { } } +/* + namespace ::= {} (`::`)? (`tUIDENT` `::`)* `tUIDENT` <`::`> + | {} <> (empty -- returns empty namespace) +*/ +VALUE parse_namespace(parserstate *state, range *rg) { + bool is_absolute = false; + + if (state->next_token.type == pCOLON2) { + rg->start = state->next_token.range.start; + rg->end = state->next_token.range.end; + is_absolute = true; + + parser_advance(state); + } + + VALUE path = rb_ary_new(); + + while (true) { + if (state->next_token.type == tUIDENT && state->next_token2.type == pCOLON2) { + rb_ary_push(path, ID2SYM(INTERN_TOKEN(state, state->next_token))); + if (null_position_p(rg->start)) { + rg->start = state->next_token.range.start; + } + rg->end = state->next_token2.range.end; + parser_advance(state); + parser_advance(state); + } else { + break; + } + } + + return rbs_namespace(path, is_absolute ? Qtrue : Qfalse); +} + +/* + use_clauses ::= {} use_clause `,` ... `,` + + use_clause ::= {} namespace + | {} namespace tUIDENT `as` + | {} namespace +*/ +void parse_use_clauses(parserstate *state, VALUE clauses) { + while (true) { + range namespace_range = NULL_RANGE; + VALUE namespace = parse_namespace(state, &namespace_range); + + range clause_range = namespace_range; + + switch (state->next_token.type) + { + case tLIDENT: + case tULIDENT: + case tUIDENT: { + parser_advance(state); + + enum TokenType ident_type = state->current_token.type; + + range type_name_range; + if (null_range_p(namespace_range)) { + type_name_range = state->current_token.range; + } else { + type_name_range.start = namespace_range.start; + type_name_range.end = state->current_token.range.end; + } + clause_range = type_name_range; + + VALUE type_name = rbs_type_name(namespace, ID2SYM(INTERN_TOKEN(state, state->current_token))); + + range keyword_range = NULL_RANGE; + range new_name_range = NULL_RANGE; + + VALUE new_name = Qnil; + if (state->next_token.type == kAS) { + parser_advance(state); + keyword_range = state->current_token.range; + + if (ident_type == tUIDENT) parser_advance_assert(state, tUIDENT); + if (ident_type == tLIDENT) parser_advance_assert(state, tLIDENT); + if (ident_type == tULIDENT) parser_advance_assert(state, tULIDENT); + + new_name = ID2SYM(INTERN_TOKEN(state, state->current_token)); + new_name_range = state->current_token.range; + clause_range.end = new_name_range.end; + } + + VALUE location = rbs_new_location(state->buffer, clause_range); + rbs_loc *loc = rbs_check_location(location); + rbs_loc_add_required_child(loc, rb_intern("type_name"), state->current_token.range); + if (!null_range_p(keyword_range)) { + rbs_loc_add_optional_child(loc, rb_intern("keyword"), keyword_range); + } + if (!null_range_p(new_name_range)) { + rbs_loc_add_optional_child(loc, rb_intern("new_name"), new_name_range); + } + + rb_ary_push(clauses, rbs_ast_directives_use_single_clause(type_name, new_name, location)); + + break; + } + case pSTAR: + { + parser_advance(state); + + range star_range = state->current_token.range; + clause_range.end = star_range.end; + + VALUE location = rbs_new_location(state->buffer, clause_range); + rbs_loc *loc = rbs_check_location(location); + rbs_loc_add_required_child(loc, rb_intern("namespace"), namespace_range); + rbs_loc_add_required_child(loc, rb_intern("star"), star_range); + + rb_ary_push(clauses, rbs_ast_directives_use_wildcard_clause(namespace, location)); + + break; + } + default: + raise_syntax_error( + state, + state->next_token, + "use clause is expected" + ); + } + + if (state->next_token.type == pCOMMA) { + parser_advance(state); + } else { + break; + } + } + + return; +} + +/* + use_directive ::= {} `use` + */ +VALUE parse_use_directive(parserstate *state) { + if (state->next_token.type == kUSE) { + parser_advance(state); + + range keyword_range = state->current_token.range; + + VALUE clauses = rb_ary_new(); + parse_use_clauses(state, clauses); + + range directive_range = keyword_range; + directive_range.end = state->current_token.range.end; + + VALUE location = rbs_new_location(state->buffer, directive_range); + rbs_loc *loc = rbs_check_location(location); + rbs_loc_add_required_child(loc, rb_intern("keyword"), keyword_range); + + return rbs_ast_directives_use(clauses, location); + } else { + return Qnil; + } +} + VALUE parse_signature(parserstate *state) { VALUE dirs = rb_ary_new(); VALUE decls = rb_ary_new(); while (state->next_token.type != pEOF) { - rb_ary_push(decls, parse_decl(state)); + if (state->next_token.type == kUSE) { + VALUE use = parse_use_directive(state); + rb_ary_push(dirs, use); + } else { + rb_ary_push(decls, parse_decl(state)); + } } VALUE ret = rb_ary_new(); diff --git a/ext/rbs_extension/ruby_objs.c b/ext/rbs_extension/ruby_objs.c index baa528a4a..10945ed24 100644 --- a/ext/rbs_extension/ruby_objs.c +++ b/ext/rbs_extension/ruby_objs.c @@ -563,3 +563,29 @@ VALUE rbs_ast_decl_class(VALUE name, VALUE type_params, VALUE super_class, VALUE &kwargs ); } + +VALUE rbs_ast_directives_use(VALUE clauses, VALUE location) { + VALUE kwargs = rb_hash_new(); + rb_hash_aset(kwargs, ID2SYM(rb_intern("clauses")), clauses); + rb_hash_aset(kwargs, ID2SYM(rb_intern("location")), location); + + return CLASS_NEW_INSTANCE(RBS_AST_Directives_Use, 1, &kwargs); +} + +VALUE rbs_ast_directives_use_single_clause(VALUE type_name, VALUE new_name, VALUE location) { + VALUE kwargs = rb_hash_new(); + rb_hash_aset(kwargs, ID2SYM(rb_intern("type_name")), type_name); + rb_hash_aset(kwargs, ID2SYM(rb_intern("new_name")), new_name); + rb_hash_aset(kwargs, ID2SYM(rb_intern("location")), location); + + return CLASS_NEW_INSTANCE(RBS_AST_Directives_Use_SingleClause, 1, &kwargs); +} + +VALUE rbs_ast_directives_use_wildcard_clause(VALUE namespace, VALUE location) { + VALUE kwargs = rb_hash_new(); + rb_hash_aset(kwargs, ID2SYM(rb_intern("namespace")), namespace); + rb_hash_aset(kwargs, ID2SYM(rb_intern("location")), location); + + return CLASS_NEW_INSTANCE(RBS_AST_Directives_Use_WildcardClause, 1, &kwargs); +} + diff --git a/ext/rbs_extension/ruby_objs.h b/ext/rbs_extension/ruby_objs.h index 462d2c95d..d9ee32262 100644 --- a/ext/rbs_extension/ruby_objs.h +++ b/ext/rbs_extension/ruby_objs.h @@ -43,4 +43,8 @@ VALUE rbs_type_name(VALUE namespace, VALUE name); VALUE rbs_union(VALUE types, VALUE location); VALUE rbs_variable(VALUE name, VALUE location); +VALUE rbs_ast_directives_use(VALUE clauses, VALUE location); +VALUE rbs_ast_directives_use_single_clause(VALUE type_name, VALUE new_name, VALUE location); +VALUE rbs_ast_directives_use_wildcard_clause(VALUE namespace, VALUE location); + #endif diff --git a/sig/directives.rbs b/sig/directives.rbs index 38597e545..4991e05b8 100644 --- a/sig/directives.rbs +++ b/sig/directives.rbs @@ -6,6 +6,10 @@ module RBS class Base end + # ``` + # use Foo, Foo::Bar as FBar, Foo:Baz::* + # ``` + # class Use < Base type clause = SingleClause | WildcardClause diff --git a/test/rbs/signature_parsing_test.rb b/test/rbs/signature_parsing_test.rb index 29cb2bfdf..dada3402e 100644 --- a/test/rbs/signature_parsing_test.rb +++ b/test/rbs/signature_parsing_test.rb @@ -2089,4 +2089,36 @@ class RBS::Object = Object end end end + + def test_use_directive + Parser.parse_signature(<<~RBS).tap do |_, dirs, _| + use RBS::Namespace as NS + + module Baz + end + + use RBS::TypeName, RBS::AST::Declarations::* + + class Foo + end + RBS + + assert_equal 2, dirs.size + + dirs[0].tap do |use| + assert_equal 1, use.clauses.size + assert_equal TypeName("RBS::Namespace"), use.clauses[0].type_name + assert_equal :NS, use.clauses[0].new_name + end + + dirs[1].tap do |use| + assert_equal 2, use.clauses.size + + assert_equal TypeName("RBS::TypeName"), use.clauses[0].type_name + assert_nil use.clauses[0].new_name + + assert_equal Namespace("RBS::AST::Declarations::"), use.clauses[1].namespace + end + end + end end From e3c6684507953972e7aa72ba2dea073c72d67030 Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Mon, 6 Feb 2023 16:10:20 +0900 Subject: [PATCH 4/7] Implement Environment::UseMap --- lib/rbs.rb | 1 + lib/rbs/environment.rb | 4 ++ lib/rbs/environment/use_map.rb | 77 ++++++++++++++++++++++++++++++++++ sig/environment.rbs | 6 ++- sig/use_map.rbs | 35 ++++++++++++++++ test/rbs/use_map_test.rb | 53 +++++++++++++++++++++++ 6 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 lib/rbs/environment/use_map.rb create mode 100644 sig/use_map.rbs create mode 100644 test/rbs/use_map_test.rb diff --git a/lib/rbs.rb b/lib/rbs.rb index a49650b4a..4741ff536 100644 --- a/lib/rbs.rb +++ b/lib/rbs.rb @@ -22,6 +22,7 @@ require "rbs/ast/members" require "rbs/ast/annotation" require "rbs/environment" +require "rbs/environment/use_map" require "rbs/environment_loader" require "rbs/builtin_names" require "rbs/definition" diff --git a/lib/rbs/environment.rb b/lib/rbs/environment.rb index 0804b2a18..507305c6f 100644 --- a/lib/rbs/environment.rb +++ b/lib/rbs/environment.rb @@ -425,6 +425,10 @@ def <<(decl) self end + def add_signature_content(buffer:, decls:, directives:) + + end + def validate_type_params class_decls.each_value do |decl| decl.primary diff --git a/lib/rbs/environment/use_map.rb b/lib/rbs/environment/use_map.rb new file mode 100644 index 000000000..22f95d433 --- /dev/null +++ b/lib/rbs/environment/use_map.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +module RBS + class Environment + class UseMap + class Table + attr_reader :known_types, :children + + def initialize + @known_types = Set[] + @children = {} + end + + def compute_children + children.clear + + known_types.each do |type| + unless type.namespace.empty? + children[type.namespace] ||= Set[] + children[type.namespace] << type + end + end + + self + end + end + + attr_reader :use_dirs + + def initialize(table:) + @use_dirs = [] + @map = {} + @table = table + end + + def build_map(clause) + case clause + when AST::Directives::Use::SingleClause + if clause.new_name + @map[clause.new_name] = clause.type_name.absolute! + else + @map[clause.type_name.name] = clause.type_name.absolute! + end + when AST::Directives::Use::WildcardClause + @table.children.fetch(clause.namespace.absolute!).each do |child| + @map[child.name] = child + end + end + + self + end + + def resolve?(type_name) + return if type_name.absolute? + + hd, *tl = type_name.namespace.path + + if hd + # namespace is not empty + if tn = @map[hd] + path = [*tn.namespace.path, tn.name, *tl] + TypeName.new( + namespace: Namespace.new(absolute: true, path: path), + name: type_name.name + ) + end + else + @map[type_name.name] + end + end + + def resolve(type_name) + resolve?(type_name) || type_name + end + end + end +end diff --git a/sig/environment.rbs b/sig/environment.rbs index 6ff397312..08449533d 100644 --- a/sig/environment.rbs +++ b/sig/environment.rbs @@ -119,13 +119,15 @@ module RBS # def self.from_loader: (EnvironmentLoader) -> Environment + def add_signature_content: (buffer: Buffer, decls: Array[AST::Declarations::t], directives: Array[AST::Directives::t]) -> void + # Insert a toplevel declaration into the environment # - def <<: (AST::Declarations::t decl) -> self + private def <<: (AST::Declarations::t decl) -> self # Insert a declaration into the environment # - def insert_decl: (AST::Declarations::t, outer: Array[module_decl], namespace: Namespace) -> void + private def insert_decl: (AST::Declarations::t, outer: Array[module_decl], namespace: Namespace) -> void # Resolve all type names in the environment to absolute type names. # Relative type name will be left if absolute type name cannot be found. diff --git a/sig/use_map.rbs b/sig/use_map.rbs new file mode 100644 index 000000000..0ccdb91c3 --- /dev/null +++ b/sig/use_map.rbs @@ -0,0 +1,35 @@ +module RBS + class Environment + # ```rb + # map = UseMap.build(environment) + # + # map.resolve?(TypeName("TN")) # => nil or resolved type name + # ``` + # + class UseMap + class Table + attr_reader known_types: Set[TypeName] + + attr_reader children: Hash[Namespace, Set[TypeName]] + + def initialize: () -> void + + def compute_children: () -> self + end + + attr_reader use_dirs: Array[AST::Directives::Use] + + @map: Hash[Symbol, TypeName] + + @table: Table + + def initialize: (table: Table) -> void + + def resolve?: (TypeName) -> TypeName? + + def resolve: (TypeName) -> TypeName + + def build_map: (AST::Directives::Use::clause) -> self + end + end +end diff --git a/test/rbs/use_map_test.rb b/test/rbs/use_map_test.rb new file mode 100644 index 000000000..7113a2ddb --- /dev/null +++ b/test/rbs/use_map_test.rb @@ -0,0 +1,53 @@ +require "test_helper" + +class RBS::Environment::UseMapTest < Test::Unit::TestCase + include TestHelper + + UseMap = RBS::Environment::UseMap + Use = RBS::AST::Directives::Use + + attr_reader :map + + def setup + super + + table = UseMap::Table.new() + table.known_types << TypeName("::Foo") + table.known_types << TypeName("::Foo::M") + table.known_types << TypeName("::Foo::_I") + table.known_types << TypeName("::Foo::a") + table.compute_children() + + @map = UseMap.new(table: table) + end + + def test_import_single_clause + map.build_map(Use::SingleClause.new(type_name: TypeName("Foo::M"), new_name: nil, location: nil)) + map.build_map(Use::SingleClause.new(type_name: TypeName("Foo::_I"), new_name: :_FooI, location: nil)) + map.build_map(Use::SingleClause.new(type_name: TypeName("Foo::a"), new_name: :af, location: nil)) + + assert_equal TypeName("::Foo::M"), map.resolve?(TypeName("M")) + assert_equal TypeName("::Foo::_I"), map.resolve?(TypeName("_FooI")) + assert_equal TypeName("::Foo::a"), map.resolve?(TypeName("af")) + + assert_nil map.resolve?(TypeName("::M")) + assert_nil map.resolve?(TypeName("::_FooI")) + assert_nil map.resolve?(TypeName("::af")) + end + + def test_import_wildcard_clause + map.build_map(Use::WildcardClause.new(namespace: Namespace("Foo::"), location: nil)) + + assert_equal TypeName("::Foo::M"), map.resolve?(TypeName("M")) + assert_equal TypeName("::Foo::_I"), map.resolve?(TypeName("_I")) + assert_equal TypeName("::Foo::a"), map.resolve?(TypeName("a")) + end + + def test_resolve_namespace + map.build_map(Use::SingleClause.new(type_name: TypeName("Foo"), new_name: :Bar, location: nil)) + + assert_equal TypeName("::Foo::M"), map.resolve?(TypeName("Bar::M")) + assert_equal TypeName("::Foo::_I"), map.resolve?(TypeName("Bar::_I")) + assert_equal TypeName("::Foo::a"), map.resolve?(TypeName("Bar::a")) + end +end From 911a887459601fef412de9dce2ca577fc692606e Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Tue, 7 Feb 2023 15:00:02 +0900 Subject: [PATCH 5/7] Implememt use name resolution in Environment --- lib/rbs/environment.rb | 121 +++++++++++++++++----------- lib/rbs/environment_loader.rb | 16 ++-- sig/environment.rbs | 18 +++-- sig/environment_loader.rbs | 2 +- test/rbs/definition_builder_test.rb | 6 +- test/rbs/environment_test.rb | 47 +++++++---- 6 files changed, 127 insertions(+), 83 deletions(-) diff --git a/lib/rbs/environment.rb b/lib/rbs/environment.rb index 507305c6f..bb0ae64d2 100644 --- a/lib/rbs/environment.rb +++ b/lib/rbs/environment.rb @@ -10,6 +10,7 @@ class Environment attr_reader :constant_decls attr_reader :global_decls attr_reader :class_alias_decls + attr_reader :buffer_directives module ContextUtil def calculate_context(decls) @@ -151,6 +152,7 @@ def initialize @global_decls = {} @class_alias_decls = {} @normalize_module_name_cache = {} + @buffer_directives = {} end def initialize_copy(other) @@ -163,6 +165,7 @@ def initialize_copy(other) @constant_decls = other.constant_decls.dup @global_decls = other.global_decls.dup @class_alias_decls = other.class_alias_decls.dup + @buffer_directives = other.buffer_directives.dup end def self.from_loader(loader) @@ -425,8 +428,11 @@ def <<(decl) self end - def add_signature_content(buffer:, decls:, directives:) - + def add_signature(buffer:, directives:, decls:) + buffer_directives[buffer] = directives + decls.each do |decl| + self << decl + end end def validate_type_params @@ -439,12 +445,32 @@ def resolve_type_names(only: nil) resolver = Resolver::TypeNameResolver.new(self) env = Environment.new - declarations.each do |decl| - if only && !only.member?(decl) - env << decl - else - env << resolve_declaration(resolver, decl, outer: [], prefix: Namespace.root) + table = UseMap::Table.new() + table.known_types.merge(class_decls.keys) + table.known_types.merge(class_alias_decls.keys) + table.known_types.merge(type_alias_decls.keys) + table.known_types.merge(interface_decls.keys) + table.compute_children + + buffers_decls.each do |buffer, decls| + dirs = buffer_directives.fetch(buffer) + + map = UseMap.new(table: table) + dirs.each do |dir| + dir.clauses.each do |clause| + map.build_map(clause) + end + end + + decls = decls.map do |decl| + if only && !only.member?(decl) + decl + else + resolve_declaration(resolver, map, decl, outer: [], prefix: Namespace.root) + end end + + env.add_signature(buffer: buffer, directives: dirs, decls: decls) end env @@ -465,12 +491,12 @@ def append_context(context, decl) end end - def resolve_declaration(resolver, decl, outer:, prefix:) + def resolve_declaration(resolver, map, decl, outer:, prefix:) if decl.is_a?(AST::Declarations::Global) # @type var decl: AST::Declarations::Global return AST::Declarations::Global.new( name: decl.name, - type: absolute_type(resolver, decl.type, context: nil), + type: absolute_type(resolver, map, decl.type, context: nil), location: decl.location, comment: decl.comment ) @@ -487,21 +513,22 @@ def resolve_declaration(resolver, decl, outer:, prefix:) prefix_ = prefix + decl.name.to_namespace AST::Declarations::Class.new( name: decl.name.with_prefix(prefix), - type_params: resolve_type_params(resolver, decl.type_params, context: inner_context), + type_params: resolve_type_params(resolver, map, decl.type_params, context: inner_context), super_class: decl.super_class&.yield_self do |super_class| AST::Declarations::Class::Super.new( - name: absolute_type_name(resolver, super_class.name, context: outer_context), - args: super_class.args.map {|type| absolute_type(resolver, type, context: outer_context) }, + name: absolute_type_name(resolver, map, super_class.name, context: outer_context), + args: super_class.args.map {|type| absolute_type(resolver, map, type, context: outer_context) }, location: super_class.location ) end, members: decl.members.map do |member| case member when AST::Members::Base - resolve_member(resolver, member, context: inner_context) + resolve_member(resolver, map, member, context: inner_context) when AST::Declarations::Base resolve_declaration( resolver, + map, member, outer: outer_, prefix: prefix_ @@ -523,21 +550,22 @@ def resolve_declaration(resolver, decl, outer:, prefix:) prefix_ = prefix + decl.name.to_namespace AST::Declarations::Module.new( name: decl.name.with_prefix(prefix), - type_params: resolve_type_params(resolver, decl.type_params, context: inner_context), + type_params: resolve_type_params(resolver, map, decl.type_params, context: inner_context), self_types: decl.self_types.map do |module_self| AST::Declarations::Module::Self.new( - name: absolute_type_name(resolver, module_self.name, context: inner_context), - args: module_self.args.map {|type| absolute_type(resolver, type, context: inner_context) }, + name: absolute_type_name(resolver, map, module_self.name, context: inner_context), + args: module_self.args.map {|type| absolute_type(resolver, map, type, context: inner_context) }, location: module_self.location ) end, members: decl.members.map do |member| case member when AST::Members::Base - resolve_member(resolver, member, context: inner_context) + resolve_member(resolver, map, member, context: inner_context) when AST::Declarations::Base resolve_declaration( resolver, + map, member, outer: outer_, prefix: prefix_ @@ -554,9 +582,9 @@ def resolve_declaration(resolver, decl, outer:, prefix:) when AST::Declarations::Interface AST::Declarations::Interface.new( name: decl.name.with_prefix(prefix), - type_params: resolve_type_params(resolver, decl.type_params, context: context), + type_params: resolve_type_params(resolver, map, decl.type_params, context: context), members: decl.members.map do |member| - resolve_member(resolver, member, context: context) + resolve_member(resolver, map, member, context: context) end, comment: decl.comment, location: decl.location, @@ -566,8 +594,8 @@ def resolve_declaration(resolver, decl, outer:, prefix:) when AST::Declarations::TypeAlias AST::Declarations::TypeAlias.new( name: decl.name.with_prefix(prefix), - type_params: resolve_type_params(resolver, decl.type_params, context: context), - type: absolute_type(resolver, decl.type, context: context), + type_params: resolve_type_params(resolver, map, decl.type_params, context: context), + type: absolute_type(resolver, map, decl.type, context: context), location: decl.location, annotations: decl.annotations, comment: decl.comment @@ -576,7 +604,7 @@ def resolve_declaration(resolver, decl, outer:, prefix:) when AST::Declarations::Constant AST::Declarations::Constant.new( name: decl.name.with_prefix(prefix), - type: absolute_type(resolver, decl.type, context: context), + type: absolute_type(resolver, map, decl.type, context: context), location: decl.location, comment: decl.comment ) @@ -584,7 +612,7 @@ def resolve_declaration(resolver, decl, outer:, prefix:) when AST::Declarations::ClassAlias AST::Declarations::ClassAlias.new( new_name: decl.new_name.with_prefix(prefix), - old_name: absolute_type_name(resolver, decl.old_name, context: context), + old_name: absolute_type_name(resolver, map, decl.old_name, context: context), location: decl.location, comment: decl.comment ) @@ -592,14 +620,14 @@ def resolve_declaration(resolver, decl, outer:, prefix:) when AST::Declarations::ModuleAlias AST::Declarations::ModuleAlias.new( new_name: decl.new_name.with_prefix(prefix), - old_name: absolute_type_name(resolver, decl.old_name, context: context), + old_name: absolute_type_name(resolver, map, decl.old_name, context: context), location: decl.location, comment: decl.comment ) end end - def resolve_member(resolver, member, context:) + def resolve_member(resolver, map, member, context:) case member when AST::Members::MethodDefinition AST::Members::MethodDefinition.new( @@ -607,7 +635,7 @@ def resolve_member(resolver, member, context:) kind: member.kind, overloads: member.overloads.map do |overload| overload.update( - method_type: resolve_method_type(resolver, overload.method_type, context: context) + method_type: resolve_method_type(resolver, map, overload.method_type, context: context) ) end, comment: member.comment, @@ -619,7 +647,7 @@ def resolve_member(resolver, member, context:) when AST::Members::AttrAccessor AST::Members::AttrAccessor.new( name: member.name, - type: absolute_type(resolver, member.type, context: context), + type: absolute_type(resolver, map, member.type, context: context), kind: member.kind, annotations: member.annotations, comment: member.comment, @@ -630,7 +658,7 @@ def resolve_member(resolver, member, context:) when AST::Members::AttrReader AST::Members::AttrReader.new( name: member.name, - type: absolute_type(resolver, member.type, context: context), + type: absolute_type(resolver, map, member.type, context: context), kind: member.kind, annotations: member.annotations, comment: member.comment, @@ -641,7 +669,7 @@ def resolve_member(resolver, member, context:) when AST::Members::AttrWriter AST::Members::AttrWriter.new( name: member.name, - type: absolute_type(resolver, member.type, context: context), + type: absolute_type(resolver, map, member.type, context: context), kind: member.kind, annotations: member.annotations, comment: member.comment, @@ -652,44 +680,44 @@ def resolve_member(resolver, member, context:) when AST::Members::InstanceVariable AST::Members::InstanceVariable.new( name: member.name, - type: absolute_type(resolver, member.type, context: context), + type: absolute_type(resolver, map, member.type, context: context), comment: member.comment, location: member.location ) when AST::Members::ClassInstanceVariable AST::Members::ClassInstanceVariable.new( name: member.name, - type: absolute_type(resolver, member.type, context: context), + type: absolute_type(resolver, map, member.type, context: context), comment: member.comment, location: member.location ) when AST::Members::ClassVariable AST::Members::ClassVariable.new( name: member.name, - type: absolute_type(resolver, member.type, context: context), + type: absolute_type(resolver, map, member.type, context: context), comment: member.comment, location: member.location ) when AST::Members::Include AST::Members::Include.new( - name: absolute_type_name(resolver, member.name, context: context), - args: member.args.map {|type| absolute_type(resolver, type, context: context) }, + name: absolute_type_name(resolver, map, member.name, context: context), + args: member.args.map {|type| absolute_type(resolver, map, type, context: context) }, comment: member.comment, location: member.location, annotations: member.annotations ) when AST::Members::Extend AST::Members::Extend.new( - name: absolute_type_name(resolver, member.name, context: context), - args: member.args.map {|type| absolute_type(resolver, type, context: context) }, + name: absolute_type_name(resolver, map, member.name, context: context), + args: member.args.map {|type| absolute_type(resolver, map, type, context: context) }, comment: member.comment, location: member.location, annotations: member.annotations ) when AST::Members::Prepend AST::Members::Prepend.new( - name: absolute_type_name(resolver, member.name, context: context), - args: member.args.map {|type| absolute_type(resolver, type, context: context) }, + name: absolute_type_name(resolver, map, member.name, context: context), + args: member.args.map {|type| absolute_type(resolver, map, type, context: context) }, comment: member.comment, location: member.location, annotations: member.annotations @@ -699,27 +727,28 @@ def resolve_member(resolver, member, context:) end end - def resolve_method_type(resolver, type, context:) + def resolve_method_type(resolver, map, type, context:) type.map_type do |ty| - absolute_type(resolver, ty, context: context) + absolute_type(resolver, map, ty, context: context) end.map_type_bound do |bound| - _ = absolute_type(resolver, bound, context: context) + _ = absolute_type(resolver, map, bound, context: context) end end - def resolve_type_params(resolver, params, context:) + def resolve_type_params(resolver, map, params, context:) params.map do |param| - param.map_type {|type| _ = absolute_type(resolver, type, context: context) } + param.map_type {|type| _ = absolute_type(resolver, map, type, context: context) } end end - def absolute_type_name(resolver, type_name, context:) + def absolute_type_name(resolver, map, type_name, context:) + type_name = map.resolve(type_name) resolver.resolve(type_name, context: context) || type_name end - def absolute_type(resolver, type, context:) + def absolute_type(resolver, map, type, context:) type.map_type_name do |name, _, _| - absolute_type_name(resolver, name, context: context) + absolute_type_name(resolver, map, name, context: context) end end diff --git a/lib/rbs/environment_loader.rb b/lib/rbs/environment_loader.rb index 0de0b1b01..cee57f910 100644 --- a/lib/rbs/environment_loader.rb +++ b/lib/rbs/environment_loader.rb @@ -95,9 +95,11 @@ def load(env:) # @type var loaded: Array[[AST::Declarations::t, Pathname, source]] loaded = [] - each_decl do |decl, buf, source, path| - env << decl - loaded << [decl, path, source] + each_signature do |source, path, buffer, decls, dirs| + decls.each do |decl| + loaded << [decl, path, source] + end + env.add_signature(buffer: buffer, directives: dirs, decls: decls) end loaded @@ -148,7 +150,7 @@ def each_file(path, immediate:, skip_hidden:, &block) end end - def each_decl + def each_signature files = Set[] each_dir do |source, dir| @@ -160,11 +162,9 @@ def each_decl files << path buffer = Buffer.new(name: path.to_s, content: path.read(encoding: "UTF-8")) - _, _dirs, decls = Parser.parse_signature(buffer) + _, dirs, decls = Parser.parse_signature(buffer) - decls.each do |decl| - yield decl, buffer, source, path - end + yield source, path, buffer, decls, dirs end end end diff --git a/sig/environment.rbs b/sig/environment.rbs index 08449533d..18e821d5d 100644 --- a/sig/environment.rbs +++ b/sig/environment.rbs @@ -111,6 +111,8 @@ module RBS # Global declarations attr_reader global_decls: Hash[Symbol, GlobalEntry] + attr_reader buffer_directives: Hash[Buffer, Array[AST::Directives::t]] + def initialize: () -> void def initialize_copy: (Environment) -> void @@ -119,11 +121,11 @@ module RBS # def self.from_loader: (EnvironmentLoader) -> Environment - def add_signature_content: (buffer: Buffer, decls: Array[AST::Declarations::t], directives: Array[AST::Directives::t]) -> void + def add_signature: (buffer: Buffer, directives: Array[AST::Directives::t], decls: Array[AST::Declarations::t]) -> void # Insert a toplevel declaration into the environment # - private def <<: (AST::Declarations::t decl) -> self + def <<: (AST::Declarations::t decl) -> self # Insert a declaration into the environment # @@ -236,16 +238,16 @@ module RBS def append_context: (Resolver::context, module_decl) -> Resolver::context - def resolve_declaration: (Resolver::TypeNameResolver resolver, AST::Declarations::t decl, outer: Array[module_decl], prefix: Namespace) -> AST::Declarations::t + def resolve_declaration: (Resolver::TypeNameResolver resolver, UseMap map, AST::Declarations::t decl, outer: Array[module_decl], prefix: Namespace) -> AST::Declarations::t - def resolve_member: (Resolver::TypeNameResolver, AST::Members::t, context: Resolver::context) -> AST::Members::t + def resolve_member: (Resolver::TypeNameResolver, UseMap map, AST::Members::t, context: Resolver::context) -> AST::Members::t - def resolve_method_type: (Resolver::TypeNameResolver, RBS::MethodType, context: Resolver::context) -> RBS::MethodType + def resolve_method_type: (Resolver::TypeNameResolver, UseMap map, RBS::MethodType, context: Resolver::context) -> RBS::MethodType - def resolve_type_params: (Resolver::TypeNameResolver resolver, Array[AST::TypeParam], context: Resolver::context) -> Array[AST::TypeParam] + def resolve_type_params: (Resolver::TypeNameResolver resolver, UseMap map, Array[AST::TypeParam], context: Resolver::context) -> Array[AST::TypeParam] - def absolute_type: (Resolver::TypeNameResolver, Types::t, context: Resolver::context) -> Types::t + def absolute_type: (Resolver::TypeNameResolver, UseMap map, Types::t, context: Resolver::context) -> Types::t - def absolute_type_name: (Resolver::TypeNameResolver, TypeName, context: Resolver::context) -> TypeName + def absolute_type_name: (Resolver::TypeNameResolver, UseMap map, TypeName, context: Resolver::context) -> TypeName end end diff --git a/sig/environment_loader.rbs b/sig/environment_loader.rbs index c866ababc..af5499baf 100644 --- a/sig/environment_loader.rbs +++ b/sig/environment_loader.rbs @@ -100,7 +100,7 @@ module RBS # def self.gem_sig_path: (String name, String? version) -> [Gem::Specification, Pathname]? - def each_decl: () { (AST::Declarations::t, Buffer, source, Pathname) -> void } -> void + def each_signature: () { (source, Pathname, Buffer, Array[AST::Declarations::t], Array[AST::Directives::t]) -> void } -> void def each_dir: { (source, Pathname) -> void } -> void diff --git a/test/rbs/definition_builder_test.rb b/test/rbs/definition_builder_test.rb index 1896db103..09ecca7a8 100644 --- a/test/rbs/definition_builder_test.rb +++ b/test/rbs/definition_builder_test.rb @@ -2228,10 +2228,8 @@ class Foo include Mod end DEF - RBS::Parser.parse_signature(rbs).tap do |_, _, decls| - decls.each do |decl| - env << decl - end + RBS::Parser.parse_signature(rbs).tap do |buf, dirs, decls| + env.add_signature(buffer: buf, directives: dirs, decls: decls) end definition_builder = RBS::DefinitionBuilder.new(env: env.resolve_type_names) definition_builder.build_instance(TypeName("::Foo")).tap do |defn| diff --git a/test/rbs/environment_test.rb b/test/rbs/environment_test.rb index 14a1dddfb..b0edf3fbe 100644 --- a/test/rbs/environment_test.rb +++ b/test/rbs/environment_test.rb @@ -312,7 +312,7 @@ module Bar : _Animal def test_absolute_type env = Environment.new - _, _, decls = RBS::Parser.parse_signature(< void def test_absolute_type_generics_upper_bound env = Environment.new - _, _, decls = RBS::Parser.parse_signature(< bool end @@ -491,9 +487,7 @@ def test: [B < Bar[_Equatable]] (A, B) -> bool end RBS - decls.each do |decl| - env << decl - end + env.add_signature(buffer: buf, directives: dirs, decls: decls) env_ = env.resolve_type_names @@ -516,7 +510,7 @@ def test: [B < ::Bar[::_Equatable]] (A, B) -> bool end def test_normalize_module_name - _, _, decls = RBS::Parser.parse_signature(<<~EOF) + buf, dirs, decls = RBS::Parser.parse_signature(<<~EOF) class Foo module Bar module Baz @@ -530,12 +524,33 @@ module N = M::Baz env = Environment.new() - decls.each do |decl| - env << decl - end + env.add_signature(buffer: buf, directives: dirs, decls: decls) + env = env.resolve_type_names assert_equal type_name("::Foo::Bar"), env.normalize_module_name(type_name("::M")) assert_equal type_name("::Foo::Bar::Baz"), env.normalize_module_name(type_name("::N")) end + + def test_use_resolve + buf, dirs, decls = RBS::Parser.parse_signature(<<-RBS) +use Object as OB + +class Foo < OB +end + +class OB +end + RBS + + env = Environment.new + env.add_signature(buffer: buf, directives: dirs, decls: decls) + + env.resolve_type_names.tap do |env| + class_decl = env.class_decls[TypeName("::Foo")] + assert_equal TypeName("::Object"), class_decl.primary.decl.super_class.name + + assert_operator env.class_decls, :key?, TypeName("::OB") + end + end end From 3968e5fdaa43f55c5b63e4bb2b9671ad455e16d9 Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Tue, 7 Feb 2023 15:00:09 +0900 Subject: [PATCH 6/7] Fix git test --- test/rbs/collection/sources/git_test.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/rbs/collection/sources/git_test.rb b/test/rbs/collection/sources/git_test.rb index 305f78cc9..9e8b9eb2d 100644 --- a/test/rbs/collection/sources/git_test.rb +++ b/test/rbs/collection/sources/git_test.rb @@ -41,9 +41,11 @@ def source(revision: 'b4d3b346d9657543099a35a1fd20347e75b8c523') end def git(*cmd, **opts) - Open3.capture3("git", *cmd, **opts).then do |out, err, status| - raise "Unexpected git status: \n\n#{err}" unless status.success? - out + Bundler.with_unbundled_env do + Open3.capture3("git", *cmd, **opts).then do |out, err, status| + raise "Unexpected git status: \n\n#{err.each_line.map {|line| ">> #{line}" }.join}" unless status.success? + out + end end end From 29e16bae5bea3d268bbb260b7873490b1d8c468e Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Wed, 8 Feb 2023 11:50:17 +0900 Subject: [PATCH 7/7] Fix Writer to support `use` --- lib/rbs/writer.rb | 28 +++++++++++++++++++++++++++- sig/declarations.rbs | 2 +- sig/writer.rbs | 4 +++- test/rbs/writer_test.rb | 13 +++++++++++-- 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/lib/rbs/writer.rb b/lib/rbs/writer.rb index f796a12e1..e0ac705e2 100644 --- a/lib/rbs/writer.rb +++ b/lib/rbs/writer.rb @@ -76,7 +76,16 @@ def write_comment(comment) end end - def write(decls) + def write(contents) + dirs = contents.select {|c| c.is_a?(AST::Directives::Base) } #: Array[AST::Directives::t] + decls = contents.select {|c| c.is_a?(AST::Declarations::Base) } #: Array[AST::Declarations::t] + + dirs.each do |dir| + write_directive(dir) + end + + puts unless dirs.empty? + [nil, *decls].each_cons(2) do |prev, decl| raise unless decl @@ -85,6 +94,23 @@ def write(decls) end end + def write_directive(dir) + clauses = dir.clauses.map do |clause| + case clause + when AST::Directives::Use::SingleClause + if clause.new_name + "#{clause.type_name} as #{clause.new_name}" + else + "#{clause.type_name}" + end + when AST::Directives::Use::WildcardClause + "#{clause.namespace}*" + end + end + + puts "use #{clauses.join(", ")}" + end + def write_decl(decl) case decl when AST::Declarations::Class diff --git a/sig/declarations.rbs b/sig/declarations.rbs index 17fd5fe49..e346ddc0c 100644 --- a/sig/declarations.rbs +++ b/sig/declarations.rbs @@ -135,7 +135,7 @@ module RBS include _ToJson end - class Interface + class Interface < Base type member = Members::t # interface _Foo end diff --git a/sig/writer.rbs b/sig/writer.rbs index d0ed08390..3c7646e05 100644 --- a/sig/writer.rbs +++ b/sig/writer.rbs @@ -21,7 +21,7 @@ module RBS # Output the array of declarations. # It automatically inserts empty lines between the declarations. # - def write: (Array[AST::Declarations::t]) -> void + def write: (Array[AST::Declarations::t | AST::Directives::t]) -> void def preserve?: () -> bool @@ -96,6 +96,8 @@ module RBS def format_annotation: (AST::Annotation) -> String + def write_directive: (AST::Directives::t) -> void + def write_annotation: (Array[AST::Annotation]) -> void def write_comment: (AST::Comment?) -> void diff --git a/test/rbs/writer_test.rb b/test/rbs/writer_test.rb index 15a8542e7..0080bd0a0 100644 --- a/test/rbs/writer_test.rb +++ b/test/rbs/writer_test.rb @@ -7,9 +7,9 @@ class RBS::WriterTest < Test::Unit::TestCase Writer = RBS::Writer def format(sig, preserve: false) - Parser.parse_signature(sig).then do |_, _, decls| + Parser.parse_signature(sig).then do |_, dirs, decls| writer = Writer.new(out: StringIO.new).preserve!(preserve: preserve) - writer.write(decls) + writer.write(dirs + decls) writer.out.string end @@ -286,4 +286,13 @@ def baz: () -> String end SIG end + + def test_use + assert_writer(<<~SIG) + use Foo::Bar + use Foo::Bar as FB, Baz::* + + $hoge: Foo + SIG + end end