syntax_tree 3.6.3 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +15 -1
- data/Gemfile.lock +5 -5
- data/README.md +32 -10
- data/bin/profile +5 -6
- data/lib/syntax_tree/cli.rb +3 -3
- data/lib/syntax_tree/formatter.rb +67 -8
- data/lib/syntax_tree/node.rb +775 -527
- data/lib/syntax_tree/parser.rb +335 -245
- data/lib/syntax_tree/version.rb +1 -1
- data/lib/syntax_tree/visitor/environment.rb +81 -0
- data/lib/syntax_tree/visitor/with_environment.rb +141 -0
- data/lib/syntax_tree.rb +14 -2
- data/syntax_tree.gemspec +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10f0ce4d457d0e9f5bd36e167de9b1904ddfae5194f5b6be022aa269ca292703
|
4
|
+
data.tar.gz: 52fc74a1cdef543d8b6c47c4cc8843530f8e3ef3ad91ae28d8394e3438c78059
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4eb3a6cdf87afb63722f01b3ba3840fa96766a5636585cdec3b17d5b6ad630746d3e06e05b599960bb907db084a30c644cd2778868684f5f681953a1dbb411e
|
7
|
+
data.tar.gz: 994023a5b4da885e0b9eccd1641381e00b7142f47efbb75d27bcfe4da4b36c1cb07f000cbdbc5f0d5b57e5ef2d9c00c43bfff9251bd236cdc9e5eee01e21d683
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [4.0.0] - 2022-10-17
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- [#169](https://github.com/ruby-syntax-tree/syntax_tree/pull/169) - You can now pass `--ignore-files` multiple times.
|
14
|
+
- [#157](https://github.com/ruby-syntax-tree/syntax_tree/pull/157) - We now support tracking local variable definitions throughout the visitor. This allows you to access scope information while visiting the tree.
|
15
|
+
- [#170](https://github.com/ruby-syntax-tree/syntax_tree/pull/170) - There is now an undocumented `STREE_FAST_FORMAT` environment variable checked when formatting. It has the effect of turning _off_ formatting call chains and ternaries in special ways. This improves performance quite a bit. I'm leaving it undocumented because ideally we just improve the performance as a whole. This is meant as a stopgap until we get there.
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- [#170](https://github.com/ruby-syntax-tree/syntax_tree/pull/170) - We now require at least version `1.0.0` of `prettier_print`. This is to take advantage of the first-class string support in the doc tree.
|
20
|
+
- [#170](https://github.com/ruby-syntax-tree/syntax_tree/pull/170) - Pattern matching has been removed from usage internal to this library (excluding the language server). This should hopefully enable runtimes that don't have pattern matching fully implemented yet (e.g., TruffleRuby) to run this gem.
|
21
|
+
|
9
22
|
## [3.6.3] - 2022-10-11
|
10
23
|
|
11
24
|
### Changed
|
@@ -370,7 +383,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
370
383
|
|
371
384
|
- 🎉 Initial release! 🎉
|
372
385
|
|
373
|
-
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/
|
386
|
+
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v4.0.0...HEAD
|
387
|
+
[4.0.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.6.3...v4.0.0
|
374
388
|
[3.6.3]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.6.2...v3.6.3
|
375
389
|
[3.6.2]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.6.1...v3.6.2
|
376
390
|
[3.6.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.6.0...v3.6.1
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
syntax_tree (
|
5
|
-
prettier_print
|
4
|
+
syntax_tree (4.0.0)
|
5
|
+
prettier_print (>= 1.0.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
@@ -14,10 +14,10 @@ GEM
|
|
14
14
|
parallel (1.22.1)
|
15
15
|
parser (3.1.2.1)
|
16
16
|
ast (~> 2.4.1)
|
17
|
-
prettier_print (
|
17
|
+
prettier_print (1.0.0)
|
18
18
|
rainbow (3.1.1)
|
19
19
|
rake (13.0.6)
|
20
|
-
regexp_parser (2.
|
20
|
+
regexp_parser (2.6.0)
|
21
21
|
rexml (3.2.5)
|
22
22
|
rubocop (1.36.0)
|
23
23
|
json (~> 2.3)
|
@@ -38,7 +38,7 @@ GEM
|
|
38
38
|
simplecov_json_formatter (~> 0.1)
|
39
39
|
simplecov-html (0.12.3)
|
40
40
|
simplecov_json_formatter (0.1.4)
|
41
|
-
unicode-display_width (2.
|
41
|
+
unicode-display_width (2.3.0)
|
42
42
|
|
43
43
|
PLATFORMS
|
44
44
|
arm64-darwin-21
|
data/README.md
CHANGED
@@ -368,16 +368,16 @@ program = SyntaxTree.parse("1 + 1")
|
|
368
368
|
puts program.construct_keys
|
369
369
|
|
370
370
|
# SyntaxTree::Program[
|
371
|
-
# statements: SyntaxTree::Statements[
|
372
|
-
# body: [
|
373
|
-
# SyntaxTree::Binary[
|
374
|
-
# left: SyntaxTree::Int[value: "1"],
|
375
|
-
# operator: :+,
|
376
|
-
# right: SyntaxTree::Int[value: "1"]
|
377
|
-
# ]
|
378
|
-
# ]
|
379
|
-
# ]
|
380
|
-
# ]
|
371
|
+
# statements: SyntaxTree::Statements[
|
372
|
+
# body: [
|
373
|
+
# SyntaxTree::Binary[
|
374
|
+
# left: SyntaxTree::Int[value: "1"],
|
375
|
+
# operator: :+,
|
376
|
+
# right: SyntaxTree::Int[value: "1"]
|
377
|
+
# ]
|
378
|
+
# ]
|
379
|
+
# ]
|
380
|
+
# ]
|
381
381
|
```
|
382
382
|
|
383
383
|
## Visitor
|
@@ -447,6 +447,28 @@ end
|
|
447
447
|
|
448
448
|
The visitor defined above will error out unless it's only visiting a `SyntaxTree::Int` node. This is useful in a couple of ways, e.g., if you're trying to define a visitor to handle the whole tree but it's currently a work-in-progress.
|
449
449
|
|
450
|
+
### WithEnvironment
|
451
|
+
|
452
|
+
The `WithEnvironment` module can be included in visitors to automatically keep track of local variables and arguments
|
453
|
+
defined inside each environment. A `current_environment` accessor is made availble to the request, allowing it to find
|
454
|
+
all usages and definitions of a local.
|
455
|
+
|
456
|
+
```ruby
|
457
|
+
class MyVisitor < Visitor
|
458
|
+
include WithEnvironment
|
459
|
+
|
460
|
+
def visit_ident(node)
|
461
|
+
# find_local will return a Local for any local variables or arguments present in the current environment or nil if
|
462
|
+
# the identifier is not a local
|
463
|
+
local = current_environment.find_local(node)
|
464
|
+
|
465
|
+
puts local.type # print the type of the local (:variable or :argument)
|
466
|
+
puts local.definitions # print the array of locations where this local is defined
|
467
|
+
puts local.usages # print the array of locations where this local occurs
|
468
|
+
end
|
469
|
+
end
|
470
|
+
```
|
471
|
+
|
450
472
|
## Language server
|
451
473
|
|
452
474
|
Syntax Tree additionally ships with a language server conforming to the [language server protocol](https://microsoft.github.io/language-server-protocol/). It can be invoked through the CLI by running:
|
data/bin/profile
CHANGED
@@ -6,22 +6,21 @@ require "bundler/inline"
|
|
6
6
|
gemfile do
|
7
7
|
source "https://rubygems.org"
|
8
8
|
gem "stackprof"
|
9
|
+
gem "prettier_print"
|
9
10
|
end
|
10
11
|
|
11
12
|
$:.unshift(File.expand_path("../lib", __dir__))
|
12
13
|
require "syntax_tree"
|
13
14
|
|
14
|
-
GC.disable
|
15
|
-
|
16
15
|
StackProf.run(mode: :cpu, out: "tmp/profile.dump", raw: true) do
|
17
|
-
|
18
|
-
|
16
|
+
Dir[File.join(RbConfig::CONFIG["libdir"], "**/*.rb")].each do |filepath|
|
17
|
+
SyntaxTree.format(SyntaxTree.read(filepath))
|
18
|
+
end
|
19
19
|
end
|
20
20
|
|
21
|
-
GC.enable
|
22
|
-
|
23
21
|
File.open("tmp/flamegraph.html", "w") do |file|
|
24
22
|
report = Marshal.load(IO.binread("tmp/profile.dump"))
|
23
|
+
StackProf::Report.new(report).print_text
|
25
24
|
StackProf::Report.new(report).print_d3_flamegraph(file)
|
26
25
|
end
|
27
26
|
|
data/lib/syntax_tree/cli.rb
CHANGED
@@ -290,7 +290,7 @@ module SyntaxTree
|
|
290
290
|
:target_ruby_version
|
291
291
|
|
292
292
|
def initialize(print_width: DEFAULT_PRINT_WIDTH)
|
293
|
-
@ignore_files =
|
293
|
+
@ignore_files = []
|
294
294
|
@plugins = []
|
295
295
|
@print_width = print_width
|
296
296
|
@scripts = []
|
@@ -313,7 +313,7 @@ module SyntaxTree
|
|
313
313
|
# Any of the CLI commands that operate on filenames will then ignore
|
314
314
|
# this set of files.
|
315
315
|
opts.on("--ignore-files=GLOB") do |glob|
|
316
|
-
@ignore_files
|
316
|
+
@ignore_files << (glob.match(/\A'(.*)'\z/) ? $1 : glob)
|
317
317
|
end
|
318
318
|
|
319
319
|
# If there are any plugins specified on the command line, then load
|
@@ -434,7 +434,7 @@ module SyntaxTree
|
|
434
434
|
.glob(pattern)
|
435
435
|
.each do |filepath|
|
436
436
|
if File.readable?(filepath) &&
|
437
|
-
|
437
|
+
options.ignore_files.none? { File.fnmatch?(_1, filepath) }
|
438
438
|
queue << FileItem.new(filepath)
|
439
439
|
end
|
440
440
|
end
|
@@ -62,21 +62,39 @@ module SyntaxTree
|
|
62
62
|
# If there are comments, then we're going to format them around the node
|
63
63
|
# so that they get printed properly.
|
64
64
|
if node.comments.any?
|
65
|
-
|
65
|
+
trailing = []
|
66
|
+
last_leading = nil
|
66
67
|
|
67
|
-
#
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
# First, we're going to print all of the comments that were found before
|
69
|
+
# the node. We'll also gather up any trailing comments that we find.
|
70
|
+
node.comments.each do |comment|
|
71
|
+
if comment.leading?
|
72
|
+
comment.format(self)
|
73
|
+
breakable(force: true)
|
74
|
+
last_leading = comment
|
75
|
+
else
|
76
|
+
trailing << comment
|
77
|
+
end
|
71
78
|
end
|
72
79
|
|
73
80
|
# If the node has a stree-ignore comment right before it, then we're
|
74
81
|
# going to just print out the node as it was seen in the source.
|
75
82
|
doc =
|
76
|
-
if
|
83
|
+
if last_leading&.ignore?
|
77
84
|
range = source[node.location.start_char...node.location.end_char]
|
78
|
-
|
79
|
-
|
85
|
+
first = true
|
86
|
+
|
87
|
+
range.each_line(chomp: true) do |line|
|
88
|
+
if first
|
89
|
+
first = false
|
90
|
+
else
|
91
|
+
breakable_return
|
92
|
+
end
|
93
|
+
|
94
|
+
text(line)
|
95
|
+
end
|
96
|
+
|
97
|
+
breakable_return if range.end_with?("\n")
|
80
98
|
else
|
81
99
|
node.format(self)
|
82
100
|
end
|
@@ -101,6 +119,10 @@ module SyntaxTree
|
|
101
119
|
nodes.each { |node| format(node) }
|
102
120
|
end
|
103
121
|
|
122
|
+
def grandparent
|
123
|
+
stack[-3]
|
124
|
+
end
|
125
|
+
|
104
126
|
def parent
|
105
127
|
stack[-2]
|
106
128
|
end
|
@@ -108,5 +130,42 @@ module SyntaxTree
|
|
108
130
|
def parents
|
109
131
|
stack[0...-1].reverse_each
|
110
132
|
end
|
133
|
+
|
134
|
+
# This is a simplified version of prettyprint's group. It doesn't provide
|
135
|
+
# any of the more advanced options because we don't need them and they take
|
136
|
+
# up expensive computation time.
|
137
|
+
def group
|
138
|
+
contents = []
|
139
|
+
doc = Group.new(0, contents: contents)
|
140
|
+
|
141
|
+
groups << doc
|
142
|
+
target << doc
|
143
|
+
|
144
|
+
with_target(contents) { yield }
|
145
|
+
groups.pop
|
146
|
+
doc
|
147
|
+
end
|
148
|
+
|
149
|
+
# A similar version to the super, except that it calls back into the
|
150
|
+
# separator proc with the instance of `self`.
|
151
|
+
def seplist(list, sep = nil, iter_method = :each)
|
152
|
+
first = true
|
153
|
+
list.__send__(iter_method) do |*v|
|
154
|
+
if first
|
155
|
+
first = false
|
156
|
+
elsif sep
|
157
|
+
sep.call(self)
|
158
|
+
else
|
159
|
+
comma_breakable
|
160
|
+
end
|
161
|
+
yield(*v)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# This is a much simplified version of prettyprint's text. It avoids
|
166
|
+
# calculating width by pushing the string directly onto the target.
|
167
|
+
def text(string)
|
168
|
+
target << string
|
169
|
+
end
|
111
170
|
end
|
112
171
|
end
|