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 +4 -4
- data/.circleci/config.yml +16 -22
- data/.gitignore +4 -0
- data/.rspec +1 -1
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +82 -0
- data/bin/verify-sample-code +1 -0
- data/docs/settings.md +6 -6
- data/lib/rufo.rb +2 -0
- data/lib/rufo/command.rb +17 -10
- data/lib/rufo/erb_formatter.rb +17 -2
- data/lib/rufo/file_finder.rb +2 -8
- data/lib/rufo/file_list.rb +244 -0
- data/lib/rufo/formatter.rb +60 -34
- data/lib/rufo/version.rb +1 -1
- data/rufo.gemspec +7 -4
- metadata +56 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67f0bac262d71b5c91c9babdc6d975e88d1b7f04e903b8111f7ccf4f56aa2a35
|
4
|
+
data.tar.gz: c437092573d817e16b05bf2ddc6a1b5a084bc8a81a06836b2e84528f65db1dca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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-
|
61
|
+
build-3-0-1:
|
60
62
|
<<: *dockerbuild
|
61
63
|
docker:
|
62
|
-
- image: circleci/ruby:
|
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-
|
69
|
+
build-2-7-3:
|
68
70
|
<<: *dockerbuild
|
69
71
|
docker:
|
70
|
-
- image: circleci/ruby:2.
|
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-
|
77
|
+
build-2-6-7:
|
76
78
|
<<: *dockerbuild
|
77
79
|
docker:
|
78
|
-
- image: circleci/ruby:2.6.
|
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-
|
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.
|
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-
|
104
|
-
- build-2-
|
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
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
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
|
data/bin/verify-sample-code
CHANGED
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
|
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
|
-
- `:
|
120
|
-
- `:
|
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
|
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
|
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 [
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
135
|
+
raise e
|
129
136
|
end
|
130
137
|
|
131
138
|
def format(code, dir, erb: false)
|
data/lib/rufo/erb_formatter.rb
CHANGED
@@ -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 =
|
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
|
|
data/lib/rufo/file_finder.rb
CHANGED
@@ -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 =
|
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
|
data/lib/rufo/formatter.rb
CHANGED
@@ -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
|
-
|
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
|
-
# [:@
|
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
|
-
|
896
|
+
write_space
|
894
897
|
indent(next_indent) do
|
895
|
-
write_indent
|
896
898
|
visit(value)
|
897
899
|
end
|
898
900
|
else
|
899
|
-
|
900
|
-
|
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
|
-
|
2043
|
-
indent(
|
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
|
-
|
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
|
-
|
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
|
-
|
2914
|
-
|
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
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.
|
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", "~>
|
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", "~>
|
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.
|
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.
|
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:
|
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:
|
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:
|
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: '
|
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: '
|
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.
|
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:
|
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.
|
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.
|
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: []
|