rufo 0.2.0 → 0.3.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
  SHA1:
3
- metadata.gz: 568bbd1f6cd032ca58647141b94d48748688a1af
4
- data.tar.gz: f4d143cd048591f4a98869d7709384fdfd8b362c
3
+ metadata.gz: 68781ad7a9acb9d0469157827d84c19a3c43582d
4
+ data.tar.gz: 8dd6f678a49a8e26bd01f534ca0b3c060b88d8a9
5
5
  SHA512:
6
- metadata.gz: '0854453cd81dbaaa44175c794c595ce171de33320b2c51ba2e5a6f61dec76f175e82c0a0c572d1826aca71ff289f777d01c2ea283ba9713a7bed643123a31f30'
7
- data.tar.gz: 1c6469b61a0f9601a48a93811df18131fae20ff226965cbd7962f92b7427d17d7d98a8fb9c157cb2074794707d671126377573b3329aa1936b4d18045a9e5470
6
+ metadata.gz: 82a80a462d83f51b449a64c6b12c6a49fdd658b3321bc720a24239613ca375e5340585e2e81bd667c9c88eb956bf5d5dae557434186924817b8e9ef3c8f9ec9d
7
+ data.tar.gz: df226a82d72e7ec562b6b002e9c89956a6add4a8b5f2933c7e4f53ea53140f270acbf21e50ab297689dab1a0dad2e71fc671ee5fa24a2a638a6756cec8762dbd
@@ -2,10 +2,14 @@ sudo: false
2
2
  language: ruby
3
3
  cache: bundler
4
4
  rvm:
5
+ - 2.5.0
5
6
  - 2.4.2
6
7
  - 2.3.5
7
8
  - 2.2.8
8
9
  - ruby-head
9
- before_install: gem install bundler -v 1.15.4
10
+ matrix:
11
+ allow_failures:
12
+ - rvm: ruby-head
13
+ before_install: gem install bundler -v 1.16.1
10
14
  script:
11
15
  - bundle exec rake ci
