Module: Hecks::Adapters::Prism
- Defined in:
- lib/hecks/adapters/driven/prism.rb
Constant Summary collapse
- TREES =
{}
Class Method Summary collapse
- .block_node_at(file, line) ⇒ Object
- .body_source(block) ⇒ Object
- .canonical(block) ⇒ Object
- .canonicalise(source) ⇒ Object
-
.forget(file) ⇒ Object
TREEScaches for the life of the PROCESS, keyed by path, with no staleness check — correct for every ordinary caller (a file loads once per process: onebin/irrun, one rspec worker, never edited out from under it), but WRONG for anything that legitimately reloads an edited file in-process: a stale cached tree reports agiven/ensuresblock at its OLD line number, which no longer matches the freshly re-executed file's ownblock.source_location— surfacing as "did not survive extraction" on a perfectly valid file. - .forget_all ⇒ Object
- .tree_for(file) ⇒ Object
- .walk(node, &visit) ⇒ Object
Class Method Details
.block_node_at(file, line) ⇒ Object
26 27 28 29 30 31 32 33 34 35 |
# File 'lib/hecks/adapters/driven/prism.rb', line 26 def block_node_at(file, line) found = nil walk(tree_for(file)) do |node| next unless node.is_a?(::Prism::BlockNode) next unless node.location.start_line == line found ||= node end found end |
.body_source(block) ⇒ Object
18 19 20 21 22 23 24 |
# File 'lib/hecks/adapters/driven/prism.rb', line 18 def body_source(block) file, line = block.source_location return nil unless file && File.readable?(file) node = block_node_at(file, line) node&.body&.slice end |
.canonical(block) ⇒ Object
13 14 15 16 |
# File 'lib/hecks/adapters/driven/prism.rb', line 13 def canonical(block) body = body_source(block) body && canonicalise(body) end |
.canonicalise(source) ⇒ Object
75 76 77 |
# File 'lib/hecks/adapters/driven/prism.rb', line 75 def canonicalise(source) Bluebook::Expression::CanonicalForm.apply(source) end |
.forget(file) ⇒ Object
TREES caches for the life of the PROCESS, keyed by path, with
no staleness check — correct for every ordinary caller (a file
loads once per process: one bin/ir run, one rspec worker,
never edited out from under it), but WRONG for anything that
legitimately reloads an edited file in-process: a stale cached
tree reports a given/ensures block at its OLD line number,
which no longer matches the freshly re-executed file's own
block.source_location — surfacing as "did not survive
extraction" on a perfectly valid file. Found for real building
Hecks::Codemod (lib/hecks/codemod.rb), which used to
reach into TREES.clear directly — a private implementation
detail poked from outside. forget/forget_all are the real
API so nothing else that reloads an edited file in-process has
to know TREES exists at all.
64 |
# File 'lib/hecks/adapters/driven/prism.rb', line 64 def forget(file) = TREES.delete(file) |
.forget_all ⇒ Object
66 |
# File 'lib/hecks/adapters/driven/prism.rb', line 66 def forget_all = TREES.clear |
.tree_for(file) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/hecks/adapters/driven/prism.rb', line 37 def tree_for(file) # ::Prism.parse_file(file) reads the file itself, at the C # extension level — bypassing Ruby's own File/IO layer entirely. # That's invisible to anything that virtualizes the filesystem at # the Ruby level instead of the OS level (e.g. tebako's memfs, # used to press a hecks-based app into a single executable — # see domain/README.md's "Deploying" section in lifeadelics for # why that matters). ::Prism.parse(File.read(file)) parses the # exact same bytes, just read through Ruby's File.read first, # which those tools do intercept. TREES[file] ||= ::Prism.parse(File.read(file)).value end |
.walk(node, &visit) ⇒ Object
68 69 70 71 72 73 |
# File 'lib/hecks/adapters/driven/prism.rb', line 68 def walk(node, &visit) return unless node.is_a?(::Prism::Node) visit.call(node) node.compact_child_nodes.each { |child| walk(child, &visit) } end |