ffast 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +27 -0
- data/.github/workflows/ruby.yml +34 -0
- data/.gitignore +2 -0
- data/Fastfile +102 -15
- data/README.md +21 -7
- data/bin/console +1 -1
- data/bin/fast-experiment +3 -0
- data/bin/fast-mcp +7 -0
- data/fast.gemspec +1 -3
- data/lib/fast/cli.rb +58 -26
- data/lib/fast/experiment.rb +19 -2
- data/lib/fast/git.rb +1 -1
- data/lib/fast/mcp_server.rb +317 -0
- data/lib/fast/node.rb +258 -0
- data/lib/fast/prism_adapter.rb +310 -0
- data/lib/fast/rewriter.rb +64 -10
- data/lib/fast/scan.rb +203 -0
- data/lib/fast/shortcut.rb +16 -4
- data/lib/fast/source.rb +116 -0
- data/lib/fast/source_rewriter.rb +153 -0
- data/lib/fast/sql/rewriter.rb +36 -7
- data/lib/fast/sql.rb +15 -17
- data/lib/fast/summary.rb +435 -0
- data/lib/fast/version.rb +1 -1
- data/lib/fast.rb +140 -83
- data/mkdocs.yml +19 -4
- data/requirements-docs.txt +3 -0
- metadata +16 -59
- data/docs/command_line.md +0 -238
- data/docs/editors-integration.md +0 -46
- data/docs/experiments.md +0 -155
- data/docs/git.md +0 -115
- data/docs/ideas.md +0 -70
- data/docs/index.md +0 -404
- data/docs/pry-integration.md +0 -27
- data/docs/research.md +0 -93
- data/docs/shortcuts.md +0 -323
- data/docs/similarity_tutorial.md +0 -176
- data/docs/sql-support.md +0 -253
- data/docs/syntax.md +0 -395
- data/docs/videos.md +0 -16
- data/docs/walkthrough.md +0 -135
- data/examples/build_stubbed_and_let_it_be_experiment.rb +0 -51
- data/examples/experimental_replacement.rb +0 -46
- data/examples/find_usage.rb +0 -26
- data/examples/let_it_be_experiment.rb +0 -11
- data/examples/method_complexity.rb +0 -37
- data/examples/search_duplicated.rb +0 -15
- data/examples/similarity_research.rb +0 -58
- data/examples/simple_rewriter.rb +0 -6
- data/experiments/let_it_be_experiment.rb +0 -9
- data/experiments/remove_useless_hook.rb +0 -9
- data/experiments/replace_create_with_build_stubbed.rb +0 -10
data/lib/fast.rb
CHANGED
|
@@ -1,28 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'fileutils'
|
|
4
|
-
require 'astrolabe/builder'
|
|
5
|
-
require_relative 'fast/rewriter'
|
|
6
|
-
|
|
7
|
-
# suppress output to avoid parser gem warnings'
|
|
8
|
-
def suppress_output
|
|
9
|
-
original_stdout = $stdout.clone
|
|
10
|
-
original_stderr = $stderr.clone
|
|
11
|
-
$stderr.reopen File.new('/dev/null', 'w')
|
|
12
|
-
$stdout.reopen File.new('/dev/null', 'w')
|
|
13
|
-
yield
|
|
14
|
-
ensure
|
|
15
|
-
$stdout.reopen original_stdout
|
|
16
|
-
$stderr.reopen original_stderr
|
|
17
|
-
end
|
|
18
4
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
end
|
|
5
|
+
require_relative 'fast/source'
|
|
6
|
+
require_relative 'fast/node'
|
|
7
|
+
require_relative 'fast/rewriter'
|
|
23
8
|
|
|
24
9
|
# Fast is a tool to help you search in the code through the Abstract Syntax Tree
|
|
25
10
|
module Fast
|
|
11
|
+
NODE_PARENTS = ObjectSpace::WeakMap.new
|
|
12
|
+
|
|
13
|
+
class SyntaxError < StandardError; end
|
|
14
|
+
|
|
26
15
|
# Literals are shortcuts allowed inside {ExpressionParser}
|
|
27
16
|
LITERAL = {
|
|
28
17
|
'...' => ->(node) { node&.children&.any? },
|
|
@@ -67,83 +56,95 @@ module Fast
|
|
|
67
56
|
%\d # bind extra arguments to the expression
|
|
68
57
|
/x.freeze
|
|
69
58
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def buffer_name
|
|
74
|
-
expression.source_buffer.name
|
|
59
|
+
class << self
|
|
60
|
+
def ast_node?(node)
|
|
61
|
+
node.respond_to?(:type) && node.respond_to?(:children)
|
|
75
62
|
end
|
|
76
63
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
64
|
+
def prism_ast(content, buffer_name: '(string)')
|
|
65
|
+
require_relative 'fast/prism_adapter'
|
|
66
|
+
result = Fast::PrismAdapter.parse(content, buffer_name: buffer_name)
|
|
67
|
+
return result if result
|
|
68
|
+
|
|
69
|
+
prism_errors = Prism.parse(content).errors
|
|
70
|
+
message = prism_errors.map(&:message).uniq.join("\n")
|
|
71
|
+
raise SyntaxError, message
|
|
80
72
|
end
|
|
81
73
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
expression.source
|
|
74
|
+
def parse_ruby(content, buffer_name: '(string)')
|
|
75
|
+
prism_ast(content, buffer_name: buffer_name)
|
|
85
76
|
end
|
|
86
77
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
File.exist?(buffer_name)
|
|
78
|
+
def parser_ast(content, buffer_name: '(string)')
|
|
79
|
+
prism_ast(content, buffer_name: buffer_name)
|
|
90
80
|
end
|
|
91
81
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
82
|
+
def parser_ast_from_file(file)
|
|
83
|
+
@parser_cache ||= {}
|
|
84
|
+
@parser_cache[file] ||=
|
|
85
|
+
begin
|
|
86
|
+
method =
|
|
87
|
+
if file.end_with?('.sql')
|
|
88
|
+
require_relative 'fast/sql' unless respond_to?(:parse_sql)
|
|
89
|
+
:parse_sql
|
|
90
|
+
else
|
|
91
|
+
:parser_ast
|
|
92
|
+
end
|
|
93
|
+
Fast.public_send(method, IO.read(file), buffer_name: file)
|
|
94
|
+
end
|
|
97
95
|
end
|
|
98
96
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
def parse_file(file)
|
|
98
|
+
return parser_ast_from_file(file) if file.end_with?('.sql')
|
|
99
|
+
|
|
100
|
+
@cache ||= {}
|
|
101
|
+
@cache[file] ||=
|
|
102
|
+
begin
|
|
103
|
+
parse_ruby(IO.read(file), buffer_name: file)
|
|
104
|
+
end
|
|
102
105
|
end
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
# @return [Array<Fast::Node>>] with files and results
|
|
108
|
-
def search(pattern, *args)
|
|
109
|
-
Fast.search(pattern, self, *args)
|
|
107
|
+
def summary(code_or_ast, file: nil, command_name: '.summary', level: nil)
|
|
108
|
+
require_relative 'fast/summary'
|
|
109
|
+
Summary.new(code_or_ast, file: file, command_name: command_name, level: level)
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
# @return [Array<Fast::Node>>] with files and results
|
|
116
|
-
def capture(pattern, *args)
|
|
117
|
-
Fast.capture(pattern, self, *args)
|
|
112
|
+
def scan(locations, command_name: '.scan', level: nil)
|
|
113
|
+
require_relative 'fast/scan'
|
|
114
|
+
Scan.new(locations, command_name: command_name, level: level)
|
|
118
115
|
end
|
|
119
|
-
end
|
|
120
116
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
117
|
+
def parser_class
|
|
118
|
+
raise NoMethodError, 'Fast.parser_class was removed; Fast now parses Ruby with Prism'
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def parser_require_path
|
|
122
|
+
raise NoMethodError, 'Fast.parser_require_path was removed; Fast now parses Ruby with Prism'
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def parser_const_name
|
|
126
|
+
raise NoMethodError, 'Fast.parser_const_name was removed; Fast now parses Ruby with Prism'
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def parser_version_supported?(const_name)
|
|
130
|
+
raise NoMethodError, "Fast.parser_version_supported?(#{const_name.inspect}) was removed; Fast now parses Ruby with Prism"
|
|
129
131
|
end
|
|
130
|
-
end
|
|
131
132
|
|
|
132
|
-
class << self
|
|
133
133
|
# @return [Fast::Node] from the parsed content
|
|
134
134
|
# @example
|
|
135
135
|
# Fast.ast("1") # => s(:int, 1)
|
|
136
136
|
# Fast.ast("a.b") # => s(:send, s(:send, nil, :a), :b)
|
|
137
137
|
def ast(content, buffer_name: '(string)')
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
parse_ruby(content, buffer_name: buffer_name)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def validate_ruby!(content, buffer_name: '(string)')
|
|
142
|
+
prism_ast(content, buffer_name: buffer_name)
|
|
143
|
+
true
|
|
141
144
|
end
|
|
142
145
|
|
|
143
146
|
def builder_for(buffer_name)
|
|
144
|
-
|
|
145
|
-
builder.buffer_name = buffer_name
|
|
146
|
-
builder
|
|
147
|
+
raise NoMethodError, "Fast.builder_for(#{buffer_name.inspect}) was removed; Fast now parses Ruby with Prism"
|
|
147
148
|
end
|
|
148
149
|
|
|
149
150
|
# @return [Fast::Node] parsed from file content
|
|
@@ -152,18 +153,7 @@ module Fast
|
|
|
152
153
|
# @example
|
|
153
154
|
# Fast.ast_from_file("example.rb") # => s(...)
|
|
154
155
|
def ast_from_file(file)
|
|
155
|
-
|
|
156
|
-
@cache[file] ||=
|
|
157
|
-
begin
|
|
158
|
-
method =
|
|
159
|
-
if file.end_with?('.sql')
|
|
160
|
-
require_relative 'fast/sql' unless respond_to?(:parse_sql)
|
|
161
|
-
:parse_sql
|
|
162
|
-
else
|
|
163
|
-
:ast
|
|
164
|
-
end
|
|
165
|
-
Fast.public_send(method, IO.read(file), buffer_name: file)
|
|
166
|
-
end
|
|
156
|
+
parse_file(file)
|
|
167
157
|
end
|
|
168
158
|
|
|
169
159
|
# Verify if a given AST matches with a specific pattern
|
|
@@ -330,6 +320,73 @@ module Fast
|
|
|
330
320
|
files.reject(&dir_filter)
|
|
331
321
|
end
|
|
332
322
|
|
|
323
|
+
# Folds the AST to a maximum depth, replacing deeper branches with `...`
|
|
324
|
+
# @param node [Fast::Node]
|
|
325
|
+
# @param level [Integer] maximum depth to explore
|
|
326
|
+
# @param current_level [Integer] internal tracker for depth
|
|
327
|
+
# @return [Fast::Node] the folded AST
|
|
328
|
+
def fold_ast(node, level: nil, current_level: 1)
|
|
329
|
+
return node unless ast_node?(node) && node.respond_to?(:updated)
|
|
330
|
+
return node if level.nil?
|
|
331
|
+
|
|
332
|
+
if current_level >= level
|
|
333
|
+
if node.children.any?
|
|
334
|
+
node.updated(nil, [:'...'])
|
|
335
|
+
else
|
|
336
|
+
node
|
|
337
|
+
end
|
|
338
|
+
else
|
|
339
|
+
new_children = node.children.map { |c| fold_ast(c, level: level, current_level: current_level + 1) }
|
|
340
|
+
node.updated(nil, new_children)
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
# Folds ruby source code to a maximum depth, replacing deep block bodies with `# ...`
|
|
345
|
+
# @param node [Fast::Node]
|
|
346
|
+
# @param level [Integer] maximum depth to explore
|
|
347
|
+
# @return [String] the folded source representation
|
|
348
|
+
def fold_source(node, level: 1)
|
|
349
|
+
return node if node.is_a?(String)
|
|
350
|
+
return node.loc.expression.source rescue node.to_s unless ast_node?(node) && node.respond_to?(:loc)
|
|
351
|
+
|
|
352
|
+
source = node.loc.expression.source.dup
|
|
353
|
+
root_begin = node.loc.expression.begin_pos
|
|
354
|
+
|
|
355
|
+
regions = []
|
|
356
|
+
|
|
357
|
+
walker = ->(n, current_level) do
|
|
358
|
+
return unless ast_node?(n)
|
|
359
|
+
|
|
360
|
+
if current_level >= level
|
|
361
|
+
body_node = nil
|
|
362
|
+
case n.type
|
|
363
|
+
when :class, :module, :def, :defs, :block
|
|
364
|
+
body_node = n.children.last
|
|
365
|
+
when :begin
|
|
366
|
+
body_node = n
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
if body_node && body_node.loc && body_node.loc.respond_to?(:expression) && body_node.loc.expression
|
|
370
|
+
regions << [
|
|
371
|
+
body_node.loc.expression.begin_pos - root_begin,
|
|
372
|
+
body_node.loc.expression.end_pos - root_begin
|
|
373
|
+
]
|
|
374
|
+
return
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
n.children.each { |c| walker.call(c, current_level + 1) if ast_node?(c) }
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
walker.call(node, 1)
|
|
382
|
+
|
|
383
|
+
regions.sort_by { |r| -r[0] }.each do |start_pos, end_pos|
|
|
384
|
+
source[start_pos...end_pos] = "# ..."
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
source
|
|
388
|
+
end
|
|
389
|
+
|
|
333
390
|
# Extracts a node pattern expression from a given node supressing identifiers and primitive types.
|
|
334
391
|
# Useful to index abstract patterns or similar code structure.
|
|
335
392
|
# @see https://jonatas.github.io/fast/similarity_tutorial/
|
|
@@ -341,7 +398,7 @@ module Fast
|
|
|
341
398
|
# Fast.expression_from(Fast.ast('def name; person.name end')) # => '(def _ (args) (send (send nil _) _))'
|
|
342
399
|
def expression_from(node)
|
|
343
400
|
case node
|
|
344
|
-
when
|
|
401
|
+
when ->(candidate) { ast_node?(candidate) }
|
|
345
402
|
children_expression = node.children.map(&method(:expression_from)).join(' ')
|
|
346
403
|
"(#{node.type}#{" #{children_expression}" if node.children.any?})"
|
|
347
404
|
when nil, 'nil'
|
|
@@ -456,7 +513,7 @@ module Fast
|
|
|
456
513
|
|
|
457
514
|
def compare_symbol_or_head(expression, node)
|
|
458
515
|
case node
|
|
459
|
-
when
|
|
516
|
+
when ->(candidate) { Fast.ast_node?(candidate) }
|
|
460
517
|
node.type == expression.to_sym
|
|
461
518
|
when String
|
|
462
519
|
node == expression.to_s
|
data/mkdocs.yml
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
site_name: Fast
|
|
2
2
|
repo_url: https://github.com/jonatas/fast
|
|
3
3
|
edit_uri: edit/master/docs/
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
extra:
|
|
6
|
+
analytics:
|
|
7
|
+
provider: google
|
|
8
|
+
property: G-YKZDZDNRG2
|
|
5
9
|
|
|
6
10
|
theme:
|
|
7
11
|
name: material
|
|
@@ -13,10 +17,15 @@ theme:
|
|
|
13
17
|
extra_css:
|
|
14
18
|
- stylesheets/custom.css
|
|
15
19
|
|
|
20
|
+
plugins:
|
|
21
|
+
- search
|
|
22
|
+
|
|
16
23
|
markdown_extensions:
|
|
17
24
|
- admonition
|
|
18
|
-
-
|
|
19
|
-
|
|
25
|
+
- pymdownx.details
|
|
26
|
+
- pymdownx.superfences
|
|
27
|
+
- pymdownx.tabbed:
|
|
28
|
+
alternate_style: true
|
|
20
29
|
- toc:
|
|
21
30
|
permalink: true
|
|
22
31
|
nav:
|
|
@@ -27,10 +36,16 @@ nav:
|
|
|
27
36
|
- Experiments: experiments.md
|
|
28
37
|
- Shortcuts: shortcuts.md
|
|
29
38
|
- Git Integration: git.md
|
|
39
|
+
- Fast for LLMs and Agents: agents.md
|
|
40
|
+
- MCP Server Tutorial: mcp_tutorial.md
|
|
30
41
|
- Code Similarity: similarity_tutorial.md
|
|
42
|
+
- LLM/Agent Feature TODOs: llm_features.md
|
|
31
43
|
- Pry Integration: pry-integration.md
|
|
32
44
|
- Editors' Integration: editors-integration.md
|
|
33
45
|
- Research: research.md
|
|
34
46
|
- Ideas: ideas.md
|
|
35
47
|
- Videos: videos.md
|
|
36
|
-
- SQL
|
|
48
|
+
- SQL:
|
|
49
|
+
- Intro: sql/index.md
|
|
50
|
+
- Shortcuts: sql/shortcuts.md
|
|
51
|
+
- About: sql-support.md
|
metadata
CHANGED
|
@@ -1,29 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ffast
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jônatas Davi Paganini
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-03-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: astrolabe
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - ">="
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0'
|
|
20
|
-
type: :runtime
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - ">="
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0'
|
|
27
13
|
- !ruby/object:Gem::Dependency
|
|
28
14
|
name: coderay
|
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -52,20 +38,6 @@ dependencies:
|
|
|
52
38
|
- - ">="
|
|
53
39
|
- !ruby/object:Gem::Version
|
|
54
40
|
version: '0'
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: parser
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - ">="
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '0'
|
|
62
|
-
type: :runtime
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - ">="
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '0'
|
|
69
41
|
- !ruby/object:Gem::Dependency
|
|
70
42
|
name: pg_query
|
|
71
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -271,6 +243,8 @@ executables:
|
|
|
271
243
|
extensions: []
|
|
272
244
|
extra_rdoc_files: []
|
|
273
245
|
files:
|
|
246
|
+
- ".github/workflows/release.yml"
|
|
247
|
+
- ".github/workflows/ruby.yml"
|
|
274
248
|
- ".gitignore"
|
|
275
249
|
- ".projections.json"
|
|
276
250
|
- ".rspec"
|
|
@@ -288,43 +262,27 @@ files:
|
|
|
288
262
|
- bin/console
|
|
289
263
|
- bin/fast
|
|
290
264
|
- bin/fast-experiment
|
|
265
|
+
- bin/fast-mcp
|
|
291
266
|
- bin/setup
|
|
292
|
-
- docs/command_line.md
|
|
293
|
-
- docs/editors-integration.md
|
|
294
|
-
- docs/experiments.md
|
|
295
|
-
- docs/git.md
|
|
296
|
-
- docs/ideas.md
|
|
297
|
-
- docs/index.md
|
|
298
|
-
- docs/pry-integration.md
|
|
299
|
-
- docs/research.md
|
|
300
|
-
- docs/shortcuts.md
|
|
301
|
-
- docs/similarity_tutorial.md
|
|
302
|
-
- docs/sql-support.md
|
|
303
|
-
- docs/syntax.md
|
|
304
|
-
- docs/videos.md
|
|
305
|
-
- docs/walkthrough.md
|
|
306
|
-
- examples/build_stubbed_and_let_it_be_experiment.rb
|
|
307
|
-
- examples/experimental_replacement.rb
|
|
308
|
-
- examples/find_usage.rb
|
|
309
|
-
- examples/let_it_be_experiment.rb
|
|
310
|
-
- examples/method_complexity.rb
|
|
311
|
-
- examples/search_duplicated.rb
|
|
312
|
-
- examples/similarity_research.rb
|
|
313
|
-
- examples/simple_rewriter.rb
|
|
314
|
-
- experiments/let_it_be_experiment.rb
|
|
315
|
-
- experiments/remove_useless_hook.rb
|
|
316
|
-
- experiments/replace_create_with_build_stubbed.rb
|
|
317
267
|
- fast.gemspec
|
|
318
268
|
- lib/fast.rb
|
|
319
269
|
- lib/fast/cli.rb
|
|
320
270
|
- lib/fast/experiment.rb
|
|
321
271
|
- lib/fast/git.rb
|
|
272
|
+
- lib/fast/mcp_server.rb
|
|
273
|
+
- lib/fast/node.rb
|
|
274
|
+
- lib/fast/prism_adapter.rb
|
|
322
275
|
- lib/fast/rewriter.rb
|
|
276
|
+
- lib/fast/scan.rb
|
|
323
277
|
- lib/fast/shortcut.rb
|
|
278
|
+
- lib/fast/source.rb
|
|
279
|
+
- lib/fast/source_rewriter.rb
|
|
324
280
|
- lib/fast/sql.rb
|
|
325
281
|
- lib/fast/sql/rewriter.rb
|
|
282
|
+
- lib/fast/summary.rb
|
|
326
283
|
- lib/fast/version.rb
|
|
327
284
|
- mkdocs.yml
|
|
285
|
+
- requirements-docs.txt
|
|
328
286
|
homepage: https://jonatas.github.io/fast/
|
|
329
287
|
licenses:
|
|
330
288
|
- MIT
|
|
@@ -360,9 +318,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
360
318
|
- !ruby/object:Gem::Version
|
|
361
319
|
version: '0'
|
|
362
320
|
requirements: []
|
|
363
|
-
rubygems_version: 3.
|
|
364
|
-
signing_key:
|
|
321
|
+
rubygems_version: 3.5.22
|
|
322
|
+
signing_key:
|
|
365
323
|
specification_version: 4
|
|
366
324
|
summary: 'FAST: Find by AST.'
|
|
367
325
|
test_files: []
|
|
368
|
-
...
|