Giter Site home page Giter Site logo

syntax_tree's People

Contributors

andyw8 avatar bbuchalter avatar boris-petrov avatar csalvato avatar davidtaylorhq avatar dependabot[bot] avatar drbragg avatar eregon avatar etiennebarrie avatar felipe-vicente avatar github-actions[bot] avatar jez avatar kddnewton avatar molawson avatar morriar avatar paracycle avatar petercopter avatar sevenc-nanashi avatar strake7 avatar t-mario-y avatar vinistock avatar wassimk avatar weizheheng avatar wenderjean avatar wildmaples avatar xeger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

syntax_tree's Issues

Use with neovim

Please can you tell me how I can integrate in my neovim workflow, or if exit some plugin that use this gem.
Thank

stree hangs out with 100% CPU

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.

Read config from file

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.

Code causes syntax tree thread to terminate

Running syntax tree on this code crashes it

LongRecordName.transaction do
  LongRecordName
    .joins(:other_record)
    # rubocop:disable Rails/SkipsModelValidations

    .update_all(foo: 'bar')
end

Error:

[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'

Expected

Shows syntax error, but no stack trace

Situation where code formatting is not idempotent and creates really long comment

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

Rework inlay hints to match the spec

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.

Configuring SyntaxTree formatting

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.

Make line width configurable on the CLI ?

We are evaluating this on discourse/discourse and all our plugins.

Things are looking good, but this jumped to me as weird:

https://github.com/discourse/discourse-chat/pull/1030/files#diff-001301097537175b30c546260016452d2ff11f02435e4acb6cbd4143d744b407R199

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.

Align control structure statements with method chaining

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.

Transform between braces & do/end when reflowing blocks?

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.

Second example of non idempotent formatting

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

Long chain of << expressions doesn't get cut off

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

Pretty-print regular expression options

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.

Splitting up node.rb

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?

v4 changed formatting conflicts with rubocop

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+/, ''))

Bug with passing arguments for non-tty stdin.

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?

Supporting TruffleRuby through using RubyNext

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.

Odd syntax error?

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.

image

Oddly, it works if we remove the T.must, so this might be a related bug.

image

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

Rightward assignment `=>` converted to `in` when preceded by `in` in a prior line

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.

Support for Ruby 2.7.0?

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?

Blocks cannot be formatted when they're top-level nodes

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!

wrong indentation after block passed

-            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
+                     )

Block arguments in `if` statements uses `{`, triggering Rubocop

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:

  • Format the code to use do โ€ฆ end again (but this might not be safe if I understand #120 correctly)
  • Have the Rubocop config ignore this rule, as this gem will format it correctly

Guard against format requests for files that don't yet exist on disk

Steps to reproduce:

  1. Install vscode-syntax-tree & make sure it's in working order on existing source files
  2. Use code foo.rb to open a buffer with a name, on a file that doesn't yet exist on disk
  3. Type some Ruby code into the buffer to trigger a textDocument/inlayHints request

Outcome: 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)>'

Rubocop configuration doesn't seem to work

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.

unexpected `end', expecting end-of-input

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!

Unable to pattern match nodes

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?

Code causes syntax tree to crash

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.

v5 not using provided plugins

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

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.

Vimscript support

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>

Rubymine Integration

Hey,

What would be the best way to integrate this with RubyMine ?

i.e. be able to format on save.

Thanks

SyntaxTree::Parser::ParseError crash in vscode

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.

Body of `private_class_method` method is indented too far

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.