rufo 0.8.1 → 0.13.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
  SHA256:
3
- metadata.gz: e8e977df730572c1448155a1bc4e3fd358a1abcdadf78c18700874e75e9c54aa
4
- data.tar.gz: 07a074f0137daf3c957dd2d6646efb72281b062b93a7df7b1981b3fdcdd3ca79
3
+ metadata.gz: 67f0bac262d71b5c91c9babdc6d975e88d1b7f04e903b8111f7ccf4f56aa2a35
4
+ data.tar.gz: c437092573d817e16b05bf2ddc6a1b5a084bc8a81a06836b2e84528f65db1dca
5
5
  SHA512:
6
- metadata.gz: 32de1903e674e7a21f34b0e092d2fd4af9fa9db9f4570611b9e50bb7ec1ba031df7b940dbc9797855688d3a6956dfa2830a0251bf4ec7296b6f4a7b5117ad5fd
7
- data.tar.gz: 9592effea9978267ab0dc2d641b8e033a7a4156723a68e0aaf2b1742f69b768329a6a8d4824fcd0fdaf1ed342279f59a1cb2e15c13514045d350ddbfcbce6060
6
+ metadata.gz: 4e14f22cc80b1566449f65c5b5eb7ceaa4b3f7ed9e98c9dbce35161830049d155c7cc83dd6fe5c3e965ebc085b7cda787b18d4a705b71daebdc1571060a7b545
7
+ data.tar.gz: a49e26fe230db7e7c42d6f0a8cb700dec11caac98dfc6bfdc7eda7a0cfe80c3fb7b5da675acf0fd29da6b70253c893183279fd1b042d1f6e450f66b1e6e29813
data/.circleci/config.yml CHANGED
@@ -28,6 +28,9 @@
28
28
  --format RspecJunitFormatter \
29
29
  --out test_results/rspec.xml \
30
30
  --format progress
