rufo 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +23 -8
- data/.gitignore +1 -0
- data/CHANGELOG.md +18 -0
- data/bin/verify-sample-code +60 -0
- data/docs/settings.md +59 -0
- data/lib/rufo/command.rb +21 -16
- data/lib/rufo/dot_file.rb +2 -0
- data/lib/rufo/erb_formatter.rb +120 -0
- data/lib/rufo/file_finder.rb +31 -22
- data/lib/rufo/formatter.rb +16 -15
- data/lib/rufo/parser.rb +13 -0
- data/lib/rufo/settings.rb +4 -2
- data/lib/rufo/version.rb +1 -1
- data/lib/rufo.rb +10 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3bbc374be047a3b1a07b7f73dd004aa0629b07bdf70de0342041dabbebd16166
|
4
|
+
data.tar.gz: ac54fb2d1e593baa3207109d9cb40d4bef40ab9eb64db13be344fcfd64bdcfe2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bf1ada9dcd91f5565c519a90693f7b2e35b46b4075f7cb92e57a120539df196286fce17ab42427fd3b9937f97585093487309624b59415ee42dbd87259d3178
|
7
|
+
data.tar.gz: 40b9de53720d9ad2c1b09c44f4b5a88cd3bb69ad4ceef8034d78abdb940052f504fff1995df5eaada6d936ae418d96ba1a1c5c3d82745761f9a8f8cf45a8a4f0
|
data/.circleci/config.yml
CHANGED
@@ -15,18 +15,12 @@
|
|
15
15
|
# Restore bundle cache
|
16
16
|
- restore_cache:
|
17
17
|
keys:
|
18
|
-
- bundler-packages-{{ checksum "ruby-version-for-ci.txt" }}-{{ checksum "rufo.gemspec" }}
|
18
|
+
- bundler-packages-v2-{{ checksum "ruby-version-for-ci.txt" }}-{{ checksum "rufo.gemspec" }}-{{ checksum "bin/verify-sample-code" }}
|
19
19
|
|
20
20
|
- run:
|
21
21
|
name: Bundle Install
|
22
22
|
command: bundle check || bundle install
|
23
23
|
|
24
|
-
# Store bundle cache
|
25
|
-
- save_cache:
|
26
|
-
key: bundler-packages-{{ checksum "ruby-version-for-ci.txt" }}-{{ checksum "rufo.gemspec" }}
|
27
|
-
paths:
|
28
|
-
- vendor/bundle
|
29
|
-
- Gemfile.lock
|
30
24
|
- run:
|
31
25
|
name: Run rspec
|
32
26
|
command: |
|
@@ -43,6 +37,18 @@
|
|
43
37
|
command: |
|
44
38
|
bundle exec rake rufo:run
|
45
39
|
|
40
|
+
- run:
|
41
|
+
name: Verify rufo works against sample codebases
|
42
|
+
command: |
|
43
|
+
bin/verify-sample-code
|
44
|
+
|
45
|
+
# Store bundle cache
|
46
|
+
- save_cache:
|
47
|
+
key: bundler-packages-v2-{{ checksum "ruby-version-for-ci.txt" }}-{{ checksum "rufo.gemspec" }}-{{ checksum "bin/verify-sample-code" }}
|
48
|
+
paths:
|
49
|
+
- vendor/bundle
|
50
|
+
- Gemfile.lock
|
51
|
+
|
46
52
|
# Save test results for timing analysis
|
47
53
|
- store_test_results:
|
48
54
|
path: test_results
|
@@ -50,6 +56,14 @@
|
|
50
56
|
|
51
57
|
version: 2
|
52
58
|
jobs:
|
59
|
+
build-2-7-0:
|
60
|
+
<<: *dockerbuild
|
61
|
+
docker:
|
62
|
+
- image: circleci/ruby:2.7.0
|
63
|
+
environment:
|
64
|
+
BUNDLE_JOBS: "3"
|
65
|
+
BUNDLE_RETRY: "3"
|
66
|
+
BUNDLE_PATH: /home/circleci/project/vendor/bundle
|
53
67
|
build-2-6-3:
|
54
68
|
<<: *dockerbuild
|
55
69
|
docker:
|
@@ -57,7 +71,7 @@ jobs:
|
|
57
71
|
environment:
|
58
72
|
BUNDLE_JOBS: "3"
|
59
73
|
BUNDLE_RETRY: "3"
|
60
|
-
BUNDLE_PATH: vendor/bundle
|
74
|
+
BUNDLE_PATH: /home/circleci/project/vendor/bundle
|
61
75
|
build-2-6-1:
|
62
76
|
<<: *dockerbuild
|
63
77
|
docker:
|
@@ -86,6 +100,7 @@ workflows:
|
|
86
100
|
version: 2
|
87
101
|
test:
|
88
102
|
jobs:
|
103
|
+
- build-2-7-0
|
89
104
|
- build-2-6-3
|
90
105
|
- build-2-6-1
|
91
106
|
- build-2-5-3
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -12,6 +12,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
12
12
|
|
13
13
|
### Added
|
14
14
|
|
15
|
+
## [0.8.0] - 2020-01-02
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
- Handle endless ranges in ruby 2.6
|
19
|
+
- Handle empty string hash keys
|
20
|
+
|
21
|
+
### Changed
|
22
|
+
- Output detailed description of Syntax Error to log
|
23
|
+
- Removed newlines from start of files.
|
24
|
+
|
25
|
+
### Added
|
26
|
+
|
27
|
+
- Support for rackup files
|
28
|
+
- Settings for 'quote_style' to settings.md
|
29
|
+
- Add support for ERB files
|
30
|
+
- Add Ruby 2.7.0 to test runs on CI
|
31
|
+
- `includes` and `excludes` configuration options
|
32
|
+
|
15
33
|
## [0.7.0] - 2019-04-28
|
16
34
|
|
17
35
|
### Fixed
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
repos = {
|
4
|
+
"rspec/rspec-core" => {
|
5
|
+
"--exclude-pattern" => [
|
6
|
+
"spec/rspec/core/world_spec.rb",
|
7
|
+
"spec/rspec/core/formatters/exception_presenter_spec.rb",
|
8
|
+
"spec/rspec/core/formatters/snippet_extractor_spec.rb",
|
9
|
+
"spec/rspec/core/metadata_spec.rb",
|
10
|
+
"spec/rspec/core/formatters/html_formatter_spec.rb",
|
11
|
+
].join(","),
|
12
|
+
},
|
13
|
+
}
|
14
|
+
|
15
|
+
def run_command(cmd, allowed_statuses: [0])
|
16
|
+
puts "Running: #{cmd.inspect}"
|
17
|
+
system(cmd)
|
18
|
+
unless allowed_statuses.include?($?.exitstatus)
|
19
|
+
$stderr.puts "Command failed, aborting!"
|
20
|
+
exit 1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def clone_repo(repo)
|
25
|
+
run_command(
|
26
|
+
"git clone --depth=1 'https://github.com/#{repo}' sample_code/#{repo}"
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup_repo(repo)
|
31
|
+
run_command("cd sample_code/#{repo} && bundle")
|
32
|
+
end
|
33
|
+
|
34
|
+
def run_rspec(repo, flags)
|
35
|
+
str_flags = flags.to_a.join(" ")
|
36
|
+
run_command("cd sample_code/#{repo} && bundle exec rspec #{str_flags}")
|
37
|
+
end
|
38
|
+
|
39
|
+
def pre_format_checks(repo, rspec_flags)
|
40
|
+
run_rspec(repo, rspec_flags)
|
41
|
+
end
|
42
|
+
|
43
|
+
def format_repo(repo)
|
44
|
+
run_command(
|
45
|
+
"bundle exec rake rufo:run sample_code/#{repo}",
|
46
|
+
allowed_statuses: [0, 1, 3],
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def post_format_checks(repo, rspec_flags)
|
51
|
+
run_rspec(repo, rspec_flags)
|
52
|
+
end
|
53
|
+
|
54
|
+
repos.each do |repo, rspec_flags|
|
55
|
+
clone_repo(repo)
|
56
|
+
setup_repo(repo)
|
57
|
+
pre_format_checks(repo, rspec_flags)
|
58
|
+
format_repo(repo)
|
59
|
+
post_format_checks(repo, rspec_flags)
|
60
|
+
end
|
data/docs/settings.md
CHANGED
@@ -22,6 +22,7 @@ See https://github.com/ruby-formatter/rufo/issues/2 for more context!
|
|
22
22
|
- [align_chained_calls](#align_chained_calls)
|
23
23
|
- [parens_in_def](#parens_in_def)
|
24
24
|
- [trailing_commas](#trailing_commas)
|
25
|
+
- [quote_style](#quote_style)
|
25
26
|
|
26
27
|
### align_case_when
|
27
28
|
|
@@ -184,6 +185,7 @@ foo(
|
|
184
185
|
y: 2,
|
185
186
|
)
|
186
187
|
```
|
188
|
+
|
187
189
|
With `:never`, the formatter will change it to:
|
188
190
|
|
189
191
|
```ruby
|
@@ -217,3 +219,60 @@ foo(
|
|
217
219
|
y: 2
|
218
220
|
)
|
219
221
|
```
|
222
|
+
|
223
|
+
### quote_style
|
224
|
+
|
225
|
+
Use the specified quotation marks.
|
226
|
+
|
227
|
+
- `:double`: (default) use doublequotations unless one or more escaped double-quotations are included
|
228
|
+
- `:single`: use single quotations unless one or more interpolations `#{}` or escaped single quotations are included
|
229
|
+
|
230
|
+
This does not affect `%q()` (single), `%Q()` (double), or quotation marks within heredocs.
|
231
|
+
|
232
|
+
Given this code:
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
'a great string'
|
236
|
+
|
237
|
+
'import \"quotes\"'
|
238
|
+
"import \'quotes\'"
|
239
|
+
"#{interpolation}"
|
240
|
+
%q(single quoted)
|
241
|
+
%Q(double quoted)
|
242
|
+
code = <<CODE
|
243
|
+
"double"
|
244
|
+
'single'
|
245
|
+
CODE
|
246
|
+
```
|
247
|
+
|
248
|
+
With `:double`, the formatter will change the first line to:
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
"a great string"
|
252
|
+
|
253
|
+
'import \"quotes\"'
|
254
|
+
"import \'quotes\'"
|
255
|
+
"#{interpolation}"
|
256
|
+
%q(single quoted)
|
257
|
+
%Q(double quoted)
|
258
|
+
code = <<CODE
|
259
|
+
"double"
|
260
|
+
'single'
|
261
|
+
CODE
|
262
|
+
```
|
263
|
+
|
264
|
+
With `:single`, the formatter will change the first line just above to:
|
265
|
+
|
266
|
+
```ruby
|
267
|
+
'a great string'
|
268
|
+
|
269
|
+
'import \"quotes\"'
|
270
|
+
"import \'quotes\'"
|
271
|
+
"#{interpolation}"
|
272
|
+
%q(single quoted)
|
273
|
+
%Q(double quoted)
|
274
|
+
code = <<CODE
|
275
|
+
"double"
|
276
|
+
'single'
|
277
|
+
CODE
|
278
|
+
```
|
data/lib/rufo/command.rb
CHANGED
@@ -17,7 +17,6 @@ class Rufo::Command
|
|
17
17
|
@exit_code = exit_code
|
18
18
|
@filename_for_dot_rufo = filename_for_dot_rufo
|
19
19
|
@dot_file = Rufo::DotFile.new
|
20
|
-
@squiggly_warning_files = []
|
21
20
|
@logger = Rufo::Logger.new(loglevel)
|
22
21
|
end
|
23
22
|
|
@@ -51,8 +50,8 @@ class Rufo::Command
|
|
51
50
|
print(result) if !@want_check
|
52
51
|
|
53
52
|
code == result ? CODE_OK : CODE_CHANGE
|
54
|
-
rescue Rufo::SyntaxError
|
55
|
-
logger.error("
|
53
|
+
rescue Rufo::SyntaxError => e
|
54
|
+
logger.error("STDIN is invalid code. Error on line:#{e.lineno} #{e.message}")
|
56
55
|
CODE_ERROR
|
57
56
|
rescue => ex
|
58
57
|
logger.error("You've found a bug!")
|
@@ -61,7 +60,11 @@ class Rufo::Command
|
|
61
60
|
end
|
62
61
|
|
63
62
|
def format_args(args)
|
64
|
-
|
63
|
+
top_level_dot_file = @filename_for_dot_rufo || Dir.getwd
|
64
|
+
options = @dot_file.get_config_in(top_level_dot_file) || {}
|
65
|
+
file_finder = Rufo::FileFinder.new(
|
66
|
+
args, includes: options[:includes], excludes: options[:excludes],
|
67
|
+
)
|
65
68
|
files = file_finder.to_a
|
66
69
|
|
67
70
|
changed = false
|
@@ -95,11 +98,13 @@ class Rufo::Command
|
|
95
98
|
code = File.read(filename)
|
96
99
|
|
97
100
|
begin
|
98
|
-
|
99
|
-
|
101
|
+
location = @filename_for_dot_rufo || File.dirname(filename)
|
102
|
+
erb = filename.end_with?(".erb")
|
103
|
+
result = format(code, location, erb: erb)
|
104
|
+
rescue Rufo::SyntaxError => e
|
100
105
|
# We ignore syntax errors as these might be template files
|
101
106
|
# with .rb extension
|
102
|
-
logger.warn("
|
107
|
+
logger.warn("#{filename}:#{e.lineno} #{e.message}")
|
103
108
|
return CODE_ERROR
|
104
109
|
end
|
105
110
|
|
@@ -113,8 +118,8 @@ class Rufo::Command
|
|
113
118
|
|
114
119
|
return CODE_CHANGE
|
115
120
|
end
|
116
|
-
rescue Rufo::SyntaxError
|
117
|
-
logger.error("
|
121
|
+
rescue Rufo::SyntaxError => e
|
122
|
+
logger.error("#{filename}:#{e.lineno} #{e.message}")
|
118
123
|
CODE_ERROR
|
119
124
|
rescue => ex
|
120
125
|
logger.error("You've found a bug!")
|
@@ -123,14 +128,14 @@ class Rufo::Command
|
|
123
128
|
raise ex
|
124
129
|
end
|
125
130
|
|
126
|
-
def format(code, dir)
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
formatter.init_settings(options)
|
131
|
+
def format(code, dir, erb: false)
|
132
|
+
options = @dot_file.get_config_in(dir) || {}
|
133
|
+
if erb
|
134
|
+
formatter = Rufo::ErbFormatter.new(code, **options)
|
135
|
+
else
|
136
|
+
formatter = Rufo::Formatter.new(code, **options)
|
133
137
|
end
|
138
|
+
|
134
139
|
formatter.format
|
135
140
|
result = formatter.result
|
136
141
|
result
|
data/lib/rufo/dot_file.rb
CHANGED
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "erb"
|
3
|
+
|
4
|
+
class Rufo::ErbFormatter
|
5
|
+
def self.format(code, **options)
|
6
|
+
new(code, **options).format
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :result
|
10
|
+
|
11
|
+
def initialize(code, **options)
|
12
|
+
compiler = ERB::Compiler.new("<>")
|
13
|
+
@options = options
|
14
|
+
@scanner = compiler.make_scanner(code)
|
15
|
+
@code_mode = false
|
16
|
+
@current_lineno = 0
|
17
|
+
@current_column = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def format
|
21
|
+
out = []
|
22
|
+
process_erb do |(type, content)|
|
23
|
+
if type == :code
|
24
|
+
formatted_code = process_code(content)
|
25
|
+
indented_code = formatted_code.lines.join(" " * current_column)
|
26
|
+
out << " #{indented_code} "
|
27
|
+
else
|
28
|
+
out << content
|
29
|
+
end
|
30
|
+
|
31
|
+
update_lineno(out.last)
|
32
|
+
update_column(out.last)
|
33
|
+
end
|
34
|
+
@result = out.join("")
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :scanner, :code_mode
|
40
|
+
attr_accessor :current_lineno, :current_column
|
41
|
+
|
42
|
+
def update_lineno(token)
|
43
|
+
lines = token.count("\n")
|
44
|
+
if lines > 0
|
45
|
+
self.current_lineno = current_lineno + lines
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def update_column(token)
|
50
|
+
last_newline_index = token.rindex("\n")
|
51
|
+
if last_newline_index == nil
|
52
|
+
self.current_column = current_column + token.length
|
53
|
+
else
|
54
|
+
self.current_column = token[last_newline_index..-1].length
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def process_erb
|
59
|
+
code = []
|
60
|
+
scanner.scan do |token|
|
61
|
+
if token.is_a?(String) && token.end_with?("%>")
|
62
|
+
disable_code_mode
|
63
|
+
yield [:code, code.join("")]
|
64
|
+
yield [:text, token]
|
65
|
+
code = []
|
66
|
+
elsif code_mode
|
67
|
+
code << token
|
68
|
+
elsif token == :cr
|
69
|
+
yield [:text, "\n"]
|
70
|
+
else
|
71
|
+
yield [:text, token]
|
72
|
+
end
|
73
|
+
|
74
|
+
enable_code_mode if token.is_a?(String) && token.start_with?("<%")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def process_code(code_str)
|
79
|
+
sexps = Ripper.sexp(code_str)
|
80
|
+
if sexps.nil?
|
81
|
+
prefix, suffix = determine_code_wrappers(code_str)
|
82
|
+
end
|
83
|
+
result = format_code("#{prefix} " + code_str + " #{suffix}")
|
84
|
+
unless suffix.nil?
|
85
|
+
result = result.chomp(suffix)
|
86
|
+
end
|
87
|
+
unless prefix.nil?
|
88
|
+
result = result.sub(prefix, "")
|
89
|
+
end
|
90
|
+
result.strip
|
91
|
+
end
|
92
|
+
|
93
|
+
def determine_code_wrappers(code_str)
|
94
|
+
return nil, "\nend" if Ripper.sexp("#{code_str}\nend")
|
95
|
+
return nil, "}" if Ripper.sexp("#{code_str} }")
|
96
|
+
return "{", nil if Ripper.sexp("{ #{code_str}")
|
97
|
+
return "begin", nil if Ripper.sexp("begin #{code_str}")
|
98
|
+
return "begin\n", "\nend" if Ripper.sexp("begin\n#{code_str}\nend")
|
99
|
+
return "if a\n", "\nend" if Ripper.sexp("if a\n#{code_str}\nend")
|
100
|
+
raise_syntax_error!(code_str)
|
101
|
+
end
|
102
|
+
|
103
|
+
def raise_syntax_error!(code_str)
|
104
|
+
format_code(code_str)
|
105
|
+
rescue Rufo::SyntaxError => e
|
106
|
+
raise Rufo::SyntaxError.new(e.message, current_lineno + e.lineno)
|
107
|
+
end
|
108
|
+
|
109
|
+
def format_code(str)
|
110
|
+
Rufo::Formatter.format(str).chomp
|
111
|
+
end
|
112
|
+
|
113
|
+
def enable_code_mode
|
114
|
+
@code_mode = true
|
115
|
+
end
|
116
|
+
|
117
|
+
def disable_code_mode
|
118
|
+
@code_mode = false
|
119
|
+
end
|
120
|
+
end
|
data/lib/rufo/file_finder.rb
CHANGED
@@ -1,34 +1,48 @@
|
|
1
1
|
require "find"
|
2
|
+
require "rake/file_list"
|
2
3
|
|
3
4
|
class Rufo::FileFinder
|
4
5
|
include Enumerable
|
5
6
|
|
6
7
|
# Taken from https://github.com/ruby/rake/blob/f0a897e3fb557f64f5da59785b1a4464826f77b2/lib/rake/application.rb#L41
|
7
8
|
RAKEFILES = [
|
8
|
-
"rakefile",
|
9
|
-
"Rakefile",
|
10
|
-
"rakefile.rb",
|
11
|
-
"Rakefile.rb",
|
9
|
+
"**/rakefile",
|
10
|
+
"**/Rakefile",
|
11
|
+
"**/rakefile.rb",
|
12
|
+
"**/Rakefile.rb",
|
12
13
|
]
|
13
14
|
|
14
15
|
FILENAMES = [
|
15
|
-
"Gemfile",
|
16
|
+
"**/Gemfile",
|
16
17
|
*RAKEFILES,
|
17
18
|
]
|
18
19
|
|
19
20
|
EXTENSIONS = [
|
20
|
-
"
|
21
|
-
"
|
22
|
-
"
|
23
|
-
"
|
21
|
+
"**/*.rb",
|
22
|
+
"**/*.gemspec",
|
23
|
+
"**/*.rake",
|
24
|
+
"**/*.ru",
|
25
|
+
"**/*.jbuilder",
|
26
|
+
"**/*.erb",
|
27
|
+
]
|
28
|
+
|
29
|
+
DEFAULT_PATTERNS = [
|
30
|
+
*FILENAMES,
|
31
|
+
*EXTENSIONS,
|
24
32
|
]
|
25
33
|
|
26
34
|
EXCLUDED_DIRS = [
|
27
35
|
"vendor",
|
28
36
|
]
|
29
37
|
|
30
|
-
|
38
|
+
EXCLUDE_PATTERNS = [
|
39
|
+
"vendor/**/*",
|
40
|
+
]
|
41
|
+
|
42
|
+
def initialize(files_or_dirs, includes: [], excludes: [])
|
31
43
|
@files_or_dirs = files_or_dirs
|
44
|
+
@includes = includes
|
45
|
+
@excludes = excludes
|
32
46
|
end
|
33
47
|
|
34
48
|
def each
|
@@ -43,20 +57,15 @@ class Rufo::FileFinder
|
|
43
57
|
|
44
58
|
private
|
45
59
|
|
46
|
-
attr_reader :files_or_dirs
|
60
|
+
attr_reader :files_or_dirs, :includes, :excludes
|
47
61
|
|
48
62
|
def all_rb_files(file_or_dir)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
if EXTENSIONS.include?(File.extname(basename)) || FILENAMES.include?(basename)
|
56
|
-
files << path
|
57
|
-
end
|
58
|
-
end
|
63
|
+
Dir.chdir(file_or_dir) do
|
64
|
+
fl = Rake::FileList.new(*DEFAULT_PATTERNS)
|
65
|
+
fl.exclude(*EXCLUDE_PATTERNS)
|
66
|
+
fl.exclude(*excludes)
|
67
|
+
fl.include(*includes)
|
68
|
+
fl.to_a
|
59
69
|
end
|
60
|
-
files
|
61
70
|
end
|
62
71
|
end
|
data/lib/rufo/formatter.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "ripper"
|
4
|
-
|
5
3
|
class Rufo::Formatter
|
6
4
|
include Rufo::Settings
|
7
5
|
|
8
6
|
INDENT_SIZE = 2
|
7
|
+
EMPTY_STRING = [:string_literal, [:string_content]]
|
8
|
+
EMPTY_HASH = [:hash, nil]
|
9
9
|
|
10
10
|
def self.format(code, **options)
|
11
11
|
formatter = new(code, **options)
|
@@ -15,12 +15,13 @@ class Rufo::Formatter
|
|
15
15
|
|
16
16
|
def initialize(code, **options)
|
17
17
|
@code = code
|
18
|
-
@tokens = Ripper.lex(code).reverse!
|
19
|
-
@sexp = Ripper.sexp(code)
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
@tokens = Rufo::Parser.lex(code).reverse!
|
20
|
+
@sexp = Rufo::Parser.sexp(code)
|
21
|
+
|
22
|
+
# sexp being nil means that the code is not valid.
|
23
|
+
# Parse the code so we get better error messages.
|
24
|
+
Rufo::Parser.parse(code) if @sexp.nil?
|
24
25
|
|
25
26
|
@indent = 0
|
26
27
|
@line = 0
|
@@ -179,6 +180,8 @@ class Rufo::Formatter
|
|
179
180
|
indent_literals
|
180
181
|
do_align_case_when if align_case_when
|
181
182
|
remove_lines_before_inline_declarations
|
183
|
+
@output.lstrip!
|
184
|
+
@output = "\n" if @output.empty?
|
182
185
|
end
|
183
186
|
|
184
187
|
def visit(node)
|
@@ -2378,7 +2381,7 @@ class Rufo::Formatter
|
|
2378
2381
|
skip_space_or_newline
|
2379
2382
|
consume_op(inclusive ? ".." : "...")
|
2380
2383
|
skip_space_or_newline
|
2381
|
-
visit right
|
2384
|
+
visit right unless right.nil?
|
2382
2385
|
end
|
2383
2386
|
|
2384
2387
|
def visit_regexp_literal(node)
|
@@ -3848,15 +3851,13 @@ class Rufo::Formatter
|
|
3848
3851
|
when :hash, :string_literal, :symbol_literal, :symbol, :vcall, :string_content, :assoc_splat, :var_ref
|
3849
3852
|
node_line(node[1], beginning: beginning)
|
3850
3853
|
when :assoc_new
|
3851
|
-
|
3854
|
+
# There's no line number info for empty strings or hashes.
|
3855
|
+
if node[1] != EMPTY_STRING && node[1] != EMPTY_HASH
|
3852
3856
|
node_line(node[1], beginning: beginning)
|
3857
|
+
elsif node.last != EMPTY_STRING && node.last != EMPTY_HASH
|
3858
|
+
node_line(node.last, beginning: beginning)
|
3853
3859
|
else
|
3854
|
-
|
3855
|
-
# there's no line number for [:string_literal, [:string_content]] or [:hash, nil]
|
3856
|
-
node_line(node[1], beginning: beginning)
|
3857
|
-
else
|
3858
|
-
node_line(node.last, beginning: beginning)
|
3859
|
-
end
|
3860
|
+
return
|
3860
3861
|
end
|
3861
3862
|
when :assoclist_from_args
|
3862
3863
|
node_line(beginning ? node[1][0] : node[1].last, beginning: beginning)
|
data/lib/rufo/parser.rb
ADDED
data/lib/rufo/settings.rb
CHANGED
@@ -5,15 +5,17 @@ module Rufo::Settings
|
|
5
5
|
align_chained_calls: [false, true],
|
6
6
|
trailing_commas: [true, false],
|
7
7
|
quote_style: [:double, :single],
|
8
|
+
includes: nil,
|
9
|
+
excludes: nil,
|
8
10
|
}
|
9
11
|
|
10
12
|
attr_accessor(*OPTIONS.keys)
|
11
13
|
|
12
14
|
def init_settings(options)
|
13
15
|
OPTIONS.each do |name, valid_options|
|
14
|
-
default = valid_options
|
16
|
+
default = valid_options&.first
|
15
17
|
value = options.fetch(name, default)
|
16
|
-
|
18
|
+
if !valid_options.nil? && !valid_options.include?(value)
|
17
19
|
$stderr.puts "Invalid value for #{name}: #{value.inspect}. Valid " \
|
18
20
|
"values are: #{valid_options.map(&:inspect).join(", ")}"
|
19
21
|
value = default
|
data/lib/rufo/version.rb
CHANGED
data/lib/rufo.rb
CHANGED
@@ -3,7 +3,14 @@
|
|
3
3
|
module Rufo
|
4
4
|
class Bug < StandardError; end
|
5
5
|
|
6
|
-
class SyntaxError < StandardError
|
6
|
+
class SyntaxError < StandardError
|
7
|
+
attr_reader :lineno
|
8
|
+
|
9
|
+
def initialize(message, lineno)
|
10
|
+
super(message)
|
11
|
+
@lineno = lineno
|
12
|
+
end
|
13
|
+
end
|
7
14
|
|
8
15
|
def self.format(code, **options)
|
9
16
|
Formatter.format(code, **options)
|
@@ -14,6 +21,8 @@ require_relative "rufo/command"
|
|
14
21
|
require_relative "rufo/logger"
|
15
22
|
require_relative "rufo/dot_file"
|
16
23
|
require_relative "rufo/settings"
|
24
|
+
require_relative "rufo/parser"
|
17
25
|
require_relative "rufo/formatter"
|
26
|
+
require_relative "rufo/erb_formatter"
|
18
27
|
require_relative "rufo/version"
|
19
28
|
require_relative "rufo/file_finder"
|
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.8.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:
|
11
|
+
date: 2020-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -130,6 +130,7 @@ files:
|
|
130
130
|
- Rakefile
|
131
131
|
- bin/console
|
132
132
|
- bin/setup
|
133
|
+
- bin/verify-sample-code
|
133
134
|
- docs/developing-rufo.md
|
134
135
|
- docs/releasing-a-gem.md
|
135
136
|
- docs/settings.md
|
@@ -137,9 +138,11 @@ files:
|
|
137
138
|
- lib/rufo.rb
|
138
139
|
- lib/rufo/command.rb
|
139
140
|
- lib/rufo/dot_file.rb
|
141
|
+
- lib/rufo/erb_formatter.rb
|
140
142
|
- lib/rufo/file_finder.rb
|
141
143
|
- lib/rufo/formatter.rb
|
142
144
|
- lib/rufo/logger.rb
|
145
|
+
- lib/rufo/parser.rb
|
143
146
|
- lib/rufo/settings.rb
|
144
147
|
- lib/rufo/version.rb
|
145
148
|
- rakelib/rufo.rake
|
@@ -163,7 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
166
|
- !ruby/object:Gem::Version
|
164
167
|
version: '0'
|
165
168
|
requirements: []
|
166
|
-
rubygems_version: 3.0.
|
169
|
+
rubygems_version: 3.0.3
|
167
170
|
signing_key:
|
168
171
|
specification_version: 4
|
169
172
|
summary: Ruby code formatter
|