Skip to content

Commit df94af2

Browse files
committed
Add resolve-type-names magic comment
1 parent 266a070 commit df94af2

File tree

13 files changed

+245
-23
lines changed

13 files changed

+245
-23
lines changed

lib/rbs.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
require "ripper"
1010
require "logger"
1111
require "tsort"
12+
require "strscan"
1213

1314
require "rbs/errors"
1415
require "rbs/buffer"

lib/rbs/ast/directives.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ def initialize(clauses:, location:)
3434
end
3535
end
3636

37+
class ResolveTypeNames < Base
38+
attr_reader :location
39+
40+
attr_reader :value
41+
42+
def initialize(value:, location:)
43+
@value = value
44+
@location = location
45+
end
46+
end
3747
end
3848
end
3949
end

lib/rbs/environment.rb

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,28 @@ def validate_type_params
486486
end
487487
end
488488

489+
def resolve_signature(resolver, table, dirs, decls, only: nil)
490+
map = UseMap.new(table: table)
491+
dirs.each do |dir|
492+
case dir
493+
when AST::Directives::Use
494+
dir.clauses.each do |clause|
495+
map.build_map(clause)
496+
end
497+
end
498+
end
499+
500+
decls = decls.map do |decl|
501+
if only && !only.member?(decl)
502+
decl
503+
else
504+
resolve_declaration(resolver, map, decl, outer: [], prefix: Namespace.root)
505+
end
506+
end
507+
508+
[dirs, decls]
509+
end
510+
489511
def resolve_type_names(only: nil)
490512
resolver = Resolver::TypeNameResolver.new(self)
491513
env = Environment.new
@@ -498,21 +520,10 @@ def resolve_type_names(only: nil)
498520
table.compute_children
499521

500522
signatures.each do |buffer, (dirs, decls)|
501-
map = UseMap.new(table: table)
502-
dirs.each do |dir|
503-
dir.clauses.each do |clause|
504-
map.build_map(clause)
505-
end
523+
resolve = dirs.find { _1.is_a?(AST::Directives::ResolveTypeNames) } #: AST::Directives::ResolveTypeNames?
524+
if !resolve || resolve.value
525+
_, decls = resolve_signature(resolver, table, dirs, decls)
506526
end
507-
508-
decls = decls.map do |decl|
509-
if only && !only.member?(decl)
510-
decl
511-
else
512-
resolve_declaration(resolver, map, decl, outer: [], prefix: Namespace.root)
513-
end
514-
end
515-
516527
env.add_signature(buffer: buffer, directives: dirs, decls: decls)
517528
end
518529

lib/rbs/locator.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ def find2(line:, column:)
4040
end
4141

4242
def find_in_directive(pos, dir, array)
43+
return false unless dir.is_a?(AST::Directives::Use)
44+
4345
if test_loc(pos, location: dir.location)
4446
array.unshift(dir)
4547

