From 076c11b69ba81328cae08593afc625d56e5aec34 Mon Sep 17 00:00:00 2001 From: Marc-Andre Lafortune Date: Fri, 24 Jul 2020 15:17:31 -0400 Subject: [PATCH] NodePattern: Allow comments --- CHANGELOG.md | 1 + docs/modules/ROOT/pages/node_pattern.adoc | 16 ++++++++++++++++ lib/rubocop/ast/node_pattern.rb | 5 ++++- spec/rubocop/ast/node_pattern_spec.rb | 8 ++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89afa6b7d..919cf8f4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [#70](https://github.com/rubocop-hq/rubocop-ast/pull/70): Add `NextNode` ([@marcandre][]) * [#85](https://github.com/rubocop-hq/rubocop-ast/pull/85): Add `IntNode#value` and `FloatNode#value`. ([@fatkodima][]) +* [#82](https://github.com/rubocop-hq/rubocop-ast/pull/82): `NodePattern`: Allow comments ([@marcandre][]) ### Bug fixes diff --git a/docs/modules/ROOT/pages/node_pattern.adoc b/docs/modules/ROOT/pages/node_pattern.adoc index f57fa3f67..3c389ac42 100644 --- a/docs/modules/ROOT/pages/node_pattern.adoc +++ b/docs/modules/ROOT/pages/node_pattern.adoc @@ -477,6 +477,22 @@ def_node_matcher :interesting_call?, '(send _ %SOME_CALLS ...)' Constants as arguments to custom methods are also supported. +== Comments + +You may have comments in node patterns at the end of lines +by preceeding them with `'# '`: + +[source,ruby] +---- +def_node_matcher :complex_stuff, <<~PATTERN + (send + {#global_const?(:Kernel) nil?} # check for explicit call like Kernel.p too + {:p :pp} # let's consider `pp` also + $... # capture all arguments + ) +PATTERN +---- + == `nil` or `nil?` Take a special attention to nil behavior: diff --git a/lib/rubocop/ast/node_pattern.rb b/lib/rubocop/ast/node_pattern.rb index a2dd33f38..61c3b8cf0 100644 --- a/lib/rubocop/ast/node_pattern.rb +++ b/lib/rubocop/ast/node_pattern.rb @@ -99,6 +99,7 @@ module AST # # These arguments can be patterns themselves, in # # which case a matcher responding to === will be # # passed. + # '# comment' # comments are accepted at the end of lines # # You can nest arbitrarily deep: # @@ -122,6 +123,8 @@ class NodePattern class Compiler SYMBOL = %r{:(?:[\w+@*/?!<>=~|%^-]+|\[\]=?)}.freeze IDENTIFIER = /[a-zA-Z_][a-zA-Z0-9_-]*/.freeze + COMMENT = /#\s.*$/.freeze + META = Regexp.union( %w"( ) { } [ ] $< < > $... $ ! ^ ` ... + * ?" ).freeze @@ -788,7 +791,7 @@ def substitute_cur_node(code, cur_node, first_cur_node: cur_node) end def self.tokens(pattern) - pattern.scan(TOKEN).grep_v(ONLY_SEPARATOR) + pattern.gsub(COMMENT, '').scan(TOKEN).grep_v(ONLY_SEPARATOR) end # This method minimizes the closure for our method diff --git a/spec/rubocop/ast/node_pattern_spec.rb b/spec/rubocop/ast/node_pattern_spec.rb index 4dabb1dc1..791836ee1 100644 --- a/spec/rubocop/ast/node_pattern_spec.rb +++ b/spec/rubocop/ast/node_pattern_spec.rb @@ -1889,6 +1889,14 @@ def withargs(foo, bar, qux) end end + describe 'comments' do + let(:pattern) { "(int # We want an int\n$_) # Let's capture the value" } + let(:ruby) { '42' } + let(:captured_val) { 42 } + + it_behaves_like 'single capture' + end + describe '.descend' do let(:ruby) { '[[1, 2], 3]' }