syntax_tree 3.2.0 → 3.4.0
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/.rubocop.yml +1 -1
- data/CHANGELOG.md +30 -1
- data/Gemfile.lock +6 -6
- data/README.md +48 -3
- data/lib/syntax_tree/cli.rb +104 -75
- data/lib/syntax_tree/language_server.rb +9 -3
- data/lib/syntax_tree/node.rb +2 -2
- data/lib/syntax_tree/parser.rb +59 -13
- data/lib/syntax_tree/rake/check_task.rb +10 -1
- data/lib/syntax_tree/rake/write_task.rb +10 -1
- data/lib/syntax_tree/version.rb +1 -1
- data/lib/syntax_tree.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 52707e3169fedfce017259222e4740b2e1032d210dfb628d454134eef578a7b6
|
|
4
|
+
data.tar.gz: aed3d5b3e6de7ed1e156c5b104007db6a01dab65e0ee80913afa2c1b5c63a5c0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b81b4753a5e765712bd31081dedca6e50c67d04a7935a717fc56d278424154e6ed95b648ac1cbdd59b500ee44c2d8d89f57f52e3851f9615e378d8c9c2c6abe1
|
|
7
|
+
data.tar.gz: 32c95446f19190b8e73d9c3ce83ff4bd5573f5787f844cf695551a2d32c0c159af8c514714c4648a99be4e66189910bde7f01557ea973f6e17aaba66ace7fce2
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,32 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [3.4.0] - 2022-08-19
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- [#127](https://github.com/ruby-syntax-tree/syntax_tree/pull/127) - Allow the language server to handle other file extensions if it is activated for those extensions.
|
|
14
|
+
- [#133](https://github.com/ruby-syntax-tree/syntax_tree/pull/133) - Add documentation on supporting vim and neovim.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- [#132](https://github.com/ruby-syntax-tree/syntax_tree/pull/132) - Provide better error messages when end quotes and end keywords are missing from tokens.
|
|
19
|
+
- [#134](https://github.com/ruby-syntax-tree/syntax_tree/pull/134) - Ensure the correct `end` keyword is getting removed by `begin..rescue` clauses.
|
|
20
|
+
- [#137](https://github.com/ruby-syntax-tree/syntax_tree/pull/137) - Better support regular expressions with no ending token.
|
|
21
|
+
|
|
22
|
+
## [3.3.0] - 2022-08-02
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- [#123](https://github.com/ruby-syntax-tree/syntax_tree/pull/123) - Allow the rake tasks to configure print width.
|
|
27
|
+
- [#125](https://github.com/ruby-syntax-tree/syntax_tree/pull/125) - Add support for an `.streerc` file in the current working directory to configure the CLI.
|
|
28
|
+
|
|
29
|
+
## [3.2.1] - 2022-07-22
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- [#119](https://github.com/ruby-syntax-tree/syntax_tree/pull/119) - If there are conditionals in the assignment we cannot convert it to the modifier form. There was a bug where it would stop checking for assignment nodes if there were any optional child nodes.
|
|
34
|
+
|
|
9
35
|
## [3.2.0] - 2022-07-19
|
|
10
36
|
|
|
11
37
|
### Added
|
|
@@ -306,7 +332,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
|
306
332
|
|
|
307
333
|
- 🎉 Initial release! 🎉
|
|
308
334
|
|
|
309
|
-
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.
|
|
335
|
+
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.4.0...HEAD
|
|
336
|
+
[3.4.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.3.0...v3.4.0
|
|
337
|
+
[3.3.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.2.1...v3.3.0
|
|
338
|
+
[3.2.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.2.0...v3.2.1
|
|
310
339
|
[3.2.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.1.0...v3.2.0
|
|
311
340
|
[3.1.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.0.1...v3.1.0
|
|
312
341
|
[3.0.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v3.0.0...v3.0.1
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
syntax_tree (3.
|
|
4
|
+
syntax_tree (3.4.0)
|
|
5
5
|
prettier_print
|
|
6
6
|
|
|
7
7
|
GEM
|
|
@@ -12,24 +12,24 @@ GEM
|
|
|
12
12
|
json (2.6.2)
|
|
13
13
|
minitest (5.16.2)
|
|
14
14
|
parallel (1.22.1)
|
|
15
|
-
parser (3.1.2.
|
|
15
|
+
parser (3.1.2.1)
|
|
16
16
|
ast (~> 2.4.1)
|
|
17
17
|
prettier_print (0.1.0)
|
|
18
18
|
rainbow (3.1.1)
|
|
19
19
|
rake (13.0.6)
|
|
20
20
|
regexp_parser (2.5.0)
|
|
21
21
|
rexml (3.2.5)
|
|
22
|
-
rubocop (1.
|
|
22
|
+
rubocop (1.35.0)
|
|
23
23
|
json (~> 2.3)
|
|
24
24
|
parallel (~> 1.10)
|
|
25
|
-
parser (>= 3.1.
|
|
25
|
+
parser (>= 3.1.2.1)
|
|
26
26
|
rainbow (>= 2.2.2, < 4.0)
|
|
27
27
|
regexp_parser (>= 1.8, < 3.0)
|
|
28
28
|
rexml (>= 3.2.5, < 4.0)
|
|
29
|
-
rubocop-ast (>= 1.
|
|
29
|
+
rubocop-ast (>= 1.20.1, < 2.0)
|
|
30
30
|
ruby-progressbar (~> 1.7)
|
|
31
31
|
unicode-display_width (>= 1.4.0, < 3.0)
|
|
32
|
-
rubocop-ast (1.
|
|
32
|
+
rubocop-ast (1.21.0)
|
|
33
33
|
parser (>= 3.1.1.0)
|
|
34
34
|
ruby-progressbar (1.11.0)
|
|
35
35
|
simplecov (0.21.2)
|
data/README.md
CHANGED
|
@@ -19,6 +19,8 @@ It is built with only standard library dependencies. It additionally ships with
|
|
|
19
19
|
- [json](#json)
|
|
20
20
|
- [match](#match)
|
|
21
21
|
- [write](#write)
|
|
22
|
+
- [Configuration](#configuration)
|
|
23
|
+
- [Globbing](#globbing)
|
|
22
24
|
- [Library](#library)
|
|
23
25
|
- [SyntaxTree.read(filepath)](#syntaxtreereadfilepath)
|
|
24
26
|
- [SyntaxTree.parse(source)](#syntaxtreeparsesource)
|
|
@@ -43,7 +45,7 @@ It is built with only standard library dependencies. It additionally ships with
|
|
|
43
45
|
- [Integration](#integration)
|
|
44
46
|
- [Rake](#rake)
|
|
45
47
|
- [RuboCop](#rubocop)
|
|
46
|
-
- [
|
|
48
|
+
- [Editors](#editors)
|
|
47
49
|
- [Contributing](#contributing)
|
|
48
50
|
- [License](#license)
|
|
49
51
|
|
|
@@ -231,6 +233,37 @@ To change the print width that you are writing with, specify the `--print-width`
|
|
|
231
233
|
stree write --print-width=100 path/to/file.rb
|
|
232
234
|
```
|
|
233
235
|
|
|
236
|
+
### Configuration
|
|
237
|
+
|
|
238
|
+
Any of the above CLI commands can also read configuration options from a `.streerc` file in the directory where the commands are executed.
|
|
239
|
+
|
|
240
|
+
This should be a text file with each argument on a separate line.
|
|
241
|
+
|
|
242
|
+
```txt
|
|
243
|
+
--print-width=100
|
|
244
|
+
--plugins=plugin/trailing_comma
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
If this file is present, it will _always_ be used for CLI commands. You can also pass options from the command line as in the examples above. The options in the `.streerc` file are passed to the CLI first, then the arguments from the command line. In the case of exclusive options (e.g. `--print-width`), this means that the command line options override what's in the config file. In the case of options that can take multiple inputs (e.g. `--plugins`), the effect is additive. That is, the plugins passed from the command line will be loaded _in addition to_ the plugins in the config file.
|
|
248
|
+
|
|
249
|
+
### Globbing
|
|
250
|
+
|
|
251
|
+
When running commands with `stree`, it's common to pass in lists of files. For example:
|
|
252
|
+
|
|
253
|
+
```sh
|
|
254
|
+
stree write 'lib/*.rb' 'test/*.rb'
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
The commands in the CLI accept any number of arguments. This means you _could_ pass `**/*.rb` (note the lack of quotes). This would make your shell expand out the file paths listed according to its own rules. (For example, [here](https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html) are the rules for GNU bash.)
|
|
258
|
+
|
|
259
|
+
However, it's recommended to instead use quotes, which means that Ruby is responsible for performing the file path expansion instead. This ensures a consistent experience across different environments and shells. The globs must follow the Ruby-specific globbing syntax as specified in the documentation for [Dir](https://ruby-doc.org/core-3.1.1/Dir.html#method-c-glob).
|
|
260
|
+
|
|
261
|
+
Baked into this syntax is the ability to provide exceptions to file name patterns as well. For example, if you are in a Rails app and want to exclude files named `schema.rb` but write all other Ruby files, you can use the following syntax:
|
|
262
|
+
|
|
263
|
+
```shell
|
|
264
|
+
stree write "**/{[!schema]*,*}.rb"
|
|
265
|
+
```
|
|
266
|
+
|
|
234
267
|
## Library
|
|
235
268
|
|
|
236
269
|
Syntax Tree can be used as a library to access the syntax tree underlying Ruby source code.
|
|
@@ -505,6 +538,16 @@ SyntaxTree::Rake::WriteTask.new do |t|
|
|
|
505
538
|
end
|
|
506
539
|
```
|
|
507
540
|
|
|
541
|
+
#### `print_width`
|
|
542
|
+
|
|
543
|
+
If you want to use a different print width from the default (80), you can pass that to the `print_width` field, as in:
|
|
544
|
+
|
|
545
|
+
```ruby
|
|
546
|
+
SyntaxTree::Rake::WriteTask.new do |t|
|
|
547
|
+
t.print_width = 100
|
|
548
|
+
end
|
|
549
|
+
```
|
|
550
|
+
|
|
508
551
|
#### `plugins`
|
|
509
552
|
|
|
510
553
|
If you're running Syntax Tree with plugins (either your own or the pre-built ones), you can pass that to the `plugins` field, as in:
|
|
@@ -524,9 +567,11 @@ inherit_gem:
|
|
|
524
567
|
syntax_tree: config/rubocop.yml
|
|
525
568
|
```
|
|
526
569
|
|
|
527
|
-
###
|
|
570
|
+
### Editors
|
|
528
571
|
|
|
529
|
-
|
|
572
|
+
* [Neovim](https://neovim.io/) - [neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig).
|
|
573
|
+
* [Vim](https://www.vim.org/) - [dense-analysis/ale](https://github.com/dense-analysis/ale).
|
|
574
|
+
* [VSCode](https://code.visualstudio.com/) - [ruby-syntax-tree/vscode-syntax-tree](https://github.com/ruby-syntax-tree/vscode-syntax-tree).
|
|
530
575
|
|
|
531
576
|
## Contributing
|
|
532
577
|
|
data/lib/syntax_tree/cli.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "optparse"
|
|
4
|
+
|
|
3
5
|
module SyntaxTree
|
|
4
6
|
# Syntax Tree ships with the `stree` CLI, which can be used to inspect and
|
|
5
7
|
# manipulate Ruby code. This module is responsible for powering that CLI.
|
|
@@ -68,6 +70,12 @@ module SyntaxTree
|
|
|
68
70
|
|
|
69
71
|
# The parent action class for the CLI that implements the basics.
|
|
70
72
|
class Action
|
|
73
|
+
attr_reader :options
|
|
74
|
+
|
|
75
|
+
def initialize(options)
|
|
76
|
+
@options = options
|
|
77
|
+
end
|
|
78
|
+
|
|
71
79
|
def run(item)
|
|
72
80
|
end
|
|
73
81
|
|
|
@@ -91,15 +99,9 @@ module SyntaxTree
|
|
|
91
99
|
class UnformattedError < StandardError
|
|
92
100
|
end
|
|
93
101
|
|
|
94
|
-
attr_reader :print_width
|
|
95
|
-
|
|
96
|
-
def initialize(print_width:)
|
|
97
|
-
@print_width = print_width
|
|
98
|
-
end
|
|
99
|
-
|
|
100
102
|
def run(item)
|
|
101
103
|
source = item.source
|
|
102
|
-
if source != item.handler.format(source, print_width)
|
|
104
|
+
if source != item.handler.format(source, options.print_width)
|
|
103
105
|
raise UnformattedError
|
|
104
106
|
end
|
|
105
107
|
rescue StandardError
|
|
@@ -122,19 +124,13 @@ module SyntaxTree
|
|
|
122
124
|
class NonIdempotentFormatError < StandardError
|
|
123
125
|
end
|
|
124
126
|
|
|
125
|
-
attr_reader :print_width
|
|
126
|
-
|
|
127
|
-
def initialize(print_width:)
|
|
128
|
-
@print_width = print_width
|
|
129
|
-
end
|
|
130
|
-
|
|
131
127
|
def run(item)
|
|
132
128
|
handler = item.handler
|
|
133
129
|
|
|
134
130
|
warning = "[#{Color.yellow("warn")}] #{item.filepath}"
|
|
135
|
-
formatted = handler.format(item.source, print_width)
|
|
131
|
+
formatted = handler.format(item.source, options.print_width)
|
|
136
132
|
|
|
137
|
-
if formatted != handler.format(formatted, print_width)
|
|
133
|
+
if formatted != handler.format(formatted, options.print_width)
|
|
138
134
|
raise NonIdempotentFormatError
|
|
139
135
|
end
|
|
140
136
|
rescue StandardError
|
|
@@ -164,14 +160,8 @@ module SyntaxTree
|
|
|
164
160
|
|
|
165
161
|
# An action of the CLI that formats the input source and prints it out.
|
|
166
162
|
class Format < Action
|
|
167
|
-
attr_reader :print_width
|
|
168
|
-
|
|
169
|
-
def initialize(print_width:)
|
|
170
|
-
@print_width = print_width
|
|
171
|
-
end
|
|
172
|
-
|
|
173
163
|
def run(item)
|
|
174
|
-
puts item.handler.format(item.source, print_width)
|
|
164
|
+
puts item.handler.format(item.source, options.print_width)
|
|
175
165
|
end
|
|
176
166
|
end
|
|
177
167
|
|
|
@@ -195,18 +185,12 @@ module SyntaxTree
|
|
|
195
185
|
# An action of the CLI that formats the input source and writes the
|
|
196
186
|
# formatted output back to the file.
|
|
197
187
|
class Write < Action
|
|
198
|
-
attr_reader :print_width
|
|
199
|
-
|
|
200
|
-
def initialize(print_width:)
|
|
201
|
-
@print_width = print_width
|
|
202
|
-
end
|
|
203
|
-
|
|
204
188
|
def run(item)
|
|
205
189
|
filepath = item.filepath
|
|
206
190
|
start = Time.now
|
|
207
191
|
|
|
208
192
|
source = item.source
|
|
209
|
-
formatted = item.handler.format(source, print_width)
|
|
193
|
+
formatted = item.handler.format(source, options.print_width)
|
|
210
194
|
File.write(filepath, formatted) if filepath != :stdin
|
|
211
195
|
|
|
212
196
|
color = source == formatted ? Color.gray(filepath) : filepath
|
|
@@ -262,69 +246,114 @@ module SyntaxTree
|
|
|
262
246
|
The maximum line width to use when formatting.
|
|
263
247
|
HELP
|
|
264
248
|
|
|
249
|
+
# This represents all of the options that can be passed to the CLI. It is
|
|
250
|
+
# responsible for parsing the list and then returning the file paths at the
|
|
251
|
+
# end.
|
|
252
|
+
class Options
|
|
253
|
+
attr_reader :print_width
|
|
254
|
+
|
|
255
|
+
def initialize(print_width: DEFAULT_PRINT_WIDTH)
|
|
256
|
+
@print_width = print_width
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def parse(arguments)
|
|
260
|
+
parser.parse(arguments)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
private
|
|
264
|
+
|
|
265
|
+
def parser
|
|
266
|
+
OptionParser.new do |opts|
|
|
267
|
+
# If there are any plugins specified on the command line, then load
|
|
268
|
+
# them by requiring them here. We do this by transforming something
|
|
269
|
+
# like
|
|
270
|
+
#
|
|
271
|
+
# stree format --plugins=haml template.haml
|
|
272
|
+
#
|
|
273
|
+
# into
|
|
274
|
+
#
|
|
275
|
+
# require "syntax_tree/haml"
|
|
276
|
+
#
|
|
277
|
+
opts.on("--plugins=PLUGINS") do |plugins|
|
|
278
|
+
plugins.split(",").each { |plugin| require "syntax_tree/#{plugin}" }
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# If there is a print width specified on the command line, then
|
|
282
|
+
# parse that out here and use it when formatting.
|
|
283
|
+
opts.on("--print-width=NUMBER", Integer) do |print_width|
|
|
284
|
+
@print_width = print_width
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# We allow a minimal configuration file to act as additional command line
|
|
291
|
+
# arguments to the CLI. Each line of the config file should be a new
|
|
292
|
+
# argument, as in:
|
|
293
|
+
#
|
|
294
|
+
# --plugins=plugin/single_quote
|
|
295
|
+
# --print-width=100
|
|
296
|
+
#
|
|
297
|
+
# When invoking the CLI, we will read this config file and then parse it if
|
|
298
|
+
# it exists in the current working directory.
|
|
299
|
+
class ConfigFile
|
|
300
|
+
FILENAME = ".streerc"
|
|
301
|
+
|
|
302
|
+
attr_reader :filepath
|
|
303
|
+
|
|
304
|
+
def initialize
|
|
305
|
+
@filepath = File.join(Dir.pwd, FILENAME)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def exists?
|
|
309
|
+
File.readable?(filepath)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def arguments
|
|
313
|
+
exists? ? File.readlines(filepath, chomp: true) : []
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
265
317
|
class << self
|
|
266
318
|
# Run the CLI over the given array of strings that make up the arguments
|
|
267
319
|
# passed to the invocation.
|
|
268
320
|
def run(argv)
|
|
269
321
|
name, *arguments = argv
|
|
270
|
-
print_width = DEFAULT_PRINT_WIDTH
|
|
271
|
-
|
|
272
|
-
while arguments.first&.start_with?("--")
|
|
273
|
-
case (argument = arguments.shift)
|
|
274
|
-
when /^--plugins=(.+)$/
|
|
275
|
-
# If there are any plugins specified on the command line, then load
|
|
276
|
-
# them by requiring them here. We do this by transforming something
|
|
277
|
-
# like
|
|
278
|
-
#
|
|
279
|
-
# stree format --plugins=haml template.haml
|
|
280
|
-
#
|
|
281
|
-
# into
|
|
282
|
-
#
|
|
283
|
-
# require "syntax_tree/haml"
|
|
284
|
-
#
|
|
285
|
-
$1.split(",").each { |plugin| require "syntax_tree/#{plugin}" }
|
|
286
|
-
when /^--print-width=(\d+)$/
|
|
287
|
-
# If there is a print width specified on the command line, then
|
|
288
|
-
# parse that out here and use it when formatting.
|
|
289
|
-
print_width = Integer($1)
|
|
290
|
-
else
|
|
291
|
-
warn("Unknown CLI option: #{argument}")
|
|
292
|
-
warn(HELP)
|
|
293
|
-
return 1
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
322
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
require "syntax_tree/language_server"
|
|
303
|
-
LanguageServer.new(print_width: print_width).run
|
|
304
|
-
return 0
|
|
305
|
-
when "version"
|
|
306
|
-
puts SyntaxTree::VERSION
|
|
307
|
-
return 0
|
|
308
|
-
end
|
|
323
|
+
config_file = ConfigFile.new
|
|
324
|
+
arguments.unshift(*config_file.arguments)
|
|
325
|
+
|
|
326
|
+
options = Options.new
|
|
327
|
+
options.parse(arguments)
|
|
309
328
|
|
|
310
329
|
action =
|
|
311
330
|
case name
|
|
312
331
|
when "a", "ast"
|
|
313
|
-
AST.new
|
|
332
|
+
AST.new(options)
|
|
314
333
|
when "c", "check"
|
|
315
|
-
Check.new(
|
|
334
|
+
Check.new(options)
|
|
316
335
|
when "debug"
|
|
317
|
-
Debug.new(
|
|
336
|
+
Debug.new(options)
|
|
318
337
|
when "doc"
|
|
319
|
-
Doc.new
|
|
338
|
+
Doc.new(options)
|
|
339
|
+
when "help"
|
|
340
|
+
puts HELP
|
|
341
|
+
return 0
|
|
320
342
|
when "j", "json"
|
|
321
|
-
Json.new
|
|
343
|
+
Json.new(options)
|
|
344
|
+
when "lsp"
|
|
345
|
+
require "syntax_tree/language_server"
|
|
346
|
+
LanguageServer.new(print_width: options.print_width).run
|
|
347
|
+
return 0
|
|
322
348
|
when "m", "match"
|
|
323
|
-
Match.new
|
|
349
|
+
Match.new(options)
|
|
324
350
|
when "f", "format"
|
|
325
|
-
Format.new(
|
|
351
|
+
Format.new(options)
|
|
352
|
+
when "version"
|
|
353
|
+
puts SyntaxTree::VERSION
|
|
354
|
+
return 0
|
|
326
355
|
when "w", "write"
|
|
327
|
-
Write.new(
|
|
356
|
+
Write.new(options)
|
|
328
357
|
else
|
|
329
358
|
warn(HELP)
|
|
330
359
|
return 1
|
|
@@ -56,7 +56,7 @@ module SyntaxTree
|
|
|
56
56
|
store.delete(uri)
|
|
57
57
|
in { method: "textDocument/formatting", id:, params: { textDocument: { uri: } } }
|
|
58
58
|
contents = store[uri]
|
|
59
|
-
write(id: id, result: contents ? [format(store[uri])] : nil)
|
|
59
|
+
write(id: id, result: contents ? [format(store[uri], uri.split(".").last)] : nil)
|
|
60
60
|
in { method: "textDocument/inlayHint", id:, params: { textDocument: { uri: } } }
|
|
61
61
|
contents = store[uri]
|
|
62
62
|
write(id: id, result: contents ? inlay_hints(store[uri]) : nil)
|
|
@@ -86,7 +86,9 @@ module SyntaxTree
|
|
|
86
86
|
}
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
def format(source)
|
|
89
|
+
def format(source, extension)
|
|
90
|
+
text = SyntaxTree::HANDLERS[".#{extension}"].format(source, print_width)
|
|
91
|
+
|
|
90
92
|
{
|
|
91
93
|
range: {
|
|
92
94
|
start: {
|
|
@@ -98,7 +100,7 @@ module SyntaxTree
|
|
|
98
100
|
character: 0
|
|
99
101
|
}
|
|
100
102
|
},
|
|
101
|
-
newText:
|
|
103
|
+
newText: text
|
|
102
104
|
}
|
|
103
105
|
end
|
|
104
106
|
|
|
@@ -117,5 +119,9 @@ module SyntaxTree
|
|
|
117
119
|
output.print("Content-Length: #{response.bytesize}\r\n\r\n#{response}")
|
|
118
120
|
output.flush
|
|
119
121
|
end
|
|
122
|
+
|
|
123
|
+
def log(message)
|
|
124
|
+
write(method: "window/logMessage", params: { type: 4, message: message })
|
|
125
|
+
end
|
|
120
126
|
end
|
|
121
127
|
end
|
data/lib/syntax_tree/node.rb
CHANGED
|
@@ -1978,7 +1978,7 @@ module SyntaxTree
|
|
|
1978
1978
|
# If we hit a statements, then we're safe to use whatever since we
|
|
1979
1979
|
# know for certain we're going to get split over multiple lines
|
|
1980
1980
|
# anyway.
|
|
1981
|
-
break false if parent.is_a?(Statements)
|
|
1981
|
+
break false if parent.is_a?(Statements) || parent.is_a?(ArgParen)
|
|
1982
1982
|
|
|
1983
1983
|
[Command, CommandCall].include?(parent.class)
|
|
1984
1984
|
end
|
|
@@ -5173,7 +5173,7 @@ module SyntaxTree
|
|
|
5173
5173
|
|
|
5174
5174
|
while (node = queue.shift)
|
|
5175
5175
|
return true if [Assign, MAssign, OpAssign].include?(node.class)
|
|
5176
|
-
queue += node.child_nodes
|
|
5176
|
+
queue += node.child_nodes.compact
|
|
5177
5177
|
end
|
|
5178
5178
|
|
|
5179
5179
|
false
|
data/lib/syntax_tree/parser.rb
CHANGED
|
@@ -57,6 +57,26 @@ module SyntaxTree
|
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
# This represents all of the tokens coming back from the lexer. It is
|
|
61
|
+
# replacing a simple array because it keeps track of the last deleted token
|
|
62
|
+
# from the list for better error messages.
|
|
63
|
+
class TokenList < SimpleDelegator
|
|
64
|
+
attr_reader :last_deleted
|
|
65
|
+
|
|
66
|
+
def initialize(object)
|
|
67
|
+
super
|
|
68
|
+
@last_deleted = nil
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def delete(value)
|
|
72
|
+
@last_deleted = super || @last_deleted
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def delete_at(index)
|
|
76
|
+
@last_deleted = super
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
60
80
|
# [String] the source being parsed
|
|
61
81
|
attr_reader :source
|
|
62
82
|
|
|
@@ -124,7 +144,7 @@ module SyntaxTree
|
|
|
124
144
|
# Most of the time, when a parser event consumes one of these events, it
|
|
125
145
|
# will be deleted from the list. So ideally, this list stays pretty short
|
|
126
146
|
# over the course of parsing a source string.
|
|
127
|
-
@tokens = []
|
|
147
|
+
@tokens = TokenList.new([])
|
|
128
148
|
|
|
129
149
|
# Here we're going to build up a list of SingleByteString or
|
|
130
150
|
# MultiByteString objects. They're each going to represent a string in the
|
|
@@ -174,6 +194,33 @@ module SyntaxTree
|
|
|
174
194
|
line[column].to_i - line.start
|
|
175
195
|
end
|
|
176
196
|
|
|
197
|
+
# Returns the current location that is being looked at for the parser for
|
|
198
|
+
# the purpose of locating the error.
|
|
199
|
+
def find_token_error(location)
|
|
200
|
+
if location
|
|
201
|
+
# If we explicitly passed a location into this find_token_error method,
|
|
202
|
+
# that means that's the source of the error, so we'll use that
|
|
203
|
+
# information for our error object.
|
|
204
|
+
lineno = location.start_line
|
|
205
|
+
[lineno, location.start_char - line_counts[lineno - 1].start]
|
|
206
|
+
elsif lineno && column
|
|
207
|
+
# If there is a line number associated with the current ripper state,
|
|
208
|
+
# then we'll use that information to generate the error.
|
|
209
|
+
[lineno, column]
|
|
210
|
+
elsif (location = tokens.last_deleted&.location)
|
|
211
|
+
# If we've already deleted a token from the list of tokens that we are
|
|
212
|
+
# consuming, then we'll fall back to that token's location.
|
|
213
|
+
lineno = location.start_line
|
|
214
|
+
[lineno, location.start_char - line_counts[lineno - 1].start]
|
|
215
|
+
else
|
|
216
|
+
# Finally, it's possible that when we hit this error the parsing thread
|
|
217
|
+
# for ripper has died. In that case, lineno and column both return nil.
|
|
218
|
+
# So we're just going to set it to line 1, column 0 in the hopes that
|
|
219
|
+
# that makes any sense.
|
|
220
|
+
[1, 0]
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
177
224
|
# As we build up a list of tokens, we'll periodically need to go backwards
|
|
178
225
|
# and find the ones that we've already hit in order to determine the
|
|
179
226
|
# location information for nodes that use them. For example, if you have a
|
|
@@ -201,14 +248,7 @@ module SyntaxTree
|
|
|
201
248
|
unless index
|
|
202
249
|
token = value == :any ? type.name.split("::", 2).last : value
|
|
203
250
|
message = "Cannot find expected #{token}"
|
|
204
|
-
|
|
205
|
-
if location
|
|
206
|
-
lineno = location.start_line
|
|
207
|
-
column = location.start_char - line_counts[lineno - 1].start
|
|
208
|
-
raise ParseError.new(message, lineno, column)
|
|
209
|
-
else
|
|
210
|
-
raise ParseError.new(message, lineno, column)
|
|
211
|
-
end
|
|
251
|
+
raise ParseError.new(message, *find_token_error(location))
|
|
212
252
|
end
|
|
213
253
|
|
|
214
254
|
tokens.delete_at(index)
|
|
@@ -677,8 +717,7 @@ module SyntaxTree
|
|
|
677
717
|
else
|
|
678
718
|
keyword = find_token(Kw, "begin")
|
|
679
719
|
end_location =
|
|
680
|
-
if bodystmt.
|
|
681
|
-
bodystmt.else_clause
|
|
720
|
+
if bodystmt.else_clause
|
|
682
721
|
bodystmt.location
|
|
683
722
|
else
|
|
684
723
|
find_token(Kw, "end").location
|
|
@@ -2798,14 +2837,21 @@ module SyntaxTree
|
|
|
2798
2837
|
# :call-seq:
|
|
2799
2838
|
# on_regexp_literal: (
|
|
2800
2839
|
# RegexpContent regexp_content,
|
|
2801
|
-
# RegexpEnd ending
|
|
2840
|
+
# (nil | RegexpEnd) ending
|
|
2802
2841
|
# ) -> RegexpLiteral
|
|
2803
2842
|
def on_regexp_literal(regexp_content, ending)
|
|
2843
|
+
location = regexp_content.location
|
|
2844
|
+
|
|
2845
|
+
if ending.nil?
|
|
2846
|
+
message = "Cannot find expected regular expression ending"
|
|
2847
|
+
raise ParseError.new(message, *find_token_error(location))
|
|
2848
|
+
end
|
|
2849
|
+
|
|
2804
2850
|
RegexpLiteral.new(
|
|
2805
2851
|
beginning: regexp_content.beginning,
|
|
2806
2852
|
ending: ending.value,
|
|
2807
2853
|
parts: regexp_content.parts,
|
|
2808
|
-
location:
|
|
2854
|
+
location: location.to(ending.location)
|
|
2809
2855
|
)
|
|
2810
2856
|
end
|
|
2811
2857
|
|
|
@@ -35,14 +35,20 @@ module SyntaxTree
|
|
|
35
35
|
# Defaults to [].
|
|
36
36
|
attr_accessor :plugins
|
|
37
37
|
|
|
38
|
+
# Max line length.
|
|
39
|
+
# Defaults to 80.
|
|
40
|
+
attr_accessor :print_width
|
|
41
|
+
|
|
38
42
|
def initialize(
|
|
39
43
|
name = :"stree:check",
|
|
40
44
|
source_files = ::Rake::FileList["lib/**/*.rb"],
|
|
41
|
-
plugins = []
|
|
45
|
+
plugins = [],
|
|
46
|
+
print_width = DEFAULT_PRINT_WIDTH
|
|
42
47
|
)
|
|
43
48
|
@name = name
|
|
44
49
|
@source_files = source_files
|
|
45
50
|
@plugins = plugins
|
|
51
|
+
@print_width = print_width
|
|
46
52
|
|
|
47
53
|
yield self if block_given?
|
|
48
54
|
define_task
|
|
@@ -58,6 +64,9 @@ module SyntaxTree
|
|
|
58
64
|
def run_task
|
|
59
65
|
arguments = ["check"]
|
|
60
66
|
arguments << "--plugins=#{plugins.join(",")}" if plugins.any?
|
|
67
|
+
if print_width != DEFAULT_PRINT_WIDTH
|
|
68
|
+
arguments << "--print-width=#{print_width}"
|
|
69
|
+
end
|
|
61
70
|
|
|
62
71
|
SyntaxTree::CLI.run(arguments + Array(source_files))
|
|
63
72
|
end
|
|
@@ -35,14 +35,20 @@ module SyntaxTree
|
|
|
35
35
|
# Defaults to [].
|
|
36
36
|
attr_accessor :plugins
|
|
37
37
|
|
|
38
|
+
# Max line length.
|
|
39
|
+
# Defaults to 80.
|
|
40
|
+
attr_accessor :print_width
|
|
41
|
+
|
|
38
42
|
def initialize(
|
|
39
43
|
name = :"stree:write",
|
|
40
44
|
source_files = ::Rake::FileList["lib/**/*.rb"],
|
|
41
|
-
plugins = []
|
|
45
|
+
plugins = [],
|
|
46
|
+
print_width = DEFAULT_PRINT_WIDTH
|
|
42
47
|
)
|
|
43
48
|
@name = name
|
|
44
49
|
@source_files = source_files
|
|
45
50
|
@plugins = plugins
|
|
51
|
+
@print_width = print_width
|
|
46
52
|
|
|
47
53
|
yield self if block_given?
|
|
48
54
|
define_task
|
|
@@ -58,6 +64,9 @@ module SyntaxTree
|
|
|
58
64
|
def run_task
|
|
59
65
|
arguments = ["write"]
|
|
60
66
|
arguments << "--plugins=#{plugins.join(",")}" if plugins.any?
|
|
67
|
+
if print_width != DEFAULT_PRINT_WIDTH
|
|
68
|
+
arguments << "--print-width=#{print_width}"
|
|
69
|
+
end
|
|
61
70
|
|
|
62
71
|
SyntaxTree::CLI.run(arguments + Array(source_files))
|
|
63
72
|
end
|
data/lib/syntax_tree/version.rb
CHANGED
data/lib/syntax_tree.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: syntax_tree
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kevin Newton
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-08-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: prettier_print
|