lib/rbs/parser_aux.rb

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,48 @@ def self.parse_method_type(source, range: 0..., variables: [], require_eof: fals
1717

1818
def self.parse_signature(source)
1919
buf = buffer(source)
20-
dirs, decls = _parse_signature(buf, 0, buf.last_position)
20+
21+
resolved = magic_comment(buf)
22+
start_pos =
23+
if resolved
24+
(resolved.location || raise).end_pos
25+
else
26+
0
27+
end
28+
dirs, decls = _parse_signature(buf, start_pos, buf.last_position)
29+
30+
if resolved
31+
dirs = dirs.dup if dirs.frozen?
32+
dirs.unshift(resolved)
33+
end
2134

2235
[buf, dirs, decls]
2336
end
2437

38+
def self.magic_comment(buf)
39+
start_pos = 0
40+
41+
while true
42+
case
43+
when match = /\A#\s*(?<keyword>resolve-type-names)\s*(?<colon>:)\s+(?<value>true|false)$/.match(buf.content, start_pos)
44+
value = match[:value] or raise
45+
46+
kw_offset = match.offset(:keyword) #: [Integer, Integer]
47+
colon_offset = match.offset(:colon) #: [Integer, Integer]
48+
value_offset = match.offset(:value) #: [Integer, Integer]
49+
50+
location = Location.new(buf, kw_offset[0], value_offset[1])
51+
location.add_required_child(:keyword, kw_offset[0]...kw_offset[1])
52+
location.add_required_child(:colon, colon_offset[0]...colon_offset[1])
53+
location.add_required_child(:value, value_offset[0]...value_offset[1])
54+
55+
return AST::Directives::ResolveTypeNames.new(value: value == "true", location: location)
56+
else
57+
return
58+
end
59+
end
60+
end
61+
2562
def self.lex(source)
2663
buf = buffer(source)
2764
list = _lex(buf, buf.last_position)

lib/rbs/writer.rb

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,19 @@ def write_comment(comment)
7777
end
7878

7979
def write(contents)
80-
dirs = contents.select {|c| c.is_a?(AST::Directives::Base) } #: Array[AST::Directives::t]
80+
resolves = contents.select { _1.is_a?(AST::Directives::ResolveTypeNames) } #: Array[AST::Directives::ResolveTypeNames]
81+
uses = contents.select {|c| c.is_a?(AST::Directives::Use) } #: Array[AST::Directives::Use]
8182
decls = contents.select {|c| c.is_a?(AST::Declarations::Base) } #: Array[AST::Declarations::t]
8283

83-
dirs.each do |dir|
84-
write_directive(dir)
84+
if first_resolves = resolves.first
85+
puts "# resolve-type-names: #{first_resolves.value}"
86+
puts
8587
end
8688

87-
puts unless dirs.empty?
89+
uses.each do |dir|
90+
write_use_directive(dir)
91+
end
92+
puts unless uses.empty?
8893

8994
[nil, *decls].each_cons(2) do |prev, decl|
9095
raise unless decl
@@ -94,7 +99,7 @@ def write(contents)
9499
end
95100
end
96101

97-
def write_directive(dir)
102+
def write_use_directive(dir)
98103
clauses = dir.clauses.map do |clause|
99104
case clause
100105
when AST::Directives::Use::SingleClause

sig/directives.rbs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module RBS
22
module AST
33
module Directives
4-
type t = Use
4+
type t = Use | ResolveTypeNames
55

66
class Base
77
end
@@ -56,6 +56,22 @@ module RBS
5656

5757
def initialize: (clauses: Array[clause], location: loc?) -> void
5858
end
59+
60+
class ResolveTypeNames < Base
61+
# ```
62+
# # resolve-type-names: false
63+
# ^^^^^^^^^^^^^^^^^^ keyword
64+
# ^ colon
65+
# ^^^^^ value
66+
# ```
67+
type loc = Location[:keyword | :colon | :value, bot]
68+
69+
attr_reader location: loc?
70+
71+
attr_reader value: bool
72+
73+
def initialize: (value: bool, location: loc?) -> void
74+
end
5975
end
6076
end
6177
end

sig/environment.rbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ module RBS
141141
#
142142
def resolve_type_names: (?only: Set[AST::Declarations::t]?) -> Environment
143143

144+
def resolve_signature: (Resolver::TypeNameResolver, UseMap::Table, Array[AST::Directives::t], Array[AST::Declarations::t], ?only: Set[AST::Declarations::t]?) -> [Array[AST::Directives::t], Array[AST::Declarations::t]]
145+
144146
def inspect: () -> String
145147

146148
def buffers: () -> Array[Buffer]

sig/parser.rbs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ module RBS
6868
#
6969
def self.parse_signature: (Buffer | String) -> [Buffer, Array[AST::Directives::t], Array[AST::Declarations::t]]
7070

71+
# Returns the magic comment from the buffer
72+
#
73+
def self.magic_comment: (Buffer) -> AST::Directives::ResolveTypeNames?
74+
7175
# Parse whole RBS file and return result.
7276
#
7377
# ```ruby
@@ -86,7 +90,7 @@ module RBS
8690

8791
def self._parse_method_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof) -> MethodType?
8892

89-
def self._parse_signature: (Buffer, Integer end_pos) -> [Array[AST::Directives::t], Array[AST::Declarations::t]]
93+
def self._parse_signature: (Buffer, Integer start_pos, Integer end_pos) -> [Array[AST::Directives::t], Array[AST::Declarations::t]]
9094

9195
def self._lex: (Buffer, Integer end_pos) -> Array[[Symbol, Location[untyped, untyped]]]
9296

sig/writer.rbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ module RBS
9696

9797
def format_annotation: (AST::Annotation) -> String
9898

99-
def write_directive: (AST::Directives::t) -> void
99+
def write_use_directive: (AST::Directives::Use) -> void
100100

101101
def write_annotation: (Array[AST::Annotation]) -> void
102102

0 commit comments

Comments
 (0)