oxc 0.1.0-aarch64-linux-gnu → 0.2.0-aarch64-linux-gnu
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/README.md +165 -0
- data/ext/oxc/extconf.rb +2 -2
- data/lib/oxc/3.2/oxc.so +0 -0
- data/lib/oxc/3.3/oxc.so +0 -0
- data/lib/oxc/3.4/oxc.so +0 -0
- data/lib/oxc/4.0/oxc.so +0 -0
- data/lib/oxc/diagnostic.rb +1 -1
- data/lib/oxc/mutation_visitor.rb +128 -0
- data/lib/oxc/node.rb +186 -0
- data/lib/oxc/options.rb +2 -2
- data/lib/oxc/parse_result.rb +15 -5
- data/lib/oxc/result.rb +1 -1
- data/lib/oxc/version.rb +1 -1
- data/lib/oxc/visitor.rb +25 -0
- data/lib/oxc.rb +6 -3
- data/rust/Cargo.lock +1 -1
- data/rust/Cargo.toml +1 -1
- data/sig/oxc/mutation_visitor.rbs +80 -0
- data/sig/oxc/node.rbs +94 -0
- data/sig/oxc/options.rbs +2 -2
- data/sig/oxc/parse_result.rbs +9 -4
- data/sig/oxc/result.rbs +2 -2
- data/sig/oxc/visitor.rbs +11 -0
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5dc785957bee07cb9ebb340e741a8647cfa2f8fb68985c670ba655a25e88eba4
|
|
4
|
+
data.tar.gz: 1b1db8676e5eaa79c7d4c3e9617bcfb96fe7026d77eb7a96051d60cc7435f657
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9bd91b118312a60ff6d7abcd60142db4582f0fc2173ecaa350e85c2ccb1d0c5a39405495c4fadf55cb269795bbeb556460cf408ef92ed56e132115ead4d7e734
|
|
7
|
+
data.tar.gz: 4f6760423b7ae3db60792d5da5df4ff1313f96f9042b122a2cac2f062cb720f855639d55716fa486df9b4087954a72fe7b767c68985969e558a1949ae6c710af
|
data/README.md
CHANGED
|
@@ -205,6 +205,171 @@ Oxc.parse("let a; let a;", semantic_errors: true).errors.map(&:message)
|
|
|
205
205
|
#=> ["Identifier `a` has already been declared"]
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
+
#### Walking the AST
|
|
209
|
+
|
|
210
|
+
`root` answers the program as an `Oxc::Node`, which walks, reads its fields by name, and knows what it sits inside.
|
|
211
|
+
|
|
212
|
+
```ruby
|
|
213
|
+
root = Oxc.parse(source).root
|
|
214
|
+
|
|
215
|
+
root.type #=> "Program"
|
|
216
|
+
root.keys #=> the ESTree fields this node carries
|
|
217
|
+
root.fields #=> those fields and their values, without the span
|
|
218
|
+
root.child_nodes #=> the nodes directly under it
|
|
219
|
+
root.every("Identifier") #=> every identifier in the file
|
|
220
|
+
root.at(offset) #=> the innermost node covering a byte offset
|
|
221
|
+
root.each #=> an Enumerator over every node
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Inspecting a node shows every field it carries, so there is always something to reach for next.
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
#<Oxc::Node VariableDeclaration range=[0, 13] kind="let" declarations=[... 1 item]>
|
|
228
|
+
#<Oxc::Node VariableDeclarator range=[4, 13] id=#<Oxc::Node Identifier> init=#<Oxc::Node Literal>>
|
|
229
|
+
#<Oxc::Node Identifier range=[4, 9] name="count">
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Every field is there, so what `inspect` prints and what `keys` answers never disagree. A field holding a node prints as that node's type, one holding a list prints how many it holds, and one holding nothing prints the `nil`, the `false` or the `[]` it holds.
|
|
233
|
+
|
|
234
|
+
An ESTree field always wins over a method of the gem's own, since `name`, `attributes` and `children` are all real fields. `Identifier#name` is the identifier's name, `JSXElement#children` is what the element wraps, and `ImportDeclaration#attributes` is the import's `with` clause. The walker spells its own versions `underscored_type`, `to_h` and `child_nodes`, which no ESTree field can be called.
|
|
235
|
+
|
|
236
|
+
A field comes back as a node when it holds one, so reads chain.
|
|
237
|
+
|
|
238
|
+
```ruby
|
|
239
|
+
declaration = root.child_nodes.first
|
|
240
|
+
|
|
241
|
+
declaration.kind
|
|
242
|
+
#=> "let"
|
|
243
|
+
|
|
244
|
+
declaration.declarations.first.id.name
|
|
245
|
+
#=> "count"
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
ESTree names its fields in camelCase, and a field answers to its snake_case name too, so reading an AST does not mean writing JavaScript casing in Ruby.
|
|
249
|
+
|
|
250
|
+
```ruby
|
|
251
|
+
node.type_annotation # the same field as node.typeAnnotation
|
|
252
|
+
node.super_class # superClass
|
|
253
|
+
root.source_type # sourceType
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Patterns take either name as well, binding what you asked for.
|
|
257
|
+
|
|
258
|
+
```ruby
|
|
259
|
+
node => { type_annotation: { type: }, readonly: }
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`ancestors` is what a rewrite needs, since a reference sits inside the expression that has to be replaced.
|
|
263
|
+
|
|
264
|
+
```ruby
|
|
265
|
+
reference = root.at(source.index("count +="))
|
|
266
|
+
reference.ancestors.find { |node| node.type == "AssignmentExpression" }.slice
|
|
267
|
+
#=> "count += 1"
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
A parse result keeps the source it read and hands it down to every node it builds, so `slice` answers with no argument at all.
|
|
271
|
+
|
|
272
|
+
```ruby
|
|
273
|
+
parsed = Oxc.parse(source)
|
|
274
|
+
|
|
275
|
+
parsed.source
|
|
276
|
+
#=> "let count = 0\nfunction bump() { count += 1; render(count) }"
|
|
277
|
+
|
|
278
|
+
parsed.root.every("FunctionDeclaration").first.slice
|
|
279
|
+
#=> "function bump() { count += 1; render(count) }"
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
It still takes one, for a node assembled by hand or read against a different string.
|
|
283
|
+
|
|
284
|
+
```ruby
|
|
285
|
+
node.slice(other_source)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Nodes pattern match, and nest, since a field holding a node comes back as one.
|
|
289
|
+
|
|
290
|
+
```ruby
|
|
291
|
+
node => { type: "VariableDeclarator", id: { name: }, init: { value: } }
|
|
292
|
+
name #=> "count"
|
|
293
|
+
value #=> 0
|
|
294
|
+
|
|
295
|
+
root.select { |node| node in { type: "FunctionDeclaration", id: { name: /^handle/ } } }
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
`deconstruct_keys` is the whole protocol here. There is no `deconstruct`, since `each` yields every descendant and an array pattern over direct children would disagree with `to_a`.
|
|
299
|
+
|
|
300
|
+
`to_h` and `to_json` answer the ESTree the node wraps, which is what a snapshot test or a dump to another tool wants.
|
|
301
|
+
|
|
302
|
+
```ruby
|
|
303
|
+
node.to_h
|
|
304
|
+
#=> { "type" => "Identifier", "name" => "count", "start" => 4, "end" => 9 }
|
|
305
|
+
|
|
306
|
+
node.to_json
|
|
307
|
+
#=> "{\"type\":\"Identifier\",\"name\":\"count\",\"start\":4,\"end\":9}"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
`Oxc::Visitor` answers a node with the method named after its type, and walks through anything nothing answers.
|
|
311
|
+
|
|
312
|
+
```ruby
|
|
313
|
+
class Reads < Oxc::Visitor
|
|
314
|
+
def visit_assignment_expression(node)
|
|
315
|
+
puts "#{node.left["name"]} #{node.operator}"
|
|
316
|
+
|
|
317
|
+
visit_children(node)
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
Reads.new.visit(Oxc.parse(source))
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
It takes a parse result or a node, so the common case needs no `root`. A result with no AST is nothing to walk and visits nothing.
|
|
325
|
+
|
|
326
|
+
There is one node class, not one per type, so a type the gem has never seen still walks and still answers. The types and their fields are [ESTree](https://github.com/estree/estree). For the TypeScript and JSX nodes, which ESTree does not cover, oxc publishes the exact shapes it emits as [`@oxc-project/types`](https://www.npmjs.com/package/@oxc-project/types).
|
|
327
|
+
|
|
328
|
+
#### Rewriting
|
|
329
|
+
|
|
330
|
+
`Oxc::MutationVisitor` records what to do to a node and splices the original text at the end, so everything it did not touch survives byte for byte, comments and indentation included.
|
|
331
|
+
|
|
332
|
+
```ruby
|
|
333
|
+
class Renamer < Oxc::MutationVisitor
|
|
334
|
+
def visit_identifier(node)
|
|
335
|
+
replace(node, "renamed") if node["name"] == "count"
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
Renamer.new.rewrite("let count = 1 // keep me")
|
|
340
|
+
#=> "let renamed = 1 // keep me"
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
`replace`, `remove`, `insert_before`, `insert_after` and `wrap` are the operations, and each takes a node. Spans are exact, so removing `debugger;` removes what the node covered and leaves the newline after it alone.
|
|
344
|
+
|
|
345
|
+
Walking into a node that was replaced would edit text that is no longer there, so it stops. Two edits over the same span raise `Oxc::MutationVisitor::Overlap` instead of quietly producing something broken.
|
|
346
|
+
|
|
347
|
+
What goes in is text, so a node can become anything, including several statements or nothing at all. Nothing checks it on the way, so the result is read back afterwards and refused if it stopped being JavaScript.
|
|
348
|
+
|
|
349
|
+
```ruby
|
|
350
|
+
Breaker.new.rewrite("foo(data)")
|
|
351
|
+
#=> Oxc::MutationVisitor::Invalid: what was rewritten no longer reads as JavaScript: Unexpected token
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Pass `verify: false` for a fragment that was never going to parse on its own.
|
|
355
|
+
|
|
356
|
+
`parsed` reaches what the source parsed to, so a rewrite can ask for symbols and drive from them. That is the difference between rewriting a name and rewriting the right one.
|
|
357
|
+
|
|
358
|
+
```ruby
|
|
359
|
+
class ToState < Oxc::MutationVisitor
|
|
360
|
+
def rewrite(source) = super(source, symbols: true)
|
|
361
|
+
|
|
362
|
+
def visit_identifier(node)
|
|
363
|
+
reference = parsed.symbols.fetch("declared").flat_map { |symbol| symbol["references"] }
|
|
364
|
+
.find { |found| found["start"] == node.start }
|
|
365
|
+
|
|
366
|
+
replace(node, %(state.get("#{node["name"]}"))) if reference && !reference["write"]
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Drive from references, not from every `Identifier`. That is what keeps a declaration, a shadowed local, and a same-named property out of the rewrite.
|
|
372
|
+
|
|
208
373
|
#### What a file declared, and what it only used
|
|
209
374
|
|
|
210
375
|
`symbols: true` answers every binding with the span it was declared at and the spans of every reference to it, plus the names the file used without declaring.
|
data/ext/oxc/extconf.rb
CHANGED
|
@@ -65,12 +65,12 @@ if target_platform
|
|
|
65
65
|
|
|
66
66
|
system("rustup target add #{target_platform}") || warn("oxc: Failed to add Rust target #{target_platform}")
|
|
67
67
|
|
|
68
|
-
cargo_args = "--release --target #{target_platform}"
|
|
68
|
+
cargo_args = "--release --locked --target #{target_platform}"
|
|
69
69
|
lib_dir = File.join(target_dir, target_platform, "release")
|
|
70
70
|
else
|
|
71
71
|
puts "oxc: Compiling Rust library for native platform..."
|
|
72
72
|
|
|
73
|
-
cargo_args = "--release"
|
|
73
|
+
cargo_args = "--release --locked"
|
|
74
74
|
lib_dir = File.join(target_dir, "release")
|
|
75
75
|
end
|
|
76
76
|
|
data/lib/oxc/3.2/oxc.so
CHANGED
|
Binary file
|
data/lib/oxc/3.3/oxc.so
CHANGED
|
Binary file
|
data/lib/oxc/3.4/oxc.so
CHANGED
|
Binary file
|
data/lib/oxc/4.0/oxc.so
CHANGED
|
Binary file
|
data/lib/oxc/diagnostic.rb
CHANGED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Oxc
|
|
4
|
+
# A visitor that rewrites the source it walked, by recording what to do to a node and splicing the
|
|
5
|
+
# original text at the end. Everything nothing touched survives byte for byte.
|
|
6
|
+
#
|
|
7
|
+
# class Renamer < Oxc::MutationVisitor
|
|
8
|
+
# def visit_identifier(node)
|
|
9
|
+
# replace(node, "renamed") if node["name"] == "count"
|
|
10
|
+
# end
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# Renamer.new.rewrite("let count = 1") #=> "let renamed = 1"
|
|
14
|
+
#
|
|
15
|
+
class MutationVisitor < Visitor
|
|
16
|
+
class Overlap < StandardError; end
|
|
17
|
+
class Invalid < Error; end
|
|
18
|
+
|
|
19
|
+
Edit = Data.define(
|
|
20
|
+
:start, #: Integer
|
|
21
|
+
:finish, #: Integer
|
|
22
|
+
:text, #: String
|
|
23
|
+
:order #: Integer
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
attr_reader :source #: String
|
|
27
|
+
attr_reader :parsed #: Oxc::ParseResult
|
|
28
|
+
|
|
29
|
+
#: (String, ?verify: bool, **untyped) -> String
|
|
30
|
+
def rewrite(source, verify: true, **options)
|
|
31
|
+
@source = source
|
|
32
|
+
@edits = [] #: Array[Edit]
|
|
33
|
+
@replaced = [] #: Array[[Integer, Integer]]
|
|
34
|
+
@parsed = Oxc.parse(source, **options).validate!
|
|
35
|
+
|
|
36
|
+
visit(parsed)
|
|
37
|
+
|
|
38
|
+
rewritten = apply
|
|
39
|
+
|
|
40
|
+
verify ? verified(rewritten, options) : rewritten
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#: (Oxc::Node, String) -> void
|
|
44
|
+
def replace(node, text)
|
|
45
|
+
@replaced << [node.start, node.finish]
|
|
46
|
+
|
|
47
|
+
edit(node.start, node.finish, text)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
#: (Oxc::Node) -> void
|
|
51
|
+
def remove(node)
|
|
52
|
+
replace(node, "")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
#: (Oxc::Node, String) -> void
|
|
56
|
+
def insert_before(node, text)
|
|
57
|
+
edit(node.start, node.start, text)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
#: (Oxc::Node, String) -> void
|
|
61
|
+
def insert_after(node, text)
|
|
62
|
+
edit(node.finish, node.finish, text)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#: (Oxc::Node, String, String) -> void
|
|
66
|
+
def wrap(node, before, after)
|
|
67
|
+
insert_before(node, before)
|
|
68
|
+
insert_after(node, after)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#: (Oxc::Node) -> void
|
|
72
|
+
def visit_children(node)
|
|
73
|
+
return nil if replaced?(node)
|
|
74
|
+
|
|
75
|
+
super
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
#: (String, Hash[Symbol, untyped]) -> String
|
|
81
|
+
def verified(rewritten, options)
|
|
82
|
+
answer = Oxc.parse(rewritten, **options, ast: false)
|
|
83
|
+
|
|
84
|
+
return rewritten unless answer.errors?
|
|
85
|
+
|
|
86
|
+
raise Invalid, "what was rewritten no longer reads as JavaScript: #{answer.errors.first&.message}"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
#: (Oxc::Node) -> bool
|
|
90
|
+
def replaced?(node)
|
|
91
|
+
@replaced.any? { |start, finish| node.start >= start && node.finish <= finish }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
#: (Integer, Integer, String) -> void
|
|
95
|
+
def edit(start, finish, text)
|
|
96
|
+
@edits.each do |existing|
|
|
97
|
+
next unless overlaps?(existing, start, finish)
|
|
98
|
+
|
|
99
|
+
raise Overlap, "an edit at #{start}..#{finish} overlaps one at #{existing.start}..#{existing.finish}"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
@edits << Edit.new(start: start, finish: finish, text: text, order: @edits.length)
|
|
103
|
+
|
|
104
|
+
nil
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
#: (Edit, Integer, Integer) -> bool
|
|
108
|
+
def overlaps?(existing, start, finish)
|
|
109
|
+
return false if existing.start == existing.finish && start == finish
|
|
110
|
+
|
|
111
|
+
start < existing.finish && existing.start < finish
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
#: () -> String
|
|
115
|
+
def apply
|
|
116
|
+
taken = 0
|
|
117
|
+
result = +""
|
|
118
|
+
|
|
119
|
+
@edits.sort_by { |edit| [edit.start, edit.order] }.each do |edit|
|
|
120
|
+
result << source.byteslice(taken, edit.start - taken).to_s << edit.text
|
|
121
|
+
|
|
122
|
+
taken = edit.finish
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
result << source.byteslice(taken..).to_s
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
data/lib/oxc/node.rb
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Oxc
|
|
4
|
+
class Node
|
|
5
|
+
include Enumerable #[Oxc::Node]
|
|
6
|
+
|
|
7
|
+
ACRONYM = /([A-Z]+)([A-Z][a-z])/ #: Regexp
|
|
8
|
+
BOUNDARY = /([a-z\d])([A-Z])/ #: Regexp
|
|
9
|
+
SPAN = ["type", "start", "end"].freeze #: Array[String]
|
|
10
|
+
|
|
11
|
+
attr_reader :parent #: Oxc::Node?
|
|
12
|
+
|
|
13
|
+
protected
|
|
14
|
+
|
|
15
|
+
attr_reader :attributes #: Hash[String, untyped]
|
|
16
|
+
attr_reader :text #: String?
|
|
17
|
+
|
|
18
|
+
public
|
|
19
|
+
|
|
20
|
+
#: (Hash[String, untyped], ?Oxc::Node?, ?String?) -> void
|
|
21
|
+
def initialize(attributes, parent = nil, text = nil)
|
|
22
|
+
@attributes = attributes
|
|
23
|
+
@parent = parent
|
|
24
|
+
@text = text || parent&.text
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
#: () -> String
|
|
28
|
+
def type
|
|
29
|
+
attributes.fetch("type")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
#: () -> Integer
|
|
33
|
+
def start
|
|
34
|
+
attributes.fetch("start")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#: () -> Integer
|
|
38
|
+
def finish
|
|
39
|
+
attributes.fetch("end")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
#: () -> String
|
|
43
|
+
def underscored_type
|
|
44
|
+
@underscored_type ||= type.gsub(ACRONYM, '\1_\2').gsub(BOUNDARY, '\1_\2').downcase
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
#: (String) -> untyped
|
|
48
|
+
def [](key)
|
|
49
|
+
attributes[key]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
#: (?String?) -> String?
|
|
53
|
+
def slice(from = text)
|
|
54
|
+
raise ArgumentError, "this node does not know its source, so #slice needs it" unless from
|
|
55
|
+
|
|
56
|
+
from.byteslice(start, finish - start)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
#: () -> Array[String]
|
|
60
|
+
def keys
|
|
61
|
+
attributes.keys
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
#: () -> Hash[String, untyped]
|
|
65
|
+
def to_h
|
|
66
|
+
attributes
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
#: (?untyped) -> String
|
|
70
|
+
def to_json(state = nil)
|
|
71
|
+
state ? attributes.to_json(state) : attributes.to_json
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#: (Array[Symbol]?) -> Hash[Symbol, untyped]
|
|
75
|
+
def deconstruct_keys(keys)
|
|
76
|
+
found = {} #: Hash[Symbol, untyped]
|
|
77
|
+
|
|
78
|
+
if keys
|
|
79
|
+
keys.each do |name|
|
|
80
|
+
key = field_for(name.to_s)
|
|
81
|
+
|
|
82
|
+
found[name] = wrap(attributes[key]) if key
|
|
83
|
+
end
|
|
84
|
+
else
|
|
85
|
+
attributes.each_key { |key| found[key.to_sym] = wrap(attributes[key]) }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
found
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
#: () -> Array[Oxc::Node]
|
|
92
|
+
def child_nodes
|
|
93
|
+
@child_nodes ||= attributes.each_value
|
|
94
|
+
.flat_map { |value| value.is_a?(Array) ? value : [value] }
|
|
95
|
+
.select { |value| value.is_a?(Hash) && value.key?("type") }
|
|
96
|
+
.map { |value| Node.new(value, self) }
|
|
97
|
+
.freeze
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
#: () { (Oxc::Node) -> void } -> void
|
|
101
|
+
#: () -> Enumerator[Oxc::Node, void]
|
|
102
|
+
def each(&)
|
|
103
|
+
return enum_for(:each) unless block_given?
|
|
104
|
+
|
|
105
|
+
yield self
|
|
106
|
+
|
|
107
|
+
child_nodes.each { |child| child.each(&) }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
#: () -> Array[Oxc::Node]
|
|
111
|
+
def ancestors
|
|
112
|
+
parent ? [parent, *parent.ancestors] : []
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
#: (Integer) -> Oxc::Node?
|
|
116
|
+
def at(offset)
|
|
117
|
+
covering = each.select { |node| offset >= node.start && offset < node.finish }
|
|
118
|
+
|
|
119
|
+
covering.min_by { |node| node.finish - node.start }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
#: (String) -> Array[Oxc::Node]
|
|
123
|
+
def every(type)
|
|
124
|
+
each.select { |node| node.type == type }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
#: () -> Hash[String, untyped]
|
|
128
|
+
def fields
|
|
129
|
+
attributes.except(*SPAN)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
#: () -> String
|
|
133
|
+
def inspect
|
|
134
|
+
described = fields.map { |key, value| described_field(key, value) }
|
|
135
|
+
|
|
136
|
+
"#<#{self.class.name} #{type} range=[#{start}, #{finish}]#{" #{described.join(" ")}" unless described.empty?}>"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
#: (Symbol, *untyped) -> untyped
|
|
140
|
+
def method_missing(name, *arguments)
|
|
141
|
+
key = field_for(name.to_s)
|
|
142
|
+
|
|
143
|
+
return super unless key
|
|
144
|
+
|
|
145
|
+
wrap(attributes[key])
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
#: (Symbol, ?bool) -> bool
|
|
149
|
+
def respond_to_missing?(name, include_private = false)
|
|
150
|
+
!field_for(name.to_s).nil? || super
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private
|
|
154
|
+
|
|
155
|
+
#: (String, untyped) -> String
|
|
156
|
+
def described_field(key, value)
|
|
157
|
+
case value
|
|
158
|
+
when Array then "#{key}=#{if value.empty?
|
|
159
|
+
"[]"
|
|
160
|
+
else
|
|
161
|
+
"[... #{value.length} #{value.length == 1 ? "item" : "items"}]"
|
|
162
|
+
end}"
|
|
163
|
+
when Hash then "#{key}=#<#{self.class.name} #{value["type"]}>"
|
|
164
|
+
else "#{key}=#{value.inspect}"
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
#: (String) -> String?
|
|
169
|
+
def field_for(name)
|
|
170
|
+
return name if attributes.key?(name)
|
|
171
|
+
|
|
172
|
+
camelized = name.gsub(/_([a-z\d])/) { Regexp.last_match(1).to_s.upcase }
|
|
173
|
+
|
|
174
|
+
camelized if attributes.key?(camelized)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
#: (untyped) -> untyped
|
|
178
|
+
def wrap(value)
|
|
179
|
+
case value
|
|
180
|
+
when Hash then value.key?("type") ? Node.new(value, self, text) : value
|
|
181
|
+
when Array then value.map { |item| wrap(item) }
|
|
182
|
+
else value
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
data/lib/oxc/options.rb
CHANGED
data/lib/oxc/parse_result.rb
CHANGED
|
@@ -4,17 +4,19 @@ module Oxc
|
|
|
4
4
|
class ParseResult
|
|
5
5
|
include Diagnosed
|
|
6
6
|
|
|
7
|
+
attr_reader :source #: String?
|
|
7
8
|
attr_reader :program #: Hash[String, untyped]?
|
|
8
9
|
attr_reader :module_record #: Hash[String, untyped]?
|
|
9
10
|
attr_reader :symbols #: Hash[String, untyped]?
|
|
10
11
|
attr_reader :comments #: Array[Oxc::Comment]
|
|
11
12
|
attr_reader :diagnostics #: Array[Oxc::Diagnostic]
|
|
12
13
|
|
|
13
|
-
#: (String) -> Oxc::ParseResult
|
|
14
|
-
def self.from_json(payload)
|
|
14
|
+
#: (String, ?String?) -> Oxc::ParseResult
|
|
15
|
+
def self.from_json(payload, source = nil)
|
|
15
16
|
parsed = JSON.parse(payload)
|
|
16
17
|
|
|
17
18
|
new(
|
|
19
|
+
source: source,
|
|
18
20
|
program: parsed["program"],
|
|
19
21
|
module_record: parsed["module_record"],
|
|
20
22
|
symbols: parsed["symbols"],
|
|
@@ -24,8 +26,9 @@ module Oxc
|
|
|
24
26
|
)
|
|
25
27
|
end
|
|
26
28
|
|
|
27
|
-
#: (comments: Array[Oxc::Comment], diagnostics: Array[Oxc::Diagnostic], ?program: Hash[String, untyped]?, ?module_record: Hash[String, untyped]?, ?symbols: Hash[String, untyped]?, ?panicked: bool) -> void
|
|
28
|
-
def initialize(comments:, diagnostics:, program: nil, module_record: nil, symbols: nil, panicked: false)
|
|
29
|
+
#: (comments: Array[Oxc::Comment], diagnostics: Array[Oxc::Diagnostic], ?source: String?, ?program: Hash[String, untyped]?, ?module_record: Hash[String, untyped]?, ?symbols: Hash[String, untyped]?, ?panicked: bool) -> void
|
|
30
|
+
def initialize(comments:, diagnostics:, source: nil, program: nil, module_record: nil, symbols: nil, panicked: false)
|
|
31
|
+
@source = source
|
|
29
32
|
@program = program.freeze
|
|
30
33
|
@module_record = module_record.freeze
|
|
31
34
|
@symbols = symbols.freeze
|
|
@@ -36,6 +39,11 @@ module Oxc
|
|
|
36
39
|
freeze
|
|
37
40
|
end
|
|
38
41
|
|
|
42
|
+
#: () -> Oxc::Node?
|
|
43
|
+
def root
|
|
44
|
+
program ? Node.new(program, nil, source) : nil
|
|
45
|
+
end
|
|
46
|
+
|
|
39
47
|
#: () -> Oxc::ParseResult
|
|
40
48
|
def validate!
|
|
41
49
|
return self unless errors? || panicked?
|
|
@@ -46,7 +54,9 @@ module Oxc
|
|
|
46
54
|
#: () -> String
|
|
47
55
|
def inspect
|
|
48
56
|
parts = [] #: Array[String]
|
|
49
|
-
parts << "
|
|
57
|
+
parts << "#{root&.type} range=[#{root&.start}, #{root&.finish}]" if program
|
|
58
|
+
parts << "module_record" if module_record
|
|
59
|
+
parts << "symbols=#{symbols.fetch("declared").length}" if symbols
|
|
50
60
|
parts << "comments=#{comments.length}" unless comments.empty?
|
|
51
61
|
parts << "diagnostics=#{diagnostics.length}" unless diagnostics.empty?
|
|
52
62
|
|
data/lib/oxc/result.rb
CHANGED
data/lib/oxc/version.rb
CHANGED
data/lib/oxc/visitor.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Oxc
|
|
4
|
+
class Visitor
|
|
5
|
+
#: (Oxc::Node | Oxc::ParseResult) -> void
|
|
6
|
+
def visit(node)
|
|
7
|
+
node = node.root if node.is_a?(ParseResult)
|
|
8
|
+
|
|
9
|
+
return nil unless node
|
|
10
|
+
|
|
11
|
+
answer = "visit_#{node.underscored_type}"
|
|
12
|
+
|
|
13
|
+
respond_to?(answer) ? public_send(answer, node) : visit_children(node)
|
|
14
|
+
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
#: (Oxc::Node) -> void
|
|
19
|
+
def visit_children(node)
|
|
20
|
+
node.child_nodes.each { |child| visit(child) }
|
|
21
|
+
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/oxc.rb
CHANGED
|
@@ -19,6 +19,9 @@ require_relative "oxc/diagnosed"
|
|
|
19
19
|
require_relative "oxc/result"
|
|
20
20
|
require_relative "oxc/minify_result"
|
|
21
21
|
require_relative "oxc/transform_result"
|
|
22
|
+
require_relative "oxc/node"
|
|
23
|
+
require_relative "oxc/visitor"
|
|
24
|
+
require_relative "oxc/mutation_visitor"
|
|
22
25
|
require_relative "oxc/parse_result"
|
|
23
26
|
require_relative "oxc/transformer"
|
|
24
27
|
require_relative "oxc/minifier"
|
|
@@ -28,21 +31,21 @@ module Oxc
|
|
|
28
31
|
def self.minify(source, **options)
|
|
29
32
|
serialized = Options.serialize(options, Options::MINIFY, "minify")
|
|
30
33
|
|
|
31
|
-
MinifyResult.from_json(Backend.minify(source.to_s, serialized)).validate!(strict: options[:strict])
|
|
34
|
+
MinifyResult.from_json(Backend.minify(source.to_s, serialized)).validate!(strict: options[:strict] ? true : false)
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
#: (String, ?filename: String?, ?lang: String?, ?source_type: String?, ?cwd: String?, ?target: targets?, ?jsx: jsx?, ?typescript: typescript?, ?assumptions: assumptions?, ?decorator: decorator?, ?helpers: helpers?, ?define: Hash[String, String]?, ?inject: inject?, ?minify: minify?, ?codegen: codegen?, ?sourcemap: bool, ?strict: bool) -> Oxc::TransformResult
|
|
35
38
|
def self.transform(source, **options)
|
|
36
39
|
serialized = Options.serialize(options, Options::TRANSFORM, "transform")
|
|
37
40
|
|
|
38
|
-
TransformResult.from_json(Backend.transform(source.to_s, serialized)).validate!(strict: options[:strict])
|
|
41
|
+
TransformResult.from_json(Backend.transform(source.to_s, serialized)).validate!(strict: options[:strict] ? true : false)
|
|
39
42
|
end
|
|
40
43
|
|
|
41
44
|
#: (String, ?filename: String?, ?lang: String?, ?source_type: String?, ?ast_type: String?, ?ast: bool, ?ranges: bool, ?preserve_parens: bool, ?comments: bool, ?module_record: bool, ?symbols: bool, ?semantic_errors: bool) -> Oxc::ParseResult
|
|
42
45
|
def self.parse(source, **options)
|
|
43
46
|
serialized = Options.serialize(options, Options::PARSE, "parse")
|
|
44
47
|
|
|
45
|
-
ParseResult.from_json(Backend.parse(source.to_s, serialized))
|
|
48
|
+
ParseResult.from_json(Backend.parse(source.to_s, serialized), source.to_s)
|
|
46
49
|
end
|
|
47
50
|
|
|
48
51
|
#: () -> String
|
data/rust/Cargo.lock
CHANGED
data/rust/Cargo.toml
CHANGED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Generated from lib/oxc/mutation_visitor.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Oxc
|
|
4
|
+
# A visitor that rewrites the source it walked, by recording what to do to a node and splicing the
|
|
5
|
+
# original text at the end. Everything nothing touched survives byte for byte.
|
|
6
|
+
#
|
|
7
|
+
# class Renamer < Oxc::MutationVisitor
|
|
8
|
+
# def visit_identifier(node)
|
|
9
|
+
# replace(node, "renamed") if node["name"] == "count"
|
|
10
|
+
# end
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# Renamer.new.rewrite("let count = 1") #=> "let renamed = 1"
|
|
14
|
+
class MutationVisitor < Visitor
|
|
15
|
+
class Overlap < StandardError
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class Invalid < Error
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class Edit < Data
|
|
22
|
+
attr_reader start(): Integer
|
|
23
|
+
|
|
24
|
+
attr_reader finish(): Integer
|
|
25
|
+
|
|
26
|
+
attr_reader text(): String
|
|
27
|
+
|
|
28
|
+
attr_reader order(): Integer
|
|
29
|
+
|
|
30
|
+
def self.new: (Integer start, Integer finish, String text, Integer order) -> instance
|
|
31
|
+
| (start: Integer, finish: Integer, text: String, order: Integer) -> instance
|
|
32
|
+
|
|
33
|
+
def self.members: () -> [ :start, :finish, :text, :order ]
|
|
34
|
+
|
|
35
|
+
def members: () -> [ :start, :finish, :text, :order ]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
attr_reader source: String
|
|
39
|
+
|
|
40
|
+
attr_reader parsed: Oxc::ParseResult
|
|
41
|
+
|
|
42
|
+
# : (String, ?verify: bool, **untyped) -> String
|
|
43
|
+
def rewrite: (String, ?verify: bool, **untyped) -> String
|
|
44
|
+
|
|
45
|
+
# : (Oxc::Node, String) -> void
|
|
46
|
+
def replace: (Oxc::Node, String) -> void
|
|
47
|
+
|
|
48
|
+
# : (Oxc::Node) -> void
|
|
49
|
+
def remove: (Oxc::Node) -> void
|
|
50
|
+
|
|
51
|
+
# : (Oxc::Node, String) -> void
|
|
52
|
+
def insert_before: (Oxc::Node, String) -> void
|
|
53
|
+
|
|
54
|
+
# : (Oxc::Node, String) -> void
|
|
55
|
+
def insert_after: (Oxc::Node, String) -> void
|
|
56
|
+
|
|
57
|
+
# : (Oxc::Node, String, String) -> void
|
|
58
|
+
def wrap: (Oxc::Node, String, String) -> void
|
|
59
|
+
|
|
60
|
+
# : (Oxc::Node) -> void
|
|
61
|
+
def visit_children: (Oxc::Node) -> void
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
# : (String, Hash[Symbol, untyped]) -> String
|
|
66
|
+
def verified: (String, Hash[Symbol, untyped]) -> String
|
|
67
|
+
|
|
68
|
+
# : (Oxc::Node) -> bool
|
|
69
|
+
def replaced?: (Oxc::Node) -> bool
|
|
70
|
+
|
|
71
|
+
# : (Integer, Integer, String) -> void
|
|
72
|
+
def edit: (Integer, Integer, String) -> void
|
|
73
|
+
|
|
74
|
+
# : (Edit, Integer, Integer) -> bool
|
|
75
|
+
def overlaps?: (Edit, Integer, Integer) -> bool
|
|
76
|
+
|
|
77
|
+
# : () -> String
|
|
78
|
+
def apply: () -> String
|
|
79
|
+
end
|
|
80
|
+
end
|
data/sig/oxc/node.rbs
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Generated from lib/oxc/node.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Oxc
|
|
4
|
+
class Node
|
|
5
|
+
include Enumerable[Oxc::Node]
|
|
6
|
+
|
|
7
|
+
ACRONYM: Regexp
|
|
8
|
+
|
|
9
|
+
BOUNDARY: Regexp
|
|
10
|
+
|
|
11
|
+
SPAN: Array[String]
|
|
12
|
+
|
|
13
|
+
attr_reader parent: Oxc::Node?
|
|
14
|
+
|
|
15
|
+
attr_reader attributes: Hash[String, untyped]
|
|
16
|
+
|
|
17
|
+
attr_reader text: String?
|
|
18
|
+
|
|
19
|
+
public
|
|
20
|
+
|
|
21
|
+
# : (Hash[String, untyped], ?Oxc::Node?, ?String?) -> void
|
|
22
|
+
def initialize: (Hash[String, untyped], ?Oxc::Node?, ?String?) -> void
|
|
23
|
+
|
|
24
|
+
# : () -> String
|
|
25
|
+
def type: () -> String
|
|
26
|
+
|
|
27
|
+
# : () -> Integer
|
|
28
|
+
def start: () -> Integer
|
|
29
|
+
|
|
30
|
+
# : () -> Integer
|
|
31
|
+
def finish: () -> Integer
|
|
32
|
+
|
|
33
|
+
# : () -> String
|
|
34
|
+
def underscored_type: () -> String
|
|
35
|
+
|
|
36
|
+
# : (String) -> untyped
|
|
37
|
+
def []: (String) -> untyped
|
|
38
|
+
|
|
39
|
+
# : (?String?) -> String?
|
|
40
|
+
def slice: (?String?) -> String?
|
|
41
|
+
|
|
42
|
+
# : () -> Array[String]
|
|
43
|
+
def keys: () -> Array[String]
|
|
44
|
+
|
|
45
|
+
# : () -> Hash[String, untyped]
|
|
46
|
+
def to_h: () -> Hash[String, untyped]
|
|
47
|
+
|
|
48
|
+
# : (?untyped) -> String
|
|
49
|
+
def to_json: (?untyped) -> String
|
|
50
|
+
|
|
51
|
+
# : (Array[Symbol]?) -> Hash[Symbol, untyped]
|
|
52
|
+
def deconstruct_keys: (Array[Symbol]?) -> Hash[Symbol, untyped]
|
|
53
|
+
|
|
54
|
+
# : () -> Array[Oxc::Node]
|
|
55
|
+
def child_nodes: () -> Array[Oxc::Node]
|
|
56
|
+
|
|
57
|
+
# : () { (Oxc::Node) -> void } -> void
|
|
58
|
+
# : () -> Enumerator[Oxc::Node, void]
|
|
59
|
+
def each: () { (Oxc::Node) -> void } -> void
|
|
60
|
+
| () -> Enumerator[Oxc::Node, void]
|
|
61
|
+
|
|
62
|
+
# : () -> Array[Oxc::Node]
|
|
63
|
+
def ancestors: () -> Array[Oxc::Node]
|
|
64
|
+
|
|
65
|
+
# : (Integer) -> Oxc::Node?
|
|
66
|
+
def at: (Integer) -> Oxc::Node?
|
|
67
|
+
|
|
68
|
+
# : (String) -> Array[Oxc::Node]
|
|
69
|
+
def every: (String) -> Array[Oxc::Node]
|
|
70
|
+
|
|
71
|
+
# : () -> Hash[String, untyped]
|
|
72
|
+
def fields: () -> Hash[String, untyped]
|
|
73
|
+
|
|
74
|
+
# : () -> String
|
|
75
|
+
def inspect: () -> String
|
|
76
|
+
|
|
77
|
+
# : (Symbol, *untyped) -> untyped
|
|
78
|
+
def method_missing: (Symbol, *untyped) -> untyped
|
|
79
|
+
|
|
80
|
+
# : (Symbol, ?bool) -> bool
|
|
81
|
+
def respond_to_missing?: (Symbol, ?bool) -> bool
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
# : (String, untyped) -> String
|
|
86
|
+
def described_field: (String, untyped) -> String
|
|
87
|
+
|
|
88
|
+
# : (String) -> String?
|
|
89
|
+
def field_for: (String) -> String?
|
|
90
|
+
|
|
91
|
+
# : (untyped) -> untyped
|
|
92
|
+
def wrap: (untyped) -> untyped
|
|
93
|
+
end
|
|
94
|
+
end
|
data/sig/oxc/options.rbs
CHANGED
|
@@ -25,8 +25,8 @@ module Oxc
|
|
|
25
25
|
# : (Hash[Symbol, untyped], ?Array[Symbol], ?String) -> void
|
|
26
26
|
def initialize: (Hash[Symbol, untyped], ?Array[Symbol], ?String) -> void
|
|
27
27
|
|
|
28
|
-
# : (?
|
|
29
|
-
def to_json: (?
|
|
28
|
+
# : (?JSON::options?) -> String
|
|
29
|
+
def to_json: (?JSON::options?) -> String
|
|
30
30
|
|
|
31
31
|
# : () -> String
|
|
32
32
|
def inspect: () -> String
|
data/sig/oxc/parse_result.rbs
CHANGED
|
@@ -4,6 +4,8 @@ module Oxc
|
|
|
4
4
|
class ParseResult
|
|
5
5
|
include Diagnosed
|
|
6
6
|
|
|
7
|
+
attr_reader source: String?
|
|
8
|
+
|
|
7
9
|
attr_reader program: Hash[String, untyped]?
|
|
8
10
|
|
|
9
11
|
attr_reader module_record: Hash[String, untyped]?
|
|
@@ -14,11 +16,14 @@ module Oxc
|
|
|
14
16
|
|
|
15
17
|
attr_reader diagnostics: Array[Oxc::Diagnostic]
|
|
16
18
|
|
|
17
|
-
# : (String) -> Oxc::ParseResult
|
|
18
|
-
def self.from_json: (String) -> Oxc::ParseResult
|
|
19
|
+
# : (String, ?String?) -> Oxc::ParseResult
|
|
20
|
+
def self.from_json: (String, ?String?) -> Oxc::ParseResult
|
|
21
|
+
|
|
22
|
+
# : (comments: Array[Oxc::Comment], diagnostics: Array[Oxc::Diagnostic], ?source: String?, ?program: Hash[String, untyped]?, ?module_record: Hash[String, untyped]?, ?symbols: Hash[String, untyped]?, ?panicked: bool) -> void
|
|
23
|
+
def initialize: (comments: Array[Oxc::Comment], diagnostics: Array[Oxc::Diagnostic], ?source: String?, ?program: Hash[String, untyped]?, ?module_record: Hash[String, untyped]?, ?symbols: Hash[String, untyped]?, ?panicked: bool) -> void
|
|
19
24
|
|
|
20
|
-
# : (
|
|
21
|
-
def
|
|
25
|
+
# : () -> Oxc::Node?
|
|
26
|
+
def root: () -> Oxc::Node?
|
|
22
27
|
|
|
23
28
|
# : () -> Oxc::ParseResult
|
|
24
29
|
def validate!: () -> Oxc::ParseResult
|
data/sig/oxc/result.rbs
CHANGED
|
@@ -15,8 +15,8 @@ module Oxc
|
|
|
15
15
|
# : (code: String, diagnostics: Array[Oxc::Diagnostic], ?map: String?, ?legal_comments: Array[String], ?panicked: bool) -> void
|
|
16
16
|
def initialize: (code: String, diagnostics: Array[Oxc::Diagnostic], ?map: String?, ?legal_comments: Array[String], ?panicked: bool) -> void
|
|
17
17
|
|
|
18
|
-
# : (?strict:
|
|
19
|
-
def validate!: (?strict:
|
|
18
|
+
# : (?strict: bool?) -> self
|
|
19
|
+
def validate!: (?strict: bool?) -> self
|
|
20
20
|
|
|
21
21
|
# : () -> String
|
|
22
22
|
def to_s: () -> String
|
data/sig/oxc/visitor.rbs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Generated from lib/oxc/visitor.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Oxc
|
|
4
|
+
class Visitor
|
|
5
|
+
# : (Oxc::Node | Oxc::ParseResult) -> void
|
|
6
|
+
def visit: (Oxc::Node | Oxc::ParseResult) -> void
|
|
7
|
+
|
|
8
|
+
# : (Oxc::Node) -> void
|
|
9
|
+
def visit_children: (Oxc::Node) -> void
|
|
10
|
+
end
|
|
11
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: oxc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: aarch64-linux-gnu
|
|
6
6
|
authors:
|
|
7
7
|
- Marco Roth
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Ruby bindings for Oxc, the JavaScript Oxidation Compiler. A collection
|
|
14
14
|
of high-performance tools for JavaScript and TypeScript written in Rust.
|
|
@@ -34,12 +34,15 @@ files:
|
|
|
34
34
|
- lib/oxc/errors.rb
|
|
35
35
|
- lib/oxc/minifier.rb
|
|
36
36
|
- lib/oxc/minify_result.rb
|
|
37
|
+
- lib/oxc/mutation_visitor.rb
|
|
38
|
+
- lib/oxc/node.rb
|
|
37
39
|
- lib/oxc/options.rb
|
|
38
40
|
- lib/oxc/parse_result.rb
|
|
39
41
|
- lib/oxc/result.rb
|
|
40
42
|
- lib/oxc/transform_result.rb
|
|
41
43
|
- lib/oxc/transformer.rb
|
|
42
44
|
- lib/oxc/version.rb
|
|
45
|
+
- lib/oxc/visitor.rb
|
|
43
46
|
- licenses/README.md
|
|
44
47
|
- licenses/oxc-MIT.txt
|
|
45
48
|
- licenses/oxc-THIRD-PARTY.txt
|
|
@@ -65,6 +68,8 @@ files:
|
|
|
65
68
|
- sig/oxc/errors.rbs
|
|
66
69
|
- sig/oxc/minifier.rbs
|
|
67
70
|
- sig/oxc/minify_result.rbs
|
|
71
|
+
- sig/oxc/mutation_visitor.rbs
|
|
72
|
+
- sig/oxc/node.rbs
|
|
68
73
|
- sig/oxc/options.rbs
|
|
69
74
|
- sig/oxc/parse_result.rbs
|
|
70
75
|
- sig/oxc/result.rbs
|
|
@@ -72,6 +77,7 @@ files:
|
|
|
72
77
|
- sig/oxc/transformer.rbs
|
|
73
78
|
- sig/oxc/types.rbs
|
|
74
79
|
- sig/oxc/version.rbs
|
|
80
|
+
- sig/oxc/visitor.rbs
|
|
75
81
|
homepage: https://github.com/marcoroth/oxc-ruby
|
|
76
82
|
licenses:
|
|
77
83
|
- MIT
|