Skip to content

Commit dac4845

Browse files
committed
Introduce FileContext
Eliminate implicit global state (Fiber[:comments]) by introducing `FileContext`. Also, add cache UTF-16 code unit column to `FileContext`. Build the table once per file in O(n) and use O(1) lookups during parsing.
1 parent 539713d commit dac4845

12 files changed

Lines changed: 58 additions & 38 deletions

File tree

lib/typeprof/code_range.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ def initialize(first, last)
5555
raise unless first
5656
end
5757

58-
def self.from_node(node, encoding = Encoding::UTF_16LE)
58+
def self.from_node(node, code_units_cache)
5959
node = node.location if node.respond_to?(:location)
6060
if node.is_a?(Prism::Location)
61-
pos1 = CodePosition.new(node.start_line, node.start_code_units_column(encoding))
62-
pos2 = CodePosition.new(node.end_line, node.end_code_units_column(encoding))
61+
pos1 = CodePosition.new(node.start_line, node.cached_start_code_units_column(code_units_cache))
62+
pos2 = CodePosition.new(node.end_line, node.cached_end_code_units_column(code_units_cache))
6363
elsif node.is_a?(RBS::Location)
6464
pos1 = CodePosition.new(*node.start_loc)
6565
pos2 = CodePosition.new(*node.end_loc)

lib/typeprof/core/ast.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ def self.parse_rb(path, src)
1010

1111
raise unless raw_scope.type == :program_node
1212

13-
Fiber[:comments] = result.comments
13+
prism_source = result.source
14+
file_context = FileContext.new(path, prism_source.code_units_cache(Encoding::UTF_16LE), result.comments)
1415

1516
cref = CRef::Toplevel
16-
lenv = LocalEnv.new(path, cref, {}, [])
17+
lenv = LocalEnv.new(file_context, cref, {}, [])
1718

1819
ProgramNode.new(raw_scope, lenv)
1920
end
@@ -252,7 +253,7 @@ def self.create_node(raw_node, lenv, use_result = true, allow_meta = false)
252253
end
253254

254255
def self.create_target_node(raw_node, lenv)
255-
dummy_node = DummyRHSNode.new(TypeProf::CodeRange.from_node(raw_node.location), lenv)
256+
dummy_node = DummyRHSNode.new(lenv.code_range_from_node(raw_node.location), lenv)
256257
case raw_node.type
257258
when :local_variable_target_node
258259
LocalVariableWriteNode.new(raw_node, dummy_node, lenv)
@@ -305,7 +306,7 @@ def self.create_pattern_node(raw_node, lenv)
305306
when :pinned_expression_node then PinnedPatternNode.new(raw_node, lenv)
306307

307308
when :local_variable_target_node
308-
dummy_node = DummyRHSNode.new(TypeProf::CodeRange.from_node(raw_node.location), lenv)
309+
dummy_node = DummyRHSNode.new(lenv.code_range_from_node(raw_node.location), lenv)
309310
LocalVariableWriteNode.new(raw_node, dummy_node, lenv)
310311

311312
when :constant_read_node, :constant_path_node
@@ -368,7 +369,8 @@ def self.parse_rbs(path, src)
368369
_buffer, _directives, raw_decls = RBS::Parser.parse_signature(src)
369370

370371
cref = CRef::Toplevel
371-
lenv = LocalEnv.new(path, cref, {}, [])
372+
file_context = FileContext.new(path)
373+
lenv = LocalEnv.new(file_context, cref, {}, [])
372374

373375
raw_decls.map do |raw_decl|
374376
AST.create_rbs_decl(raw_decl, lenv)

lib/typeprof/core/ast/base.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def traverse(&blk)
5353

5454
def code_range
5555
if @raw_node
56-
TypeProf::CodeRange.from_node(@raw_node)
56+
@lenv.code_range_from_node(@raw_node)
5757
else
5858
pp self
5959
raise

