rufo 0.2.0 → 0.3.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 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