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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d3e93f183f51e89359bbe6876adfccef46e55caacfa03b3e07ddc5cb71a0b8f
4
- data.tar.gz: 2ce6c1ae1def2dab208b76716912a3aa96b050e88360db65e507b49d8ba248e5
3
+ metadata.gz: 10f0ce4d457d0e9f5bd36e167de9b1904ddfae5194f5b6be022aa269ca292703
4
+ data.tar.gz: 52fc74a1cdef543d8b6c47c4cc8843530f8e3ef3ad91ae28d8394e3438c78059
5
5
  SHA512:
6
- metadata.gz: 852c2276cf66e87a3b972ccdf0597a394ba2d4a528b03ff1e9e6ae15e3d3e0e89de3391bd480a7e2f471de795b50cf5af9be4659b37dcbd87ba91870c8de0da3
7
- data.tar.gz: 82c17f58d9536bc1d95ea7a4fb75d076a283f69b5005fbe83beaccdcbdc5c1c6530346012fe0c8960aa881aa3474177c7707b2404620cd4791991ab2be64fbab
6
+ metadata.gz: b4eb3a6cdf87afb63722f01b3ba3840fa96766a5636585cdec3b17d5b6ad630746d3e06e05b599960bb907db084a30c644cd2778868684f5f681953a1dbb411e
7
+ data.tar.gz: 994023a5b4da885e0b9eccd1641381e00b7142f47efbb75d27bcfe4da4b36c1cb07f000cbdbc5f0d5b57e5ef2d9c00c43bfff9251bd236cdc9e5eee01e21d683
data/.rubocop.yml CHANGED
@@ -55,6 +55,9 @@ Style/IdenticalConditionalBranches:
55
55
  Style/IfInsideElse:
56
56
  Enabled: false
57
57
 
58
+ Style/IfWithBooleanLiteralBranches:
59
+ Enabled: false
60
+
58
61
  Style/KeywordParametersOrder:
59
62
  Enabled: false
60
63
 
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/v3.6.3...HEAD
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 (3.6.3)
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 (0.1.0)
17
+ prettier_print (1.0.0)
18
18
  rainbow (3.1.1)
19
19
  rake (13.0.6)
20
- regexp_parser (2.5.0)
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.2.0)
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
- filepath = File.expand_path("../lib/syntax_tree/node.rb", __dir__)
18
- SyntaxTree.format(File.read(filepath))
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
 
@@ -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 = glob.match(/\A'(.*)'\z/) ? $1 : glob
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
- !File.fnmatch?(options.ignore_files, filepath)
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
- leading, trailing = node.comments.partition(&:leading?)
65
+ trailing = []
66
+ last_leading = nil
66
67
 
67
- # Print all comments that were found before the node.
68
- leading.each do |comment|
69
- comment.format(self)
70
- breakable(force: true)
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 leading.last&.ignore?
83
+ if last_leading&.ignore?
77
84
  range = source[node.location.start_char...node.location.end_char]
78
- separator = -> { breakable(indent: false, force: true) }
79
- seplist(range.split(/\r?\n/, -1), separator) { |line| text(line) }
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