lib/typeprof/core/ast/call.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_bloc
6969
raise "not supported yet: #{ raw_block.parameters.class }"
7070
end
7171
ncref = CRef.new(lenv.cref.cpath, :instance, @mid, lenv.cref)
72-
nlenv = LocalEnv.new(@lenv.path, ncref, {}, @lenv.return_boxes)
72+
nlenv = LocalEnv.new(@lenv.file_context, ncref, {}, @lenv.return_boxes)
7373
@block_body = raw_block.body ? AST.create_node(raw_block.body, nlenv) : DummyNilNode.new(code_range, lenv)
7474
end
7575
end
@@ -211,7 +211,7 @@ class CallNode < CallBaseNode
211211
def initialize(raw_node, lenv)
212212
recv = raw_node.receiver ? AST.create_node(raw_node.receiver, lenv) : nil
213213
mid = raw_node.name
214-
mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc) if raw_node.message_loc
214+
mid_code_range = lenv.code_range_from_node(raw_node.message_loc) if raw_node.message_loc
215215
raw_args = raw_node.arguments
216216
raw_block = raw_node.block
217217
super(raw_node, recv, mid, mid_code_range, raw_args, nil, raw_block, lenv)
@@ -271,7 +271,7 @@ def initialize(raw_node, lenv)
271271
class OperatorNode < CallBaseNode
272272
def initialize(raw_node, recv, lenv)
273273
mid = raw_node.binary_operator
274-
mid_code_range = TypeProf::CodeRange.from_node(raw_node.binary_operator_loc)
274+
mid_code_range = lenv.code_range_from_node(raw_node.binary_operator_loc)
275275
last_arg = AST.create_node(raw_node.value, lenv)
276276
super(raw_node, recv, mid, mid_code_range, nil, last_arg, nil, lenv)
277277
end
@@ -304,7 +304,7 @@ class CallReadNode < CallBaseNode
304304
def initialize(raw_node, lenv)
305305
recv = AST.create_node(raw_node.receiver, lenv)
306306
mid = raw_node.read_name
307-
mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc)
307+
mid_code_range = lenv.code_range_from_node(raw_node.message_loc)
308308
super(raw_node, recv, mid, mid_code_range, nil, nil, nil, lenv)
309309
end
310310
end
@@ -313,7 +313,7 @@ class CallWriteNode < CallBaseNode
313313
def initialize(raw_node, rhs, lenv)
314314
recv = AST.create_node(raw_node.receiver, lenv)
315315
mid = raw_node.is_a?(Prism::CallTargetNode) ? raw_node.name : raw_node.write_name
316-
mid_code_range = TypeProf::CodeRange.from_node(raw_node.message_loc)
316+
mid_code_range = lenv.code_range_from_node(raw_node.message_loc)
317317
@rhs = rhs
318318
super(raw_node, recv, mid, mid_code_range, nil, rhs, nil, lenv)
319319
end

lib/typeprof/core/ast/const.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def initialize(raw_node, lenv)
88
@cbase = nil
99
@toplevel = false
1010
@cname = raw_node.name
11-
@cname_code_range = TypeProf::CodeRange.from_node(raw_node.location)
11+
@cname_code_range = lenv.code_range_from_node(raw_node.location)
1212
when :constant_path_node, :constant_path_target_node
1313
if raw_node.parent
1414
@cbase = AST.create_node(raw_node.parent, lenv)
@@ -18,7 +18,7 @@ def initialize(raw_node, lenv)
1818
@toplevel = true
1919
end
2020
@cname = raw_node.name
21-
@cname_code_range = TypeProf::CodeRange.from_node(raw_node.name_loc)
21+
@cname_code_range = lenv.code_range_from_node(raw_node.name_loc)
2222
else
2323
raise raw_node.type.to_s
2424
end
@@ -57,17 +57,17 @@ def initialize(raw_node, rhs, lenv)
5757
# C = expr
5858
@cpath = nil
5959
@static_cpath = lenv.cref.cpath + [raw_node.name]
60-
@cname_code_range = TypeProf::CodeRange.from_node(raw_node.respond_to?(:name_loc) ? raw_node.name_loc : raw_node)
60+
@cname_code_range = lenv.code_range_from_node(raw_node.respond_to?(:name_loc) ? raw_node.name_loc : raw_node)
6161
when :constant_path_write_node, :constant_path_operator_write_node, :constant_path_or_write_node, :constant_path_and_write_node
6262
# expr::C = expr
6363
@cpath = AST.create_node(raw_node.target, lenv)
6464
@static_cpath = AST.parse_cpath(raw_node.target, lenv.cref)
65-
@cname_code_range = TypeProf::CodeRange.from_node(raw_node.target)
65+
@cname_code_range = lenv.code_range_from_node(raw_node.target)
6666
when :constant_path_target_node
6767
# expr::C, * = ary
6868
@cpath = ConstantReadNode.new(raw_node, lenv)
6969
@static_cpath = AST.parse_cpath(raw_node, lenv.cref)
70-
@cname_code_range = TypeProf::CodeRange.from_node(raw_node)
70+
@cname_code_range = lenv.code_range_from_node(raw_node)
7171
else
7272
raise
7373
end

lib/typeprof/core/ast/meta.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def rest_keywords = nil
7272
def mname_code_range(name)
7373
idx = @args.index(name.to_sym) # TODO: support string args
7474
node = @raw_node.arguments.arguments[idx].location
75-
TypeProf::CodeRange.from_node(node)
75+
@lenv.code_range_from_node(node)
7676
end
7777

7878
def install0(genv)
@@ -104,7 +104,7 @@ def attrs = { args: }
104104
def mname_code_range(name)
105105
idx = @args.index(name.to_sym) # TODO: support string args
106106
node = @raw_node.arguments.arguments[idx].location
107-
TypeProf::CodeRange.from_node(node)
107+
@lenv.code_range_from_node(node)
108108
end
109109