31
+ - run:
32
+ name: Upload code coverage
33
+ command: bash <(curl -s https://codecov.io/bash) -f 'coverage/coverage.xml'
31
34
  - run:
32
35
  name: Run RuboCop
33
36
  command: |
@@ -53,55 +56,46 @@
53
56
  - store_test_results:
54
57
  path: test_results
55
58
 
56
-
57
59
  version: 2
58
60
  jobs:
59
- build-2-7-0:
61
+ build-3-0-1:
60
62
  <<: *dockerbuild
61
63
  docker:
62
- - image: circleci/ruby:2.7.0
64
+ - image: circleci/ruby:3.0.1
63
65
  environment:
64
66
  BUNDLE_JOBS: "3"
65
67
  BUNDLE_RETRY: "3"
66
68
  BUNDLE_PATH: /home/circleci/project/vendor/bundle
67
- build-2-6-3:
69
+ build-2-7-3:
68
70
  <<: *dockerbuild
69
71
  docker:
70
- - image: circleci/ruby:2.6.3
72
+ - image: circleci/ruby:2.7.3
71
73
  environment:
72
74
  BUNDLE_JOBS: "3"
73
75
  BUNDLE_RETRY: "3"
74
76
  BUNDLE_PATH: /home/circleci/project/vendor/bundle
75
- build-2-6-1:
77
+ build-2-6-7:
76
78
  <<: *dockerbuild
77
79
  docker:
78
- - image: circleci/ruby:2.6.1
80
+ - image: circleci/ruby:2.6.7
79
81
  environment:
80
82
  BUNDLE_JOBS: "3"
81
83
  BUNDLE_RETRY: "3"
82
- BUNDLE_PATH: vendor/bundle
83
- build-2-5-3:
84
- <<: *dockerbuild
85
- docker:
86
- - image: circleci/ruby:2.5.3
87
- environment:
88
- BUNDLE_JOBS: "3"
89
- BUNDLE_RETRY: "3"
90
- BUNDLE_PATH: vendor/bundle
91
- build-2-4-5:
84
+ BUNDLE_PATH: /home/circleci/project/vendor/bundle
85
+ build-2-6-1:
92
86
  <<: *dockerbuild
93
87
  docker:
94
- - image: circleci/ruby:2.4.5
88
+ - image: circleci/ruby:2.6.1
95
89
  environment:
96
90
  BUNDLE_JOBS: "3"
97
91
  BUNDLE_RETRY: "3"
98
92
  BUNDLE_PATH: vendor/bundle
93
+
99
94
  workflows:
100
95
  version: 2
101
96
  test:
102
97
  jobs:
103
- - build-2-7-0
104
- - build-2-6-3
98
+ - build-3-0-1
99
+ - build-2-7-3
100
+ - build-2-6-7
105
101
  - build-2-6-1
106
- - build-2-5-3
107
- - build-2-4-5
data/.gitignore CHANGED
@@ -11,4 +11,8 @@
11
11
 
12
12
  # rspec failure tracking
13
13
  .rspec_status
14
+ spec/examples.txt
15
+
14
16
  sample_code
17
+
18
+ .byebug_history
data/.rspec CHANGED
@@ -1,2 +1,2 @@
1
+ --require spec_helper
1
2
  --format documentation
2
- --color
data/.rubocop.yml CHANGED
@@ -2,7 +2,7 @@ AllCops:
2
2
  Exclude:
3
3
  - "spec/**/*"
4
4
  - "vendor/**/*"
5
- TargetRubyVersion: 2.4
5
+ TargetRubyVersion: 2.6
6
6
 
7
7
  Layout:
8
8
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -12,6 +12,88 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
12
12
 
13
13
  ### Added
14
14
 
15
+ ## [0.13.0] - 2021-05-07
16
+
17
+ ### Fixed
18
+
19
+ - Properly format comma when a heredoc is passed as a call argument
20
+ - Correctly interpret case statements with multiple when clauses in ERB files
21
+
22
+ ### Changed
23
+
24
+ - Dropped support for Ruby 2.4 and 2.5 as they are end of life.
25
+
26
+ ### Added
27
+
28
+ - Add Ruby 3.0.1 to test runs on CI.
29
+
30
+ ## [0.12.0] - 2020-03-08
31
+
32
+ ### Fixed
33
+
34
+ - File.read default encode UTF-8
35
+ - Handle case where the code is invalid but ripper does not raise an error.
36
+ - Removed implicit dependency on `rake`.
37
+ - Error when semicolon and then used in a case statement #230.
38
+
39
+ ### Changed
40
+
41
+ ### Added
42
+ - Code coverage tracking with codecov.io
43
+ - `node_modules` folders are now ignored.
44
+
45
+ ## [0.11.0] - 2020-02-09
46
+
47
+ ### Fixed
48
+ - Documentation for `trailing_commas`
49
+ - Handle empty string symbol for key in hash.
50
+
51
+ ### Added
52
+ - Support for escaped ERB template tags. For example `<%%%%= format :name %>`.
53
+
54
+ ## [0.10.0] - 2020-01-16
55
+
56
+ ### Fixed
57
+ - Squiggly heredoc closing tag indentation.
58
+ - Formatting .erb files from stdin.
59
+
60
+ ### Changed
61
+ - Method parameters are now no longer aligned with the method parenthesis. For example:
62
+ - ```ruby
63
+ def foo(
64
+ param
65
+ )
66
+ end
67
+
68
+ # Becomes:
69
+
70
+ def foo(
71
+ param
72
+ )
73
+ end
74
+ ```
75
+ - Multiline assignments are no longer aligned with variable indentation.
76
+ - ```ruby
77
+ a = if true
78
+ b
79
+ end
80
+
81
+ # Becomes:
82
+
83
+ a = if true
84
+ b
85
+ end
86
+ ```
87
+ ### Added
88
+
89
+ ## [0.9.0] - 2020-01-11
90
+
91
+ ### Added
92
+
93
+ - Support for trim style erb templates ending with `-%>`.
94
+ - Support for rails raw mode erb templates starting with `<%==`.
95
+ - Support for ruby 2.7 features. This includes beginless ranges `..10`, method argument forwarding `def forward(...); to(...); end` and keyword args not being allowed `def foo(*args, **nil)`.
96
+
15
97
  ## [0.8.1] - 2020-01-02
16
98
 
17
99
  ### Fixed
@@ -8,6 +8,7 @@ repos = {
8
8
  "spec/rspec/core/formatters/snippet_extractor_spec.rb",
9
9
  "spec/rspec/core/metadata_spec.rb",
10
10
  "spec/rspec/core/formatters/html_formatter_spec.rb",
11
+ "spec/rspec/core/formatters_spec.rb",
11
12
  ].join(","),
12
13
  },
13
14
  }
