Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace SemanticBlocks with custom BlockDelimiters #263

Merged
merged 1 commit into from
Mar 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## unreleased changes

* Relax multi-line block rules, moving away from enforcing semantic blocks to
instead allowing code to adhere to whatever multi-line format the author deems
best

## 0.13.0

* Update rubocop from 1.7.0 to [1.10.0](https://github.com/rubocop-hq/rubocop/releases/tag/v1.10.0) enabling:
Expand All @@ -12,7 +18,7 @@
* Update rubocop from 1.7.0 to [1.8.1](https://github.com/rubocop-hq/rubocop/releases/tag/v1.8.1)
* Enabled [`Style/SlicingWithRange`](https://github.com/testdouble/standard/issues/175)

## 0.11.0
## 0.11.0

* Update rubocop-performance from 1.9.1 to [1.9.2](https://github.com/rubocop-hq/rubocop-performance/releases/tag/v1.9.2)
* Update rubocop from 1.4.2 to [1.7.0](https://github.com/rubocop-hq/rubocop/releases/tag/v1.7.0)
Expand Down
2 changes: 1 addition & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Copyright (c) 2019 Test Double, LLC

Portions of these files Copyright (c) 2012-18 Bozhidar Batsov:
- config/base.yml
- lib/standard/cop/semantic_blocks.rb
- lib/standard/cop/block_delimiters.rb
- test/cop_invoker.rb

Permission is hereby granted, free of charge, to any person obtaining
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ flag.
you'll need interpolation in a string slows people down
- **1.9 hash syntax** - When all the keys in a hash literal are symbols,
Standard enforces Ruby 1.9's `{hash: syntax}`
- **Semantic blocks** - `{`/`}` for functional blocks that return a value, and
`do`/`end` for procedural blocks that have side effects. More
[here](http://www.virtuouscode.com/2011/07/26/the-procedurefunction-block-convention-in-ruby/)
and [here](https://github.com/rubocop-hq/ruby-style-guide/issues/162)
- **Braces for single-line blocks** - Require `{`/`}` for one-line blocks, but
allow either braces or `do`/`end` for multiline blocks. Like using `do`/`end`
for multiline blocks? Prefer `{`/`}` when chaining? A fan of expressing intent
with Jim Weirich's [semantic
block](http://www.virtuouscode.com/2011/07/26/the-procedurefunction-block-convention-in-ruby/)
approach? Standard lets you do you!
- **Leading dots on multi-line method chains** - chosen for
[these](https://github.com/testdouble/standard/issues/75) reasons.
- **Spaces inside blocks, but not hash literals** - In Ruby, the `{` and `}`
Expand Down
35 changes: 2 additions & 33 deletions config/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -738,39 +738,8 @@ Security/YAMLLoad:
Enabled: true
SafeAutoCorrect: false

Standard/SemanticBlocks:
ProceduralMethods:
- benchmark
- bm
- bmbm
- tap
# Enumerable
- cycle
- each
- each_cons
- each_entry
- each_slice
- each_with_index
# Rails
- transaction
FunctionalMethods:
- given
- given!
- let
- let!
- subject
- watch
- Given
- Given!
- Invariant
- Then
- And
IgnoredMethods:
- lambda
- proc
- describe
- it
- When
Standard/BlockDelimiters:
Enabled: true

Style/Alias:
Enabled: true
Expand Down
2 changes: 1 addition & 1 deletion lib/standard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
require "standard/railtie" if defined?(Rails) && defined?(Rails::Railtie)

require "standard/formatter"
require "standard/cop/semantic_blocks"
require "standard/cop/block_delimiters"

module Standard
end
96 changes: 96 additions & 0 deletions lib/standard/cop/block_delimiters.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
module RuboCop::Cop
module Standard
# Check for uses of braces around single line blocks, but allows either
# braces or do/end for multi-line blocks.
#
# @example
# # bad - single line block
# items.each do |item| item / 5 end
#
# # good - single line block
# items.each { |item| item / 5 }
#
class BlockDelimiters < RuboCop::Cop::Base
extend RuboCop::Cop::AutoCorrector

def on_send(node)
return unless node.arguments?
return if node.parenthesized?
return if node.operator_method? || node.assignment_method?

node.arguments.each do |arg|
get_blocks(arg) do |block|
# If there are no parentheses around the arguments, then braces
# and do-end have different meaning due to how they bind, so we
# allow either.
ignore_node(block)
end
end
end

def on_block(node)
return if ignored_node?(node)
return if proper_block_style?(node)

message = message(node)
add_offense(node.loc.begin, message: message) do |corrector|
autocorrect(corrector, node)
end
end

private

def get_blocks(node, &block)
case node.type
when :block
yield node
when :send
get_blocks(node.receiver, &block) if node.receiver
when :hash
# A hash which is passed as method argument may have no braces
# In that case, one of the K/V pairs could contain a block node
# which could change in meaning if do...end replaced {...}
return if node.braces?

node.each_child_node { |child| get_blocks(child, &block) }
when :pair
node.each_child_node { |child| get_blocks(child, &block) }
end
end

def proper_block_style?(node)
node.multiline? || node.braces?
end

def message(node)
"Prefer `{...}` over `do...end` for single-line blocks."
end

def autocorrect(corrector, node)
return if correction_would_break_code?(node)

replace_do_end_with_braces(corrector, node.loc)
end

def correction_would_break_code?(node)
return unless node.keywords?

node.send_node.arguments? && !node.send_node.parenthesized?
end

def replace_do_end_with_braces(corrector, loc)
b = loc.begin
e = loc.end

corrector.insert_after(b, " ") unless whitespace_after?(b, 2)

corrector.replace(b, "{")
corrector.replace(e, "}")
end

def whitespace_after?(range, length = 1)
/\s/.match?(range.source_buffer.source[range.begin_pos + length, 1])
end
end
end
end
165 changes: 0 additions & 165 deletions lib/standard/cop/semantic_blocks.rb

This file was deleted.

12 changes: 6 additions & 6 deletions test/fixture/cli/autocorrectable-good.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,29 @@ def do_stuff(a:, b:, c:)
5 +
6

plus_stuff = STUFF.map { |e|
plus_stuff = STUFF.map do |e|
e + 1 + maths_and_stuff
}
end

STUFF.tap { |arr| arr.delete(0) }

STUFF.each { |e| e.succ }

THINGS.tap do |things|
THINGS.tap { |things|
if THINGS.is_a?(Hash)
42 + 8
end
end
}

test = "hi"
test2 = "hi"
test3 = test.equal?(test2)
if test3
32 + 3
end
THINGS.keys.each do |key|
THINGS.keys.each { |key|
THINGS[key] = plus_stuff[i]
end
}
end

def do_even_more_stuff
Expand Down
Loading