110110
def define0(genv)

lib/typeprof/core/ast/method.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
module TypeProf::Core
22
class AST
33
def self.get_rbs_comment_before(raw_node, lenv)
4-
comments = Fiber[:comments]
4+
comments = lenv.file_context.comments
5+
return nil unless comments
56
node_line = raw_node.location.start_line
67
last_comment_index = comments.bsearch_index {|c| c.location.start_line >= node_line } || comments.size
78
rbs_comments = []
@@ -45,7 +46,7 @@ def self.parse_params(tbl, raw_args, lenv)
4546
args_code_ranges = []
4647
req_positionals = []
4748
raw_args.requireds.each do |n|
48-
args_code_ranges << TypeProf::CodeRange.from_node(n.location)
49+
args_code_ranges << lenv.code_range_from_node(n.location)
4950
req_positionals << (n.is_a?(Prism::MultiTargetNode) ? nil : n.name)
5051
end
5152

@@ -116,7 +117,7 @@ def initialize(raw_node, lenv, use_result)
116117
# TODO: warn "def self.foo" in a metaclass
117118
singleton = !!raw_node.receiver || lenv.cref.scope_level == :metaclass
118119
mid = raw_node.name
119-
mid_code_range = TypeProf::CodeRange.from_node(raw_node.name_loc)
120+
mid_code_range = lenv.code_range_from_node(raw_node.name_loc)
120121
@tbl = raw_node.locals
121122
raw_args = raw_node.parameters
122123
raw_body = raw_node.body
@@ -128,7 +129,7 @@ def initialize(raw_node, lenv, use_result)
128129
@mid_code_range = mid_code_range
129130

130131
ncref = CRef.new(lenv.cref.cpath, @singleton ? :class : :instance, @mid, lenv.cref)
131-
nlenv = LocalEnv.new(@lenv.path, ncref, {}, [])
132+
nlenv = LocalEnv.new(@lenv.file_context, ncref, {}, [])
132133
if raw_body
133134
@body = AST.create_node(raw_body, nlenv)
134135
else

lib/typeprof/core/ast/module.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ def initialize(raw_node, lenv, raw_cpath, meta, raw_scope, use_result)
1212

1313
if @static_cpath
1414
ncref = CRef.new(@static_cpath, meta ? :metaclass : :class, nil, lenv.cref)
15-
nlenv = LocalEnv.new(@lenv.path, ncref, {}, [])
15+
nlenv = LocalEnv.new(@lenv.file_context, ncref, {}, [])
1616
@body = raw_scope ? AST.create_node(raw_scope, nlenv, use_result) : DummyNilNode.new(code_range, lenv)
1717
else
1818
@body = nil
1919
end
2020

21-
@cname_code_range = meta ? nil : TypeProf::CodeRange.from_node(raw_node.constant_path)
21+
@cname_code_range = meta ? nil : lenv.code_range_from_node(raw_node.constant_path)
2222
@mod_cdef = nil
2323
end
2424

lib/typeprof/core/ast/sig_decl.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def initialize(raw_decl, lenv)
1515
# TODO: decl.type_params
1616
# TODO: decl.super_class.args
1717
ncref = CRef.new(@cpath, :class, nil, lenv.cref)
18-
nlenv = LocalEnv.new(@lenv.path, ncref, {}, [])
18+
nlenv = LocalEnv.new(@lenv.file_context, ncref, {}, [])
1919
@members = raw_decl.members.map do |member|
2020
AST.create_rbs_member(member, nlenv)
2121
end.compact
@@ -190,7 +190,7 @@ class SigDefNode < Node
190190
def initialize(raw_decl, lenv)
191191
super(raw_decl, lenv)
192192
@mid = raw_decl.name
193-
@mid_code_range = TypeProf::CodeRange.from_node(raw_decl.location[:name])
193+
@mid_code_range = lenv.code_range_from_node(raw_decl.location[:name])
194194
@singleton = raw_decl.singleton?
195195
@instance = raw_decl.instance?
196196
@method_types = raw_decl.overloads.map do |overload|

lib/typeprof/core/ast/value.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ def self.create_part_node(raw_part, lenv)
55
when :string_node
66
AST.create_node(raw_part, lenv)
77
when :embedded_statements_node
8-
raw_part.statements ? AST.create_node(raw_part.statements, lenv) : DummyNilNode.new(TypeProf::CodeRange.from_node(raw_part), lenv)
8+
raw_part.statements ? AST.create_node(raw_part.statements, lenv) : DummyNilNode.new(lenv.code_range_from_node(raw_part), lenv)
99
when :embedded_variable_node
1010
AST.create_node(raw_part.variable, lenv)
1111
else

0 commit comments

Comments
 (0)