ruby-syntax-tree / syntax_tree Goto Github PK
View Code? Open in Web Editor NEWInteract with the Ruby syntax tree
Home Page: https://ruby-syntax-tree.github.io/syntax_tree/
License: MIT License
Interact with the Ruby syntax tree
Home Page: https://ruby-syntax-tree.github.io/syntax_tree/
License: MIT License
Please can you tell me how I can integrate in my neovim workflow, or if exit some plugin that use this gem.
Thank
Reproduction steps:
git clone https://github.com/discourse/discourse-chat.git
cd discourse-chat
bundle install
bundle exec stree check --plugins=plugin/single_quotes db/migrate/*.rb
We are evaluating adoption syntax_tree in discourse and wanted to start with this plugin so we can get CI and bugs ironed out.
It works fine on 2.7.1 but fails on 2.8.0 so I suspect it's the parallel code.
While I love that there are very few configuration options, since there are some, what do you think about having the CLI read a configuration file in addition to the arguments that are passed in?
In most cases, it's not too much effort to make sure you're passing in the options you want (and I particularly like the ability to dynamically define rake tasks with the options already specified!), but that becomes a bit unwieldy with multiple projects that use different options. E.g., the VS Code extension lets you specify those options, but they're applied globally. Switching projects means I need to remember to update my editor to match the options for syntax_tree. Having a per-project config file would let that (and other) editor integrations "do the right thing" in each repo.
If you're open to it, I'd be happy to make a pass at implementing the necessary changes.
See prettier/plugin-ruby#1264 for details.
For inspiration, check out: https://github.com/prettier/plugin-ruby/blob/main/lib/prettier/rake/task.rb.
Running syntax tree on this code crashes it
LongRecordName.transaction do
LongRecordName
.joins(:other_record)
# rubocop:disable Rails/SkipsModelValidations
.update_all(foo: 'bar')
end
[warn] foo.rb
Error: Cannot find expected end
#<Thread:0x0000000108fc4898 /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:382 run> terminated with exception (report_on_exception is true):
/Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:426:in `highlight_error': undefined method `+' for nil:NilClass (NoMethodError)
maximum = [error.lineno + 3, lines.length].min
^
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:401:in `rescue in block (2 levels) in process_queue'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:396:in `block (2 levels) in process_queue'
/Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/parser.rb:210:in `find_token': Cannot find expected end (SyntaxTree::Parser::ParseError)
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/parser.rb:1198:in `on_do_block'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree.rb:46:in `parse'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree.rb:46:in `parse'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree.rb:53:in `format'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:104:in `run'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:397:in `block (2 levels) in process_queue'
/Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:426:in `highlight_error': undefined method `+' for nil:NilClass (NoMethodError)
maximum = [error.lineno + 3, lines.length].min
^
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:401:in `rescue in block (2 levels) in process_queue'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:396:in `block (2 levels) in process_queue'
/Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/parser.rb:210:in `find_token': Cannot find expected end (SyntaxTree::Parser::ParseError)
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/parser.rb:1198:in `on_do_block'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree.rb:46:in `parse'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree.rb:46:in `parse'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree.rb:53:in `format'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:104:in `run'
from /Users/devon/.gem/ruby/3.1.2/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:397:in `block (2 levels) in process_queue'
Shows syntax error, but no stack trace
Try formatting this code:
def foo(bar)
Foo
.where(
id: bar
)
# The second condition helps to skip the newly create runtime stated as "initialized"
# The first condition helps to skip the soft deleted runtime marked as "remote_deleted"
# that hasn't been appeared in ProdRegistry
.where(<<-SQL)
(foo)
SQL
end
def foo(bar)
Foo.where(
id: bar
)# The second condition helps to skip the newly create runtime stated as "initialized"
# The first condition helps to skip the soft deleted runtime marked as "remote_deleted"
# that hasn't been appeared in ProdRegistry
.
where(<<-SQL)
(foo)
SQL
end
def foo(bar)
Foo.where(
id: bar
)# The first condition helps to skip the soft deleted runtime marked as "remote_deleted" # The second condition helps to skip the newly create runtime stated as "initialized"
# that hasn't been appeared in ProdRegistry
.
where(<<-SQL)
(foo)
SQL
end
def foo(bar)
Foo.where(id: bar)# that hasn't been appeared in ProdRegistry # The first condition helps to skip the soft deleted runtime marked as "remote_deleted" # The second condition helps to skip the newly create runtime stated as "initialized"
.
where(<<-SQL)
(foo)
SQL
end
def foo(bar)
Foo.where(id: bar) # that hasn't been appeared in ProdRegistry # The first condition helps to skip the soft deleted runtime marked as "remote_deleted" # The second condition helps to skip the newly create runtime stated as "initialized"
.where(<<-SQL)
(foo)
SQL
end
At the time that I wrote the inlay hints stuff for the language server, inlay hints were not actually a part of the LSP. Since then, they have been added. If we conform to the spec, we can greatly simplify vscode-syntax-tree because it won't have to handle deduping itself and can just let the client handle it. Additionally, it will work for clients that aren't vscode.
Any plans for allowing some level of configuration?
I'm trying to integrate it into erb-formatter, and would really like to be able to configure staff like the max line width, or quotes, and so on.
OT: eventually I'd like to try writing a syntax tree plugin for ERB, but for now I'd like to be able to just use it for formatting bits of ruby code inside ERB files.
We are evaluating this on discourse/discourse and all our plugins.
Things are looking good, but this jumped to me as weird:
Is this because of line width? I see ternaries being removed in many places because of, I assume, line width. Can we get a cli option for line width? We have no immediate interest in forking nor using syntax_tree as a lib at the moment, so that would be great to help adoption.
In case that some control structure statement chain methods, the indentations are not aligned.
ok:
if condition
#...
value1
else
#...
value2
end.method1 do |this|
#...
end.method2
ng:
if condition
#...
value1
else # <- x
#...
value2
end.method1 # <- x
.method2ใ # <- cause by the beginning of the line is a dot
.method3 do
#...
end
.method4
Originally from prettier/plugin-ruby#1211.
I was rather surprised to see Syntax Tree make the following choice:
expect(
resulting_items.map { |i|
{ amount: i.amount }
},
).to match(
existing_model.fund.ownership_positions.current.map { |i|
{ amount: Float(i.id) }
},
)
It was preserving my choice of {}
but when it reflowed the block to multiple lines, our convention normally would have been to switch to a do/end
pair (and vice-versa).
As a workaround, I can Rubocop to auto-fix after formatting; it's a minor pain however. Is this a behavior that would be amenable to a Syntax Tree plugin? If so, perhaps I can work on contributing one to the core.
Original code
class Foo
scope :by_bar, -> {
order(Arel.sql(
<<-SQL
(CASE WHEN foo LIKE 'bar%' THEN 1 ELSE 2 END) asc,
classification asc
SQL
))
}
scope :by_foo_and_bar, -> { by_classification.order(:foo) }
end
Format 1:
class Foo
scope :by_bar, -> { order(Arel.sql(<<-SQL)) }
(CASE WHEN foo LIKE 'bar%' THEN 1 ELSE 2 END) asc,
classification asc
SQL
scope :by_foo_and_bar, -> { by_classification.order(:foo) }
end
Format 2:
class Foo
scope :by_bar, -> { order(Arel.sql(<<-SQL)) }
(CASE WHEN foo LIKE 'bar%' THEN 1 ELSE 2 END) asc,
classification asc
SQL
scope :by_foo_and_bar, -> { by_classification.order(:foo) }
end
e.g.
long_name << longer_name << really_long_name << really_longer_name << even_longer_name << and_a_final_long_name
Expected:
long_name << longer_name << really_long_name << really_longer_name <<
even_longer_name << and_a_final_long_name
Given the trivial program
/asdf/
/asdf/i
/asdf/m
/asdf/x
/asdf/o
/asdf/imxo
the pretty-print for each of these regular expressions literals is identical:
(program
(statements
((regexp_literal ((tstring_content "asdf"))),
(regexp_literal ((tstring_content "asdf"))),
(regexp_literal ((tstring_content "asdf"))),
(regexp_literal ((tstring_content "asdf"))),
(regexp_literal ((tstring_content "asdf"))),
(regexp_literal ((tstring_content "asdf"))))))
even though they have different options (which are present in the AST node as part of the ending
attribute).
I'm happy to submit a PR to change this behavior if you a) think it would be valuable, and b) would be so kind as to suggest the sexp structure you'd like to emit in this case.
expect(sorted_fruit.map { |fruit| fruit["name"] }).
# order by size
to eq(["apple", "strawberry", "blueberry"])
For more details, see prettier/plugin-ruby#1034
On this and the prettier-ruby gem, I found that the "everything in one file" situation to be a bit of an obstacle to contributing and understanding what's going on. I notice you've started splitting up the different pieces - would you be open to a PR that puts each Node subclass in its own file?
Hey Kevin,
Seems that formatting has changed in 4.0, causing conflicts with rubocop rules.
For example:
4.0 wants to change this:
module Migration
Sequel.migration do
down do
DB.run(
"
SOME SQL STMT
"
)
end
end
end
to this:
module Migration
Sequel.migration do
down { DB.run("
SOME SQL STMT
") }
end
end
and rubocop is complaining:
C: [Correctable] Layout/FirstMethodArgumentLineBreak: Add a line break before the first argument of a multi-line method argument list.
DB.run(" ...
another example with puts:
before:
puts(
'
some string.
'.gsub(/^\s+/, '')
)
after:
puts('
some string.
'.gsub(/^\s+/, ''))
In https://github.com/ruby-syntax-tree/syntax_tree/pull/152/files#diff-9c0147bbfba8210004d93e758fd167a09f12f0749003f15bd8ea5f41da995f9bR390, I believe the conditional changed from
$stdin.tty? || arguments.any?
to $stdin.tty? && (arguments.any? || options.scripts.any?)
. This seems to alter the conditional to prevent non-tty stdin from using FileItem
types. Instead you get the following warning:
[warn] stdin
The listed files did not match the expected format.
This popped up for me when I tried to upgrade syntax_tree
and it broke CI checks I had previously setup.
If this was intentional, is there a better recommended way to run stree:check
in CI?
From phlex-ruby/phlex#157
https://github.com/ruby-next/ruby-next could be a nice way to support TruffleRuby in syntax_tree
until TruffleRuby has full pattern matching support (which will likely require the new parser, the existing one seems too buggy to support hash patterns and other cases).
@kddnewton Would you be open to a PR using https://github.com/ruby-next/ruby-next to make syntax_tree on TruffleRuby and potentially other Rubies? I might give it a try.
It's not ideal because Ripper is rather slow on TruffleRuby (it's a lot of C ext code to warmup), but it should work.
P.S.: I guess longer-term the new parser would probably also be used for syntax_tree or instead of it? Although I guess if Ripper uses the new parser there might not need to do anything and it'd still use the new parser under the hood, it'd just be an extra indirection in between.
as an example:
- widget: {
- activator: "#Intercom"
- },
+ widget:
+ {
+ activator: "#Intercom"
+ },
This code gives a syntax error, but it's not clear why. It might be nice to either say, keyword arguments must come at the end, or show the red underline on the second argument.
Oddly, it works if we remove the T.must, so this might be a related bug.
module Foo
class Bar
extend T::Sig
sig { void}
def service
nil
end
sig { void }
def baz
Job.perform_later(service:, T.must(name))
end
end
end
- before_action :load_event, only: %i[show edit update destroy copy share delete]
+ before_action :load_event,
+ only: %i[show edit update destroy copy share delete]
Example:
puts SyntaxTree.format <<~RUBY
if a in Integer
puts "a is integer"
end
b => [Integer => c]
RUBY
emits:
puts "a is integer" if a in Integer
b in [Integer => c]
However, as long as you don't use in
earlier in scope, the b
line correctly isn't modified
puts SyntaxTree.format "b => [Integer => c]"
emits
b => [Integer => c]
Happy to take a crack at fixing if you can point me in the right direction.
I am trying to install Prettier for Ruby on Ubuntu 20.04 LTS. Unfortunately, since that version of Ubuntu ships Ruby 2.7.0 while syntax_tree (a dependency of the prettier gem) has a minimum requirement of 2.7.3 (#14), it doesn't work.
Is support for 2.7.0 something that might be considered supposing that somebody puts in the effort for a PR?
If you parse a string like foo = bar { |x| x + 1 }
, then traverse it down to the block node ({ |x| x + 1 }
), trying to format that node throws an error. Here's a repro case:
require 'syntax_tree'
# Create a node visitor that walks the syntax tree looking for blocks.
class BlockFinder < SyntaxTree::Visitor
attr_reader :first_block
visit_method def visit_do_block(node)
puts "found a brace block node!"
@first_block ||= node
# Don't traverse further
end
visit_method def visit_brace_block(node)
puts "found a brace block node!"
@first_block ||= node
# Don't traverse further
end
end
input_string = "foo = bar() { |x| x + 1}"
root = SyntaxTree.parse(input_string)
# use that visitor to find the first, outermost block
visitor = BlockFinder.new
visitor.visit(root)
block_node = visitor.first_block
formatter = SyntaxTree::Formatter.new(input_string, [], 80)
# !!! This throws an error:
# /Users/kevin/.rvm/gems/ruby-3.0.0/gems/syntax_tree-3.6.0/lib/syntax_tree/node.rb:1990:in `forced_do_end_bounds?': undefined method `call' for nil:NilClass
formatter.format(block_node)
# But if I comment that line out and then fake that this block node is nested
# within a parent node, it works:
formatter.instance_variable_set(:@stack, [proc {SyntaxTree::Program.new(statements: [], location: nil)}])
formatter.format(block_node)
formatter.flush
output_string = formatter.output.join
puts output_string # Prints { |x| x + 1 }
The issue seems to be that forced_do_end_bounds
in BlockFormatter
inspects the parent node and doesn't handle when it doesn't exist.
PS: thanks for the great tool and, honestly, the very readable source!
It would be nice to be able to format entire directories
For more information, see prettier/plugin-ruby#1171 and prettier/plugin-ruby#1158.
Using @prettier/plugin-ruby
3.1.2 and syntax_tree
2.6.0. A string like x = "asd'qwe"
is changed to x = 'asd\'qwe'
which I believe is worse. Is it possible to somehow configure plugin/single_quotes
? Or change the default so it doesn't do that? ๐
- expect { subject }.to change(ActionMailer::Base.deliveries, :count)
- .by(1)
+ expect { subject }.to change(
+ ActionMailer::Base.deliveries,
+ :count
+ ).by(1)
expect { subject }.to_not change(
- ActionMailer::Base.deliveries,
- :count
- )
+ ActionMailer::Base.deliveries,
+ :count
+ )
expect { subject }.to_not change(
- ActionMailer::Base.deliveries,
- :count
- )
+ ActionMailer::Base.deliveries,
+ :count
+ )
Sample code after formatting using @prettier/plugin-ruby
3:
if current_user&.admin? ||
Rails.application.config.x.team_ips.any? { |i|
i.include?(request.remote_ip)
}
Rack::MiniProfiler.authorize_request
end
This is triggering Rubocop, even after including this gem's config:
app/controllers/application_controller.rb:62:51: C: [Correctable] Style/BlockDelimiters: Avoid using {...} for multi-line blocks.
Rails.application.config.x.team_ips.any? { |i|
The original code (formatted by the Prettier plugin v2) cas using do โฆ end
, which did not trigger Rubocop.
I am not sure what is the correct fix here:
do โฆ end
again (but this might not be safe if I understand #120 correctly)Using syntax_tree
v1.1.0. Rewriting the following code:
n = 1
if (b = n+1) > 1
puts b
end
is rewritten as:
n = 1
puts b if (b = n + 1) > 1
which will cause an "undefined local variable or method" NameError
exception to be raised.
Steps to reproduce:
code foo.rb
to open a buffer with a name, on a file that doesn't yet exist on disktextDocument/inlayHints
requestOutcome: the stree
process crashes with ENOENT
Desired: the process recovers from file-not-exist (either by failing the jsonrpc request, or perhaps by grabbing fresh content from the request and putting it into the store).
Full backtrace here:
<snip>/syntax_tree-2.8.0/lib/syntax_tree/language_server.rb:26:in `binread': No such file or directory @ rb_sysopen - /tmp/bar.rb (Errno::ENOENT)
from <snip>/syntax_tree-2.8.0/lib/syntax_tree/language_server.rb:26:in `block in run'
from <snip>/syntax_tree-2.8.0/lib/syntax_tree/language_server.rb:68:in `run'
from <snip>/syntax_tree-2.8.0/lib/syntax_tree/cli.rb:262:in `run'
from <snip>/syntax_tree-2.8.0/exe/stree:9:in `<top (required)>'
I added to my .rubocop.yml
the suggested configuration.
inherit_gem:
rubocop-shopify: rubocop.yml
shopify-cloud: rubocop.yml
syntax_tree: config/rubocop.yml
Even with that it seems I still get Rubocop errors that I have to manually override such as
Layout/LineEndStringConcatenationIndentation
Layout/LineLength
Style/BlockDelimiters
Style/RegexpLiteral
Style/CommandLiteral
Style/SymbolLiteral
I would expect the config to override them for me, but I'm not sure if this was intentional.
rails -v
> Rails 7.0.1
ruby -v
> ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux]
I do gem add syntax_tree
, than rails s
, and then I receive a ton of the following (and similar) in logs:
/home/staleo/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/syntax_tree-1.2.0/lib/syntax_tree.rb:14006: syntax error, unexpected end', expecting end-of-input
Any ideas how to solve this? Thanks!
I used a class visitor and got the following class
(class
(const_ref (const "HomeController"))
(var_ref (const "ApplicationController"))
(bodystmt
(statements
((def
nil
nil
(ident "index")
(params)
(bodystmt (statements ((void_stmt)))))))))
I tried to use pattern matching on it using
case node
in { const_ref: const, var_ref: var, bodystmt: body }
puts "got class"
end
But it didn't match the class. Is there something I'm missing?
For more information, see prettier/plugin-ruby#1186
See ruby/ruby#5801.
Given the input
if true #comment1
#comment2
end
The syntax_tree formatter removes #comment1
, leaving only #comment2
if true
#comment2
end
Looking at this issue #129 and it seems to work correctly from the CLI
example code:
LongRecordName.transaction do
LongRecordName
.joins(:other_record)
# rubocop:disable Rails/SkipsModelValidations
.update_all(foo: 'bar')
end
CLI:
Error: Cannot find expected end
> 1 | LongRecordName.transaction do
| ^
2 | LongRecordName
3 | .joins(:other_record)
4 | # rubocop:disable Rails/SkipsModelValidations
The listed files did not match the expected format.
However in vscode it crashes synax-tree and there is nothing indicating that something is wrong. Is this the correct behavior?
VSCODE:
/Users/nix/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/syntax_tree-3.6.0/lib/syntax_tree/parser.rb:251:in `find_token': Cannot find expected end (SyntaxTree::Parser::ParseError)
from /Users/nix/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/syntax_tree-3.6.0/lib/syntax_tree/parser.rb:1242:in `on_do_block'
from /Users/nix/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/syntax_tree-3.6.0/lib/syntax_tree.rb:47:in `parse'
from /Users/nix/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/syntax_tree-3.6.0/lib/syntax_tree.rb:47:in `parse'
from /Users/nix/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/syntax_tree-3.6.0/lib/syntax_tree.rb:54:in `format'
from /Users/nix/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/syntax_tree-3.6.0/lib/syntax_tree/language_server.rb:90:in `format'
from /Users/nix/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/syntax_tree-3.6.0/lib/syntax_tree/language_server.rb:59:in `run'
from /Users/nix/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/syntax_tree-3.6.0/lib/syntax_tree/cli.rb:410:in `run'
from /Users/nix/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/syntax_tree-3.6.0/exe/stree:9:in `<top (required)>'
from /Users/nix/.asdf/installs/ruby/3.1.2/bin/stree:25:in `load'
from /Users/nix/.asdf/installs/ruby/3.1.2/bin/stree:25:in `<main>'
[Info - 5:29:20 PM] Connection to server got closed. Server will restart.
def foo
some_interesting_method
.another_method
.yet_another_interesting_one do |first_object, second|
first_object.do_something(second)
end
end
for more details see prettier/plugin-ruby#1130
Hey,
Just FYI, on my machine + our CI, since v5.0.0, our plugins are not respected anymore (in a .streerc
or via the command line).
Call chains should be formatted one indentation to the right with leading operators if the overall chain breaks.
foo.bar.baz.qux.qax
vvvvvvvvvvvvvvvvvvvvvvv
foo
.bar
.baz
.qux
.qax
There's prior art here from the way it's handled in prettier https://github.com/prettier/plugin-ruby/blob/main/src/ruby/nodes/calls.ts by passing doc nodes up the tree as it's printed so the top-most call node has something to put into its if_break
block.
Not really an issue, please close. But in case anyone is looking for vimscript support ... I kind of cobbled this hack up.
I guess the next thing will be for someone to cleanly package this up in a plugin (and clean the messy bits).
" with help from https://github.com/prettier/vim-prettier/blob/master/autoload/prettier/utils/buffer.vim
function SyntaxTreeRubyFormat()
let l:contents = join(getline(1, '$'), "\n")
let l:path = fnamemodify(expand('%:p'), ':h')
let l:found = 0
while len(l:path) > 2
if filereadable(l:path . '/Gemfile')
let l:gemfile = join(readfile(l:path . '/Gemfile'), "\n")
if stridx(l:gemfile, 'syntax_tree') > 0
let l:found = 1
break
endif
endif
let l:path = fnamemodify(l:path, ':h')
endwhile
if l:found == 0
return
endif
let l:command = "bundle exec stree format"
let l:old_path = chdir(l:path)
let l:old_ruby_opt = $RUBYOPT
let $RUBYOPT = "-W0"
let l:formatted = system(l:command, l:contents)
let $RUBYOPT = l:old_ruby_opt
call chdir(l:old_path)
let l:winview = winsaveview()
" https://vim.fandom.com/wiki/Restore_the_cursor_position_after_undoing_text_change_made_by_a_script
" create a fake change entry and merge with undo stack prior to do formating
execute "normal! i "
execute "normal! a\<BS>"
try | silent undojoin | catch | endtry
" delete all lines on the current buffer
silent! execute 'lockmarks %delete _'
" replace all lines from the current buffer with output from prettier
let l:idx = 0
for l:line in split(l:formatted, "\n")
silent! lockmarks call append(l:idx, l:line)
let l:idx += 1
endfor
" delete trailing newline introduced by the above append procedure
silent! lockmarks execute '$delete _'
" Restore view
call winrestview(l:winview)
endfunction
nmap <silent> <leader>s :call SyntaxTreeRubyFormat()<CR>
Hey,
What would be the best way to integrate this with RubyMine ?
i.e. be able to format on save.
Thanks
When formatting the code:
foo.instance_exec(&T.must(block))
It gets formatted to
foo.instance_exec()
I just noticed syntax_tree having an argument with the contents of this file and crashing:
if ::ActiveRecord.respond_to?(:use_yaml_unsafe_load)
::ActiveRecord.use_yaml_unsafe_load = false
::ActiveRecord.yaml_column_permitted_classes = [
::ActionController::Parameters
::ActiveRecord::Type::Time::Value,
::ActiveSupport::HashWithIndifferentAccess
::ActiveSupport::TimeWithZone,
::ActiveSupport::TimeZone,
::BigDecimal,
::Date,
::Symbol,
::Time,
]
end
it crashes even if stripped down of ::
, not sure what's going on.
/Users/kain/.rvm/gems/ruby-3.0.0/gems/syntax_tree-3.3.0/lib/syntax_tree/parser.rb:2474:in `on_parse_error': syntax error, unexpected :: at EXPR_BEG, expecting ']' (SyntaxTree::Parser::ParseError)
from /Users/kain/.rvm/gems/ruby-3.0.0/gems/syntax_tree-3.3.0/lib/syntax_tree.rb:46:in `parse'
from /Users/kain/.rvm/gems/ruby-3.0.0/gems/syntax_tree-3.3.0/lib/syntax_tree.rb:46:in `parse'
from /Users/kain/.rvm/gems/ruby-3.0.0/gems/syntax_tree-3.3.0/lib/syntax_tree.rb:53:in `format'
from /Users/kain/.rvm/gems/ruby-3.0.0/gems/syntax_tree-3.3.0/lib/syntax_tree/language_server.rb:101:in `format'
from /Users/kain/.rvm/gems/ruby-3.0.0/gems/syntax_tree-3.3.0/lib/syntax_tree/language_server.rb:59:in `run'
from /Users/kain/.rvm/gems/ruby-3.0.0/gems/syntax_tree-3.3.0/lib/syntax_tree/cli.rb:310:in `run'
from /Users/kain/.rvm/gems/ruby-3.0.0/gems/syntax_tree-3.3.0/exe/stree:9:in `<top (required)>'
from /Users/kain/.rvm/gems/ruby-3.0.0/bin/stree:23:in `load'
from /Users/kain/.rvm/gems/ruby-3.0.0/bin/stree:23:in `<main>'
[Info - 8:43:17 PM] Connection to server got closed. Server will restart.
input.rb
class A
private_class_method def self.foo
puts 'hello, world!'
end
end
output.rb
class A
private_class_method def self.foo
puts "hello, world!"
end
end
diff
--- input.rb 2022-03-24 14:26:09.669225408 -0700
+++ output.rb 2022-03-24 14:26:22.145203738 -0700
@@ -1,5 +1,5 @@
class A
private_class_method def self.foo
- puts 'hello, world!'
- end
+ puts "hello, world!"
+ end
end
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.