forked from rubocop/rubocop
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
AndNode
and OrNode
node extensions
This change adds node extensions for `and`- and `or` nodes. It allows these nodes to describe themselves from any point within the AST.
- Loading branch information
Showing
11 changed files
with
449 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module AST | ||
# A node extension for `until` nodes. This will be used in place of a plain | ||
# node when the builder constructs the AST, making its methods available | ||
# to all `until` nodes within RuboCop. | ||
class AndNode < Node | ||
include BinaryOperatorNode | ||
include PredicateOperatorNode | ||
|
||
# Returns the alternate operator of the `and` as a string. | ||
# Returns `and` for `&&` and vice versa. | ||
# | ||
# @return [String] the alternate of the `and` operator | ||
def alternate_operator | ||
logical_operator? ? SEMANTIC_AND : LOGICAL_AND | ||
end | ||
|
||
# Returns the inverse keyword of the `and` node as a string. | ||
# Returns `||` for `&&` and `or` for `and`. | ||
# | ||
# @return [String] the inverse of the `and` operator | ||
def inverse_operator | ||
logical_operator? ? LOGICAL_OR : SEMANTIC_OR | ||
end | ||
|
||
# Custom destructuring method. This can be used to normalize | ||
# destructuring for different variations of the node. | ||
# | ||
# @return [Array<Node>] the different parts of the `and` predicate | ||
def node_parts | ||
[*self] | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module AST | ||
# Common functionality for nodes that are binary operations: | ||
# `or`, `and` ... | ||
module BinaryOperatorNode | ||
# Returns the left hand side node of the binary operation. | ||
# | ||
# @return [Node] the left hand side of the binary operation | ||
def lhs | ||
node_parts[0] | ||
end | ||
|
||
# Returns the right hand side node of the binary operation. | ||
# | ||
# @return [Node] the right hand side of the binary operation | ||
def rhs | ||
node_parts[1] | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module AST | ||
# Common functionality for nodes that are predicates: | ||
# `or`, `and` ... | ||
module PredicateOperatorNode | ||
LOGICAL_AND = '&&'.freeze | ||
SEMANTIC_AND = 'and'.freeze | ||
LOGICAL_OR = '||'.freeze | ||
SEMANTIC_OR = 'or'.freeze | ||
|
||
# Returns the operator as a string. | ||
# | ||
# @return [String] the operator | ||
def operator | ||
loc.operator.source | ||
end | ||
|
||
# Checks whether this is a logical operator. | ||
# | ||
# @return [Boolean] whether this is a logical operator | ||
def logical_operator? | ||
operator == LOGICAL_AND || operator == LOGICAL_OR | ||
end | ||
|
||
# Checks whether this is a semantic operator. | ||
# | ||
# @return [Boolean] whether this is a semantic operator | ||
def semantic_operator? | ||
operator == SEMANTIC_AND || operator == SEMANTIC_OR | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module AST | ||
# A node extension for `or` nodes. This will be used in place of a plain | ||
# node when the builder constructs the AST, making its methods available | ||
# to all `or` nodes within RuboCop. | ||
class OrNode < Node | ||
include BinaryOperatorNode | ||
include PredicateOperatorNode | ||
|
||
# Returns the alternate operator of the `or` as a string. | ||
# Returns `or` for `||` and vice versa. | ||
# | ||
# @return [String] the alternate of the `or` operator | ||
def alternate_operator | ||
logical_operator? ? SEMANTIC_OR : LOGICAL_OR | ||
end | ||
|
||
# Returns the inverse keyword of the `or` node as a string. | ||
# Returns `and` for `or` and `&&` for `||`. | ||
# | ||
# @return [String] the inverse of the `or` operator | ||
def inverse_operator | ||
logical_operator? ? LOGICAL_AND : SEMANTIC_AND | ||
end | ||
|
||
# Custom destructuring method. This can be used to normalize | ||
# destructuring for different variations of the node. | ||
# | ||
# @return [Array<Node>] the different parts of the `or` predicate | ||
def node_parts | ||
[*self] | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
describe RuboCop::AST::AndNode do | ||
let(:and_node) { parse_source(source).ast } | ||
|
||
describe '.new' do | ||
context 'with a logical and node' do | ||
let(:source) do | ||
':foo && :bar' | ||
end | ||
|
||
it { expect(and_node).to be_a(described_class) } | ||
end | ||
|
||
context 'with a semantic and node' do | ||
let(:source) do | ||
':foo and :bar' | ||
end | ||
|
||
it { expect(and_node).to be_a(described_class) } | ||
end | ||
end | ||
|
||
describe '#logical_operator?' do | ||
context 'with a logical and node' do | ||
let(:source) do | ||
':foo && :bar' | ||
end | ||
|
||
it { expect(and_node).to be_logical_operator } | ||
end | ||
|
||
context 'with a semantic and node' do | ||
let(:source) do | ||
':foo and :bar' | ||
end | ||
|
||
it { expect(and_node).not_to be_logical_operator } | ||
end | ||
end | ||
|
||
describe '#semantic_operator?' do | ||
context 'with a logical and node' do | ||
let(:source) do | ||
':foo && :bar' | ||
end | ||
|
||
it { expect(and_node).not_to be_semantic_operator } | ||
end | ||
|
||
context 'with a semantic and node' do | ||
let(:source) do | ||
':foo and :bar' | ||
end | ||
|
||
it { expect(and_node).to be_semantic_operator } | ||
end | ||
end | ||
|
||
describe '#operator' do | ||
context 'with a logical and node' do | ||
let(:source) do | ||
':foo && :bar' | ||
end | ||
|
||
it { expect(and_node.operator).to eq('&&') } | ||
end | ||
|
||
context 'with a semantic and node' do | ||
let(:source) do | ||
':foo and :bar' | ||
end | ||
|
||
it { expect(and_node.operator).to eq('and') } | ||
end | ||
end | ||
|
||
describe '#alternate_operator' do | ||
context 'with a logical and node' do | ||
let(:source) do | ||
':foo && :bar' | ||
end | ||
|
||
it { expect(and_node.alternate_operator).to eq('and') } | ||
end | ||
|
||
context 'with a semantic and node' do | ||
let(:source) do | ||
':foo and :bar' | ||
end | ||
|
||
it { expect(and_node.alternate_operator).to eq('&&') } | ||
end | ||
end | ||
|
||
describe '#inverse_operator' do | ||
context 'with a logical and node' do | ||
let(:source) do | ||
':foo && :bar' | ||
end | ||
|
||
it { expect(and_node.inverse_operator).to eq('||') } | ||
end | ||
|
||
context 'with a semantic and node' do | ||
let(:source) do | ||
':foo and :bar' | ||
end | ||
|
||
it { expect(and_node.inverse_operator).to eq('or') } | ||
end | ||
end | ||
|
||
describe '#lhs' do | ||
context 'with a logical and node' do | ||
let(:source) do | ||
':foo && 42' | ||
end | ||
|
||
it { expect(and_node.lhs).to be_sym_type } | ||
end | ||
|
||
context 'with a semantic and node' do | ||
let(:source) do | ||
':foo and 42' | ||
end | ||
|
||
it { expect(and_node.lhs).to be_sym_type } | ||
end | ||
end | ||
|
||
describe '#rhs' do | ||
context 'with a logical and node' do | ||
let(:source) do | ||
':foo && 42' | ||
end | ||
|
||
it { expect(and_node.rhs).to be_int_type } | ||
end | ||
|
||
context 'with a semantic and node' do | ||
let(:source) do | ||
':foo and 42' | ||
end | ||
|
||
it { expect(and_node.rhs).to be_int_type } | ||
end | ||
end | ||
end |
Oops, something went wrong.