data/docs/settings.md CHANGED
@@ -23,7 +23,7 @@ See https://github.com/ruby-formatter/rufo/issues/2 for more context!
23
23
  - [parens_in_def](#parens_in_def)
24
24
  - [trailing_commas](#trailing_commas)
25
25
  - [quote_style](#quote_style)
26
- - [includes and excludes](#includes%20and%20excludes)
26
+ - [includes and excludes](#includes-and-excludes)
27
27
 
28
28
  ### align_case_when
29
29
 
@@ -116,8 +116,8 @@ With `:dynamic` it won't modify it.
116
116
 
117
117
  Use trailing commas in array and hash literals, and keyword arguments?
118
118
 
119
- - `:always`: (default) always put a trailing comma
120
- - `:never`: never put a trailing comma
119
+ - `true`: (default) always put a trailing comma
120
+ - `false`: never put a trailing comma
121
121
 
122
122
  Given this code:
123
123
 
@@ -153,7 +153,7 @@ foo(
153
153
  )
154
154
  ```
155
155
 
156
- With `:always`, the formatter will change it to:
156
+ With `true`, the formatter will change it to:
157
157
 
158
158
  ```ruby
159
159
  [
@@ -187,7 +187,7 @@ foo(
187
187
  )
188
188
  ```
189
189
 
190
- With `:never`, the formatter will change it to:
190
+ With `false`, the formatter will change it to:
191
191
 
192
192
  ```ruby
193
193
  [
@@ -284,5 +284,5 @@ Files can be excluded or included in formatting with rufo by specifying glob pat
284
284
  For example:
285
285
  ```
286
286
  includes [*.txt,*.text]
287
- excludes [*.rb]
287
+ excludes [**/*.erb]
288
288
  ```
data/lib/rufo.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Rufo
4
4
  class Bug < StandardError; end
5
+ class UnknownSyntaxError < StandardError; end
5
6
 
6
7
  class SyntaxError < StandardError
7
8
  attr_reader :lineno
@@ -25,4 +26,5 @@ require_relative "rufo/parser"
25
26
  require_relative "rufo/formatter"
26
27
  require_relative "rufo/erb_formatter"
27
28
  require_relative "rufo/version"
29
+ require_relative "rufo/file_list"
28
30
  require_relative "rufo/file_finder"
data/lib/rufo/command.rb CHANGED
@@ -35,17 +35,18 @@ class Rufo::Command
35
35
 
36
36
  def run(argv)
37
37
  status_code = if argv.empty?
38
- format_stdin
39
- else
40
- format_args argv
41
- end
38
+ format_stdin
39
+ else
40
+ format_args argv
41
+ end
42
42
  exit exit_code(status_code)
43
43
  end
44
44
 
45
45
  def format_stdin
46
46
  code = STDIN.read
47
47
 
48
- result = format(code, @filename_for_dot_rufo || Dir.getwd)
48
+ erb = @filename_for_dot_rufo && @filename_for_dot_rufo.end_with?(".erb")
49
+ result = format(code, @filename_for_dot_rufo || Dir.getwd, erb: erb)
49
50
 
50
51
  print(result) if !@want_check
51
52
 
@@ -53,10 +54,13 @@ class Rufo::Command
53
54
  rescue Rufo::SyntaxError => e
54
55
  logger.error("STDIN is invalid code. Error on line:#{e.lineno} #{e.message}")
55
56
  CODE_ERROR
56
- rescue => ex
57
+ rescue Rufo::UnknownSyntaxError
58
+ logger.error("STDIN is invalid code. Try running the code for a better error.")
59
+ CODE_ERROR
60
+ rescue => e
57
61
  logger.error("You've found a bug!")
58
62
  logger.error("Please report it to https://github.com/ruby-formatter/rufo/issues with code that triggers it\n")
59
- raise ex
63
+ raise e
60
64
  end
61
65
 
62
66
  def format_args(args)
@@ -95,7 +99,7 @@ class Rufo::Command
95
99
 
96
100
  def format_file(filename)
97
101
  logger.debug("Formatting: #{filename}")
98
- code = File.read(filename)
102
+ code = File.read(filename, encoding: "UTF-8")
99
103
 
100
104
  begin
101
105
  location = @filename_for_dot_rufo || File.dirname(filename)
@@ -121,11 +125,14 @@ class Rufo::Command
121
125
  rescue Rufo::SyntaxError => e
122
126
  logger.error("#{filename}:#{e.lineno} #{e.message}")
123
127
  CODE_ERROR
124
- rescue => ex
128
+ rescue Rufo::UnknownSyntaxError
129
+ logger.error("#{filename} is invalid code. Try running the code for a better error.")
130
+ CODE_ERROR
131
+ rescue => e
125
132
  logger.error("You've found a bug!")
126
133
  logger.error("It happened while trying to format the file #{filename}")
127
134
  logger.error("Please report it to https://github.com/ruby-formatter/rufo/issues with code that triggers it\n")
128
- raise ex
135
+ raise e
129
136
  end
130
137
 
131
138
  def format(code, dir, erb: false)
@@ -1,6 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
  require "erb"
3
3
 
4
+ class CustomScanner < ERB::Compiler::TrimScanner
5
+ def initialize(src)
6
+ super(src, "<>", false)
7
+ @scan_reg = /(.*?)(%>\r?\n|#{(stags + etags).join("|")}|\n|\z)/m
8
+ end
9
+
10
+ def stags
11
+ ["<%==", "<%+={0,2}"] + super
12
+ end
13
+
14
+ def etags
15
+ super + ["-%>"]
16
+ end
17
+ end
18
+
4
19
  class Rufo::ErbFormatter
5
20
  def self.format(code, **options)
6
21
  new(code, **options).format
@@ -9,9 +24,8 @@ class Rufo::ErbFormatter
9
24
  attr_reader :result
10
25
 
11
26
  def initialize(code, **options)
12
- compiler = ERB::Compiler.new("<>")
13
27
  @options = options
14
- @scanner = compiler.make_scanner(code)
28
+ @scanner = CustomScanner.new(code)
15
29
  @code_mode = false
16
30
  @current_lineno = 0
17
31
  @current_column = 0
@@ -97,6 +111,7 @@ class Rufo::ErbFormatter
97
111
  return "begin", nil if Ripper.sexp("begin #{code_str}")
98
112
  return "begin\n", "\nend" if Ripper.sexp("begin\n#{code_str}\nend")
99
113
  return "if a\n", "\nend" if Ripper.sexp("if a\n#{code_str}\nend")
114
+ return "case a\n", "\nend" if Ripper.sexp("case a\n#{code_str}\nend")
100
115
  raise_syntax_error!(code_str)
101
116
  end
102
117
 
@@ -1,6 +1,3 @@
1
- require "find"
2
- require "rake/file_list"
3
-
4
1
  class Rufo::FileFinder
5
2
  include Enumerable
6
3
 
@@ -31,12 +28,9 @@ class Rufo::FileFinder
31
28
  *EXTENSIONS,
32
29
  ]
33
30
 
34
- EXCLUDED_DIRS = [
35
- "vendor",
36
- ]
37
-
38
31
  EXCLUDE_PATTERNS = [
39
32
  "vendor/**/*",
33
+ "node_modules/**/*",
40
34
  ]
41
35
 
42
36
  def initialize(files_or_dirs, includes: [], excludes: [])
@@ -69,7 +63,7 @@ class Rufo::FileFinder
69
63
  end
70
64
 
71
65
  def build_file_list
72
- fl = Rake::FileList.new(*DEFAULT_PATTERNS)
66
+ fl = Rufo::FileList.new(*DEFAULT_PATTERNS)
73
67
  fl.exclude(*EXCLUDE_PATTERNS)
74
68
  fl.exclude(*excludes)
75
69
  fl.include(*includes)
@@ -0,0 +1,244 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is based on https://github.com/ruby/rake/blob/master/lib/rake/file_list.rb
4
+ # Git commit: 5b8f8fc41a5d7d7d6a5d767e48464c60884d3aee
5
+
6
+ module Rufo
7
+
8
+ ##
9
+ # A FileList is essentially an array with a few helper methods defined to
10
+ # make file manipulation a bit easier.
11
+ #
12
+ # FileLists are lazy. When given a list of glob patterns for possible files
13
+ # to be included in the file list, instead of searching the file structures
14
+ # to find the files, a FileList holds the pattern for latter use.
15
+ #
16
+ # This allows us to define a number of FileList to match any number of
17
+ # files, but only search out the actual files when then FileList itself is
18
+ # actually used. The key is that the first time an element of the
19
+ # FileList/Array is requested, the pending patterns are resolved into a real
20
+ # list of file names.
21
+ #
22
+ class FileList
23
+
24
+ # == Method Delegation
25
+ #
26
+ # The lazy evaluation magic of FileLists happens by implementing all the
27
+ # array specific methods to call +resolve+ before delegating the heavy
28
+ # lifting to an embedded array object (@items).
29
+ #
30
+ # In addition, there are two kinds of delegation calls. The regular kind
31
+ # delegates to the @items array and returns the result directly. Well,
32
+ # almost directly. It checks if the returned value is the @items object
33
+ # itself, and if so will return the FileList object instead.
34
+ #
35
+ # The second kind of delegation call is used in methods that normally
36
+ # return a new Array object. We want to capture the return value of these
37
+ # methods and wrap them in a new FileList object. We enumerate these
38
+ # methods in the +SPECIAL_RETURN+ list below.
39
+
40
+ # List of array methods (that are not in +Object+) that need to be
41
+ # delegated.
42
+ ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map(&:to_s)
43
+
44
+ # List of additional methods that must be delegated.
45
+ MUST_DEFINE = %w[inspect <=>]
46
+
47
+ # List of methods that should not be delegated here (we define special
48
+ # versions of them explicitly below).
49
+ MUST_NOT_DEFINE = %w[to_a to_ary partition * <<]
50
+
51
+ # List of delegated methods that return new array values which need
52
+ # wrapping.
53
+ SPECIAL_RETURN = %w[
54
+ map collect sort sort_by select find_all reject grep
55
+ compact flatten uniq values_at
56
+ + - & |
57
+ ]
58
+
59
+ DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).map(&:to_s).sort.uniq
60
+
61
+ # Now do the delegation.
62
+ DELEGATING_METHODS.each do |sym|
63
+ if SPECIAL_RETURN.include?(sym)
64
+ ln = __LINE__ + 1
65
+ class_eval %{
66
+ def #{sym}(*args, &block)
67
+ resolve
68
+ result = @items.send(:#{sym}, *args, &block)
69
+ self.class.new.import(result)
70
+ end
71
+ }, __FILE__, ln
72
+ else
73
+ ln = __LINE__ + 1
74
+ class_eval %{
75
+ def #{sym}(*args, &block)
76
+ resolve
77
+ result = @items.send(:#{sym}, *args, &block)
78
+ result.object_id == @items.object_id ? self : result
79
+ end
80
+ }, __FILE__, ln
81
+ end
82
+ end
83
+
84
+ GLOB_PATTERN = %r{[*?\[\{]}
85
+
86
+ # Create a file list from the globbable patterns given. If you wish to
87
+ # perform multiple includes or excludes at object build time, use the
88
+ # "yield self" pattern.
89
+ #
90
+ # Example:
91
+ # file_list = FileList.new('lib/**/*.rb', 'test/test*.rb')
92
+ #
93
+ # pkg_files = FileList.new('lib/**/*') do |fl|
94
+ # fl.exclude(/\bCVS\b/)
95
+ # end
96
+ #
97
+ def initialize(*patterns)
98
+ @pending_add = []
99
+ @pending = false
100
+ @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
101
+ @exclude_procs = DEFAULT_IGNORE_PROCS.dup
102
+ @items = []
103
+ patterns.each { |pattern| include(pattern) }
104
+ yield self if block_given?
105
+ end
106
+
107
+ # Add file names defined by glob patterns to the file list. If an array
108
+ # is given, add each element of the array.
109
+ #
110
+ # Example:
111
+ # file_list.include("*.java", "*.cfg")
112
+ # file_list.include %w( math.c lib.h *.o )
113
+ #
114
+ def include(*filenames)
115
+ filenames.each do |fn|
116
+ @pending_add << fn
117
+ end
118
+ @pending = true
119
+ self
120
+ end
121
+
122
+ alias :add :include
123
+
124
+ # Register a list of file name patterns that should be excluded from the
125
+ # list. Patterns may be regular expressions, glob patterns or regular
126
+ # strings. In addition, a block given to exclude will remove entries that
127
+ # return true when given to the block.
128
+ #
129
+ # Note that glob patterns are expanded against the file system. If a file
130
+ # is explicitly added to a file list, but does not exist in the file
131
+ # system, then an glob pattern in the exclude list will not exclude the
132
+ # file.
133
+ #
134
+ # Examples:
135
+ # FileList['a.c', 'b.c'].exclude("a.c") => ['b.c']
136
+ # FileList['a.c', 'b.c'].exclude(/^a/) => ['b.c']
137
+ #
138
+ # If "a.c" is a file, then ...
139
+ # FileList['a.c', 'b.c'].exclude("a.*") => ['b.c']
140
+ #
141
+ # If "a.c" is not a file, then ...
142
+ # FileList['a.c', 'b.c'].exclude("a.*") => ['a.c', 'b.c']
143
+ #
144
+ def exclude(*patterns, &block)
145
+ patterns.each do |pat|
146
+ @exclude_patterns << pat
147
+ end
148
+ @exclude_procs << block if block_given?
149
+ resolve_exclude unless @pending
150
+ self
151
+ end
152
+
153
+ # Return the internal array object.
154
+ def to_a
155
+ resolve
156
+ @items
157
+ end
158
+
159
+ def <<(obj)
160
+ resolve
161
+ @items << obj
162
+ self
163
+ end
164
+
165
+ # Resolve all the pending adds now.
166
+ def resolve
167
+ if @pending
168
+ @pending = false
169
+ @pending_add.each do |fn| resolve_add(fn) end
170
+ @pending_add = []
171
+ resolve_exclude
172
+ end
173
+ self
174
+ end
175
+
176
+ def resolve_add(filename) # :nodoc:
177
+ case filename
178
+ when GLOB_PATTERN
179
+ add_matching(filename)
180
+ else
181
+ self << filename
182
+ end
183
+ end
184
+
185
+ private :resolve_add
186
+
187
+ def resolve_exclude # :nodoc:
188
+ reject! { |fn| excluded_from_list?(fn) }
189
+ self
190
+ end
191
+
192
+ private :resolve_exclude
193
+ # Convert a FileList to a string by joining all elements with a space.
194
+ def to_s
195
+ resolve
196
+ self.join(" ")
197
+ end
198
+
199
+ # Add matching glob patterns.
200
+ def add_matching(pattern)
201
+ self.class.glob(pattern).each do |fn|
202
+ self << fn unless excluded_from_list?(fn)
203
+ end
204
+ end
205
+
206
+ private :add_matching
207
+
208
+ # Should the given file name be excluded from the list?
209
+ def excluded_from_list?(filename)
210
+ return true if @exclude_patterns.any? do |pat|
211
+ case pat
212
+ when Regexp
213
+ filename =~ pat
214
+ when GLOB_PATTERN
215
+ flags = File::FNM_PATHNAME
216
+ flags |= File::FNM_EXTGLOB
217
+ File.fnmatch?(pat, filename, flags)
218
+ else
219
+ filename == pat
220
+ end
221
+ end
222
+ @exclude_procs.any? { |p| p.call(filename) }
223
+ end
224
+
225
+ DEFAULT_IGNORE_PATTERNS = [
226
+ /(^|[\/\\])CVS([\/\\]|$)/,
227
+ /(^|[\/\\])\.svn([\/\\]|$)/,
228
+ /\.bak$/,
229
+ /~$/,
230
+ ]
231
+ DEFAULT_IGNORE_PROCS = [
232
+ proc { |fn| fn =~ /(^|[\/\\])core$/ && !File.directory?(fn) },
233
+ ]
234
+
235
+ class << self
236
+ # Get a sorted list of files matching the pattern. This method
237
+ # should be preferred to Dir[pattern] and Dir.glob(pattern) because
238
+ # the files returned are guaranteed to be sorted.
239
+ def glob(pattern, *args)
240
+ Dir.glob(pattern, *args).sort
241
+ end
242
+ end
243
+ end
244
+ end
@@ -21,7 +21,10 @@ class Rufo::Formatter
21
21
 
22
22
  # sexp being nil means that the code is not valid.
23
23
  # Parse the code so we get better error messages.
24
- Rufo::Parser.parse(code) if @sexp.nil?
24
+ if @sexp.nil?
25
+ Rufo::Parser.parse(code)
26
+ raise Rufo::UnknownSyntaxError # Sometimes parsing does not raise an error
27
+ end
25
28
 
26
29
  @indent = 0
27
30
  @line = 0
@@ -209,7 +212,7 @@ class Rufo::Formatter
209
212
  when :@float
210
213
  # Float literal
211
214
  #
212
- # [:@int, "123.45", [1, 0]]
215
+ # [:@float, "123.45", [1, 0]]
213
216
  consume_token :on_float
214
217
  when :@rational
215
218
  # Rational literal
@@ -484,6 +487,8 @@ class Rufo::Formatter
484
487
  visit_begin_node(node)
485
488
  when :END
486
489
  visit_end_node(node)
490
+ when :args_forward
491
+ consume_op("...")
487
492
  else
488
493
  bug "Unhandled node: #{node.first}"
489
494
  end
@@ -885,19 +890,24 @@ class Rufo::Formatter
885
890
  def visit_assign_value(value)
886
891
  has_slash_newline, _first_space = skip_space_backslash
887
892
 
888
- sticky = indentable_value?(value)
889
-
890
893
  # Remove backslash after equal + newline (it's useless)
891
894
  if has_slash_newline
892
895
  skip_space_or_newline
893
- write_line
896
+ write_space
894
897
  indent(next_indent) do
895
- write_indent
896
898
  visit(value)
897
899
  end
898
900
  else
899
- indent_after_space value, sticky: sticky,
900
- want_space: true
901
+ if [:begin, :case, :if, :unless].include?(value.first)
902
+ skip_space_or_newline
903
+ write_space
904
+ indent(next_indent) do
905
+ visit value
906
+ end
907
+ else
908
+ indent_after_space value, sticky: false,
909
+ want_space: true
910
+ end
901
911
  end
902
912
  end
903
913
 
@@ -1116,11 +1126,14 @@ class Rufo::Formatter
1116
1126
 
1117
1127
  found_comma = comma?
1118
1128
 
1129
+ heredoc_needs_newline = true
1130
+
1119
1131
  if found_comma
1120
1132
  if needs_trailing_newline
1121
1133
  write "," if trailing_commas && !block_arg
1122
1134
 
1123
1135
  next_token
1136
+ heredoc_needs_newline = !newline?
1124
1137
  indent(next_indent) do
1125
1138
  consume_end_of_line
1126
1139
  end
@@ -1132,7 +1145,7 @@ class Rufo::Formatter
1132
1145
  end
1133
1146
 
1134
1147
  if newline? || comment?
1135
- if needs_trailing_newline
1148
+ if needs_trailing_newline && !@last_was_heredoc
1136
1149
  write "," if trailing_commas && want_trailing_comma
1137
1150
 
1138
1151
  indent(next_indent) do
@@ -1144,7 +1157,7 @@ class Rufo::Formatter
1144
1157
  end
1145
1158
  else
1146
1159
  if needs_trailing_newline && !found_comma
1147
- write "," if trailing_commas && want_trailing_comma
1160
+ write "," if trailing_commas && want_trailing_comma && !@last_was_heredoc
1148
1161
  consume_end_of_line
1149
1162
  write_indent
1150
1163
  end
@@ -1159,8 +1172,9 @@ class Rufo::Formatter
1159
1172
  call_info << @line
1160
1173
  end
1161
1174
 
1162
- if @last_was_heredoc
1175
+ if @last_was_heredoc && heredoc_needs_newline
1163
1176
  write_line
1177
+ write_indent
1164
1178
  end
1165
1179
  consume_token :on_rparen
1166
1180
  end
@@ -1193,9 +1207,6 @@ class Rufo::Formatter
1193
1207
  write current_token_value.rstrip
1194
1208
  next_token
1195
1209
  write_line
1196
- if @heredocs.last[1]
1197
- write_indent(next_indent)
1198
- end
1199
1210
  end
1200
1211
 
1201
1212
  printed = false
@@ -2029,6 +2040,7 @@ class Rufo::Formatter
2029
2040
  next_token
2030
2041
  skip_space
2031
2042
  skip_semicolons
2043
+ broken_across_line = false
2032
2044
 
2033
2045
  if empty_params?(params)
2034
2046
  skip_space_or_newline
@@ -2039,8 +2051,8 @@ class Rufo::Formatter
2039
2051
  write "("
2040
2052
 
2041
2053
  if newline? || comment?
2042
- column = @column
2043
- indent(column) do
2054
+ broken_across_line = true
2055
+ indent(next_indent) do
2044
2056
  consume_end_of_line
2045
2057
  write_indent
2046
2058
  visit params
@@ -2052,7 +2064,12 @@ class Rufo::Formatter
2052
2064
  end
2053
2065
 
2054
2066
  skip_space_or_newline
2067
+ consume_keyword("nil") if current_token[1] == :on_kw
2055
2068
  check :on_rparen
2069
+ if broken_across_line
2070
+ write_line
2071
+ write_indent
2072
+ end
2056
2073
  write ")"
2057
2074
  next_token
2058
2075
  end
@@ -2125,6 +2142,8 @@ class Rufo::Formatter
2125
2142
  case rest_param
2126
2143
  when 0, [:excessed_comma]
2127
2144
  write_params_comma
2145
+ when [:args_forward]
2146
+ consume_op "..."
2128
2147
  else
2129
2148
  # [:rest_param, [:@ident, "x", [1, 15]]]
2130
2149
  _, rest = rest_param
@@ -2377,7 +2396,7 @@ class Rufo::Formatter
2377
2396
  # [:dot2, left, right]
2378
2397
  _, left, right = node
2379
2398
 
2380
- visit left
2399
+ visit left unless left.nil?
2381
2400
  skip_space_or_newline
2382
2401
  consume_op(inclusive ? ".." : "...")
2383
2402
  skip_space_or_newline
@@ -2732,8 +2751,9 @@ class Rufo::Formatter
2732
2751
  # We have to be careful not to aumatically write a heredoc on next_token,
2733
2752
  # because we miss the chance to write a comma to separate elements
2734
2753
  first_space = skip_space_no_heredoc_check
2735
- wrote_comma = check_heredocs_in_literal_elements(is_last, wrote_comma)
2736
-
2754
+ indent(needed_indent) do
2755
+ wrote_comma = check_heredocs_in_literal_elements(is_last, wrote_comma)
2756
+ end
2737
2757
  next unless comma?
2738
2758
 
2739
2759
  unless is_last
@@ -2746,7 +2766,9 @@ class Rufo::Formatter
2746
2766
  next_token_no_heredoc_check
2747
2767
 
2748
2768
  first_space = skip_space_no_heredoc_check
2749
- wrote_comma = check_heredocs_in_literal_elements(is_last, wrote_comma)
2769
+ indent(needed_indent) do
2770
+ wrote_comma = check_heredocs_in_literal_elements(is_last, wrote_comma)
2771
+ end
2750
2772
 
2751
2773
  if newline? || comment?
2752
2774
  if is_last
@@ -2909,10 +2931,23 @@ class Rufo::Formatter
2909
2931
  visit_comma_separated_list conds
2910
2932
  skip_space
2911
2933
  end
2934
+ written_space = false
2935
+ if semicolon?
2936
+ inline = true
2937
+ skip_semicolons
2938
+
2939
+ if newline? || comment?
2940
+ inline = false
2941
+ else
2942
+ write ";"
2943
+ track_case_when
2944
+ write " "
2945
+ written_space = true
2946
+ end
2947
+ end
2912
2948
 
2913
- then_keyword = keyword?("then")
2914
- inline = then_keyword || semicolon?
2915
- if then_keyword
2949
+ if keyword?("then")
2950
+ inline = true
2916
2951
  next_token
2917
2952
 
2918
2953
  skip_space
@@ -2926,7 +2961,7 @@ class Rufo::Formatter
2926
2961
  # Cancel tracking of `case when ... then` on a nelwine.
2927
2962
  @case_when_positions.pop
2928
2963
  else
2929
- write_space
2964
+ write_space unless written_space
2930
2965
 
2931
2966
  write "then"
2932
2967
 
@@ -2949,16 +2984,6 @@ class Rufo::Formatter
2949
2984
 
2950
2985
  write_space
2951
2986
  end
2952
- elsif semicolon?
2953
- skip_semicolons
2954
-
2955
- if newline? || comment?
2956
- inline = false
2957
- else
2958
- write ";"
2959
- track_case_when
2960
- write " "
2961
- end
2962
2987
  end
2963
2988
 
2964
2989
  if inline
@@ -3845,6 +3870,7 @@ class Rufo::Formatter
3845
3870
  end
3846
3871
 
3847
3872
  def node_line(node, beginning: true)
3873
+ return if node.nil?
3848
3874
  # get line of node, it is only used in visit_hash right now,
3849
3875
  # so handling the following node types is enough.
3850
3876
  case node.first
data/lib/rufo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rufo
4
- VERSION = "0.8.1"
4
+ VERSION = "0.13.0"
5
5
  end
data/rufo.gemspec CHANGED
@@ -20,13 +20,16 @@ Gem::Specification.new do |spec|
20
20
  spec.bindir = "exe"
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
23
- spec.required_ruby_version = ">= 2.4.5"
23
+ spec.required_ruby_version = ">= 2.6.0"
24
24
 
25
25
  spec.add_development_dependency "bundler", ">= 1.15"
26
- spec.add_development_dependency "byebug", "~> 10.0.2"
26
+ spec.add_development_dependency "byebug", "~> 11.0.1"
27
27
  spec.add_development_dependency "guard-rspec", "~> 4.0"
28
- spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rake", "~> 13.0"
29
+ spec.add_development_dependency "rexml", "~> 3.2.5"
29
30
  spec.add_development_dependency "rspec", "~> 3.0"
30
31
  spec.add_development_dependency "rspec_junit_formatter", "~> 0.4.1"
31
- spec.add_development_dependency "rubocop", "~> 0.63.1"
32
+ spec.add_development_dependency "rubocop", "~> 0.79.0"
33
+ spec.add_development_dependency "simplecov", "~> 0.18.5"
34
+ spec.add_development_dependency "simplecov-cobertura", "~> 1.3.1"
32
35
  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.8.1
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ary Borenszweig
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-02 00:00:00.000000000 Z
11
+ date: 2021-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 10.0.2
33
+ version: 11.0.1
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 10.0.2
40
+ version: 11.0.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: guard-rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '13.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '13.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rexml
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.2.5
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.2.5
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +114,42 @@ dependencies:
100
114
  requirements:
101
115
  - - "~>"
102
116
  - !ruby/object:Gem::Version
103
- version: 0.63.1
117
+ version: 0.79.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.79.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.18.5
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.18.5
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov-cobertura
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 1.3.1
104
146
  type: :development
105
147
  prerelease: false
106
148
  version_requirements: !ruby/object:Gem::Requirement
107
149
  requirements:
108
150
  - - "~>"
109
151
  - !ruby/object:Gem::Version
110
- version: 0.63.1
152
+ version: 1.3.1
111
153
  description: Fast and unobtrusive Ruby code formatter
112
154
  email:
113
155
  - asterite@gmail.com
@@ -140,6 +182,7 @@ files:
140
182
  - lib/rufo/dot_file.rb
141
183
  - lib/rufo/erb_formatter.rb
142
184
  - lib/rufo/file_finder.rb
185
+ - lib/rufo/file_list.rb
143
186
  - lib/rufo/formatter.rb
144
187
  - lib/rufo/logger.rb
145
188
  - lib/rufo/parser.rb
@@ -151,7 +194,7 @@ homepage: https://github.com/ruby-formatter/rufo
151
194
  licenses:
152
195
  - MIT
153
196
  metadata: {}
154
- post_install_message:
197
+ post_install_message:
155
198
  rdoc_options: []
156
199
  require_paths:
157
200
  - lib
@@ -159,15 +202,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
159
202
  requirements:
160
203
  - - ">="
161
204
  - !ruby/object:Gem::Version
162
- version: 2.4.5
205
+ version: 2.6.0
163
206
  required_rubygems_version: !ruby/object:Gem::Requirement
164
207
  requirements:
165
208
  - - ">="
166
209
  - !ruby/object:Gem::Version
167
210
  version: '0'
168
211
  requirements: []
169
- rubygems_version: 3.0.3
170
- signing_key:
212
+ rubygems_version: 3.2.17
213
+ signing_key:
171
214
  specification_version: 4
172
215
  summary: Ruby code formatter
173
216
  test_files: []