@@ -6,6 +6,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.3.0] - 2018-03-24
10
+
11
+ ### Added
12
+ - Added Idempotency check to source_specs/ tester.
13
+ - Normalize string quotes according to quote_style, which defaults to :double.
14
+
15
+ ## Fixed
16
+ - Fix printing of extraneous trailing semicolons from inline classes, modules, methods (issue [#59](https://github.com/ruby-formatter/rufo/issues/59))
17
+ - Fix unhandled white space between array getter/setters `x[0] [0]` (issue [#62](https://github.com/ruby-formatter/rufo/issues/62))
18
+ - Fix comma printing for heredocs when inside a hash (issue [#61](https://github.com/ruby-formatter/rufo/issues/61))
19
+ - Fix array literals against changes to Ruby 2.5.0
20
+
9
21
  ## [0.2.0] - 2017-11-13
10
22
  ### Changed
11
23
  Config parsing and handling:
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Rufo
2
2
 
3
- [![Build Status](https://travis-ci.org/ruby-formatter/rufo.svg)](https://travis-ci.org/ruby-formatter/rufo)
3
+ [![Build Status](https://api.travis-ci.org/ruby-formatter/rufo.svg?branch=master)](https://travis-ci.org/ruby-formatter/rufo)
4
4
  [![Gem](https://img.shields.io/gem/v/rufo.svg)](https://rubygems.org/gems/rufo)
5
5
 
6
6
  **Ru**by **fo**rmatter
@@ -65,7 +65,7 @@ class Rufo::Command
65
65
 
66
66
  args.each do |arg|
67
67
  if Dir.exist?(arg)
68
- files.concat Dir[File.join(arg, '**', '*.rb')].select(&File.method(:file?))
68
+ files.concat Dir[File.join(arg, "**", "*.rb")].select(&File.method(:file?))
69
69
  elsif File.exist?(arg)
70
70
  files << arg
71
71
  else
@@ -109,7 +109,7 @@ Rufo Warning!
109
109
  end
110
110
 
111
111
  def squiggly_warning_files
112
- @squiggly_warning_files.join(', ')
112
+ @squiggly_warning_files.join(", ")
113
113
  end
114
114
 
115
115
  def backported_version
@@ -22,12 +22,12 @@ class Rufo::DotFile
22
22
  file_contents.lines
23
23
  .map { |s| s.strip.split(/\s+/, 2) }
24
24
  .each_with_object({}) do |(name, value), acc|
25
- value ||= ''
26
- if value.start_with?(':')
25
+ value ||= ""
26
+ if value.start_with?(":")
27
27
  value = value[1..-1].to_sym
28
- elsif value == 'true'
28
+ elsif value == "true"
29
29
  value = true
30
- elsif value == 'false'
30
+ elsif value == "false"
31
31
  value = false
32
32
  else
33
33
  $stderr.puts "Unknown config value=#{value.inspect} for #{name.inspect}"
@@ -159,7 +159,20 @@ class Rufo::Formatter
159
159
  # This is [[line, original_line], ...]
160
160
  @inline_declarations = []
161
161
 
162
+ # This is used to track how far deep we are in the AST.
163
+ # This is useful as it allows you to check if you are inside an array
164
+ # when dealing with heredocs.
165
+ @node_level = 0
166
+
167
+ # This represents the node level of the most recent literal elements list.
168
+ # It is used to track if we are in a list of elements so that commas
169
+ # can be added appropriately for heredocs for example.
170
+ @literal_elements_level = nil
171
+
162
172
  init_settings(options)
173
+
174
+ # Which quote character are we using?
175
+ @quote_char = (quote_style == :double) ? '"' : "'"
163
176
  end
164
177
 
165
178
  def format
@@ -175,6 +188,7 @@ class Rufo::Formatter
175
188
  end
176
189
 
177
190
  def visit(node)
191
+ @node_level += 1
178
192
  unless node.is_a?(Array)
179
193
  bug "unexpected node: #{node} at #{current_token}"
180
194
  end
@@ -473,6 +487,8 @@ class Rufo::Formatter
473
487
  else
474
488
  bug "Unhandled node: #{node.first}"
475
489
  end
490
+ ensure
491
+ @node_level -= 1
476
492
  end
477
493
 
478
494
  def visit_exps(exps, with_indent: false, with_lines: true, want_trailing_multiline: false)
@@ -574,32 +590,96 @@ class Rufo::Formatter
574
590
  # Accumulate heredoc: we'll write it once
575
591
  # we find a newline.
576
592
  @heredocs << [node, tilde]
577
- next_token
593
+ # Get the next_token while capturing any output.
594
+ # This is needed so that we can add a comma if one is not already present.
595
+ captured_output = capture_output { next_token }
596
+
597
+ inside_literal_elements_list = !@literal_elements_level.nil? &&
598
+ (@node_level - @literal_elements_level) == 2
599
+ needs_comma = !comma? && trailing_commas
600
+
601
+ if inside_literal_elements_list && needs_comma
602
+ write ","
603
+ @last_was_heredoc = true
604
+ end
605
+
606
+ @output << captured_output
578
607
  return
579
608
  elsif current_token_kind == :on_backtick
580
609
  consume_token :on_backtick
581
610
  else
611
+ return if format_simple_string(node)
582
612
  consume_token :on_tstring_beg
583
613
  end
584
614
 
585
615
  visit_string_literal_end(node)
586
616
  end
587
617
 
588
- def visit_string_literal_end(node)
618
+ # For simple string formatting, look for nodes like:
619
+ # [:string_literal, [:string_content, [:@tstring_content, "abc", [...]]]]
620
+ # and return the simple string inside.
621
+ def simple_string(node)
622
+ inner = node[1][1..-1]
623
+ return if inner.length > 1
624
+ inner = inner[0]
625
+ return "" if !inner
626
+ return if inner[0] != :@tstring_content
627
+ string = inner[1]
628
+ string
629
+ end
630
+
631
+ # should we format this string according to :quote_style?
632
+ def should_format_string?(string)
633
+ # don't format %q or %Q
634
+ return unless current_token_value == "'" || current_token_value == '"'
635
+ # don't format strings containing slashes
636
+ return if string.include?("\\")
637
+ # don't format strings that contain our quote character
638
+ return if string.include?(@quote_char)
639
+ true
640
+ end
641
+
642
+ def format_simple_string(node)
643
+ # is it a simple string node?
644
+ string = simple_string(node)
645
+ return if !string
646
+
647
+ # is it eligible for formatting?
648
+ return if !should_format_string?(string)
649
+
650
+ # success!
651
+ write @quote_char
652
+ next_token
653
+ with_unmodifiable_string_lines do
654
+ inner = node[1][1..-1]
655
+ visit_exps(inner, with_lines: false)
656
+ end
657
+ write @quote_char
658
+ next_token
659
+
660
+ true
661
+ end
662
+
663
+ # Every line between the first line and end line of this string (excluding the
664
+ # first line) must remain like it is now (we don't want to mess with that when
665
+ # indenting/dedenting)
666
+ #
667
+ # This can happen with heredocs, but also with string literals spanning
668
+ # multiple lines.
669
+ def with_unmodifiable_string_lines(&block)
589
670
  line = @line
671
+ yield
672
+ (line + 1..@line).each do |i|
673
+ @unmodifiable_string_lines[i] = true
674
+ end
675
+ end
590
676
 
677
+ def visit_string_literal_end(node)
591
678
  inner = node[1]
592
679
  inner = inner[1..-1] unless node[0] == :xstring_literal
593
- visit_exps(inner, with_lines: false)
594
680
 
595
- # Every line between the first line and end line of this
596
- # string (excluding the first line) must remain like it is
597
- # now (we don't want to mess with that when indenting/dedenting)
598
- #
599
- # This can happen with heredocs, but also with string literals
600
- # spanning multiple lines.
601
- (line + 1..@line).each do |i|
602
- @unmodifiable_string_lines[i] = true
681
+ with_unmodifiable_string_lines do
682
+ visit_exps(inner, with_lines: false)
603
683
  end
604
684
 
605
685
  case current_token_kind
@@ -1256,11 +1336,7 @@ class Rufo::Formatter
1256
1336
 
1257
1337
  visit call
1258
1338
 
1259
- if block[0] == :brace_block
1260
- consume_space
1261
- else
1262
- consume_space
1263
- end
1339
+ consume_space
1264
1340
 
1265
1341
  old_dot_column = @dot_column
1266
1342
  old_original_dot_column = @original_dot_column
@@ -1619,7 +1695,7 @@ class Rufo::Formatter
1619
1695
  skip_space
1620
1696
  if comma?
1621
1697
  check :on_comma
1622
- write ','
1698
+ write ","
1623
1699
  next_token
1624
1700
  skip_space_or_newline
1625
1701
  end
@@ -2139,14 +2215,26 @@ class Rufo::Formatter
2139
2215
  has_space = current_token_value.end_with?(" ")
2140
2216
  write current_token_value.strip
2141
2217
 
2142
- # If there's a newline after `%w(`, write line and indent
2143
- if current_token_value.include?("\n") && elements
2218
+ # (pre 2.5.0) If there's a newline after `%w(`, write line and indent
2219
+ if current_token_value.include?("\n") && elements # "%w[\n"
2144
2220
  write_line
2145
- write_indent(next_indent)
2221
+ write_indent next_indent
2146
2222
  end
2147
2223
 
2148
2224
  next_token
2149
2225
 
2226
+ # fix for 2.5.0 ripper change
2227
+ if current_token_kind == :on_words_sep && elements && !elements.empty?
2228
+ value = current_token_value
2229
+ has_space = value.start_with?(" ")
2230
+ if value.include?("\n") && elements # "\n "
2231
+ write_line
2232
+ write_indent next_indent
2233
+ end
2234
+ next_token
2235
+ has_space = true if current_token_value.start_with?(" ")
2236
+ end
2237
+
2150
2238
  if elements && !elements.empty?
2151
2239
  write_space if has_space
2152
2240
  column = @column
@@ -2310,6 +2398,7 @@ class Rufo::Formatter
2310
2398
 
2311
2399
  token_column = current_token_column
2312
2400
 
2401
+ skip_space
2313
2402
  check :on_lbracket
2314
2403
  write "["
2315
2404
  next_token
@@ -2600,6 +2689,8 @@ class Rufo::Formatter
2600
2689
  first_space = nil
2601
2690
 
2602
2691
  elements.each_with_index do |elem, i|
2692
+ @literal_elements_level = @node_level
2693
+
2603
2694
  is_last = last?(i, elements)
2604
2695
  wrote_comma = false
2605
2696
 
@@ -2641,9 +2732,10 @@ class Rufo::Formatter
2641
2732
  write_space unless is_last
2642
2733
  end
2643
2734
  end
2735
+ @literal_elements_level = nil
2644
2736
 
2645
2737
  if needs_trailing_comma
2646
- write "," unless wrote_comma || !trailing_commas
2738
+ write "," unless wrote_comma || !trailing_commas || @last_was_heredoc
2647
2739
 
2648
2740
  consume_end_of_line(first_space: first_space)
2649
2741
  write_indent
@@ -2675,7 +2767,7 @@ class Rufo::Formatter
2675
2767
 
2676
2768
  def check_heredocs_in_literal_elements(is_last, needs_trailing_comma, wrote_comma)
2677
2769
  if (newline? || comment?) && !@heredocs.empty?
2678
- if !is_last || needs_trailing_comma
2770
+ if is_last && trailing_commas
2679
2771
  write "," unless wrote_comma
2680
2772
  wrote_comma = true
2681
2773
  end
@@ -3075,9 +3167,12 @@ class Rufo::Formatter
3075
3167
  # print it, but only if it's not followed by a newline
3076
3168
  if !found_newline && want_semicolon && last != :semicolon
3077
3169
  skip_space
3078
- case current_token_kind
3170
+ kind = current_token_kind
3171
+ case kind
3079
3172
  when :on_ignored_nl, :on_eof
3080
3173
  else
3174
+ return if (kind == :on_kw) &&
3175
+ (%w[class module def].include?(current_token_value))
3081
3176
  write "; "
3082
3177
  last = :semicolon
3083
3178
  end
@@ -3335,6 +3430,15 @@ class Rufo::Formatter
3335
3430
  end
3336
3431
  end
3337
3432
 
3433
+ def capture_output
3434
+ old_output = @output
3435
+ @output = "".dup
3436
+ yield
3437
+ result = @output
3438
+ @output = old_output
3439
+ result
3440
+ end
3441
+
3338
3442
  def write(value)
3339
3443
  @output << value
3340
3444
  @last_was_newline = false
@@ -4,6 +4,7 @@ module Rufo::Settings
4
4
  align_case_when: [false, true],
5
5
  align_chained_calls: [false, true],
6
6
  trailing_commas: [true, false],
7
+ quote_style: [:double, :single],
7
8
  }
8
9
 
9
10
  attr_accessor *OPTIONS.keys
@@ -14,7 +15,7 @@ module Rufo::Settings
14
15
  value = options.fetch(name, default)
15
16
  unless valid_options.include?(value)
16
17
  $stderr.puts "Invalid value for #{name}: #{value.inspect}. Valid " \
17
- "values are: #{valid_options.map(&:inspect).join(', ')}"
18
+ "values are: #{valid_options.map(&:inspect).join(", ")}"
18
19
  value = default
19
20
  end
20
21
  self.public_send("#{name}=", value)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rufo
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ary Borenszweig
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-13 00:00:00.000000000 Z
11
+ date: 2018-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -121,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
121
  version: '0'
122
122
  requirements: []
123
123
  rubyforge_project:
124
- rubygems_version: 2.6.13
124
+ rubygems_version: 2.6.14
125
125
  signing_key:
126
126
  specification_version: 4
127
127
  summary: Ruby code formatter