Class: JRuby::Lint::Checkers::NonAtomic

Inherits:
Object
  • Object
show all
Includes:
JRuby::Lint::Checker
Defined in:
lib/jruby/lint/checkers/nonatomic.rb

Constant Summary collapse

IVAR =
org::jruby::ast::InstVarNode
CVAR =
org::jruby::ast::ClassVarNode
OPERATORS =
[:+, :-, :/, :*, :&, :|, :^, :>>, :<<, :%, :**]

Instance Attribute Summary

Attributes included from JRuby::Lint::Checker

#collector

Instance Method Summary collapse

Methods included from JRuby::Lint::Checker

#grand_parent, included, loaded_checkers, #parent, #src_line

Instance Method Details

#add_finding(collector, node, name) ⇒ Object



64
65
66
# File 'lib/jruby/lint/checkers/nonatomic.rb', line 64

def add_finding(collector, node, name)
  collector.add_finding("Non-local operator assignment (#{name}) is not guaranteed to be atomic.", [:nonatomic, :warning], node.line+1)
end

#check_nonatomic(orig_node, risk_node, name = nil) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/jruby/lint/checkers/nonatomic.rb', line 52

def check_nonatomic(orig_node, risk_node, name=nil)
  case risk_node
  when org::jruby::ast::LocalVarNode,
       org::jruby::ast::DVarNode
    # ok...mostly-safe cases
    false
  else
    add_finding(collector, orig_node, name || risk_node.name)
    true
  end
end

#operator_op_assignment?(node, type) ⇒ Boolean

Returns:

  • (Boolean)


29
30
31
32
33
34
# File 'lib/jruby/lint/checkers/nonatomic.rb', line 29

def operator_op_assignment?(node, type)
  rhs = node.value_node
  rhs.kind_of?(org::jruby::ast::CallNode) &&
    OPERATORS.include?(rhs.name) &&
    rhs.receiver_node.kind_of?(type)
end

#visitClassVarAsgnNode(node) ⇒ Object



44
45
46
47
48
49
50
# File 'lib/jruby/lint/checkers/nonatomic.rb', line 44

def visitClassVarAsgnNode(node)
  if !@last && operator_op_assignment?(node, CVAR) ||
     @last && parent != @last
    check_nonatomic(node, node)
  end
  @last = nil
end

#visitInstAsgnNode(node) ⇒ Object



36
37
38
39
40
41
42
# File 'lib/jruby/lint/checkers/nonatomic.rb', line 36

def visitInstAsgnNode(node)
  if !@last && operator_op_assignment?(node, IVAR) ||
     @last && parent != @last
    check_nonatomic(node, node)
  end
  @last = nil
end

#visitOpAsgnAndNode(node) ⇒ Object



15
16
17
18
# File 'lib/jruby/lint/checkers/nonatomic.rb', line 15

def visitOpAsgnAndNode(node)
  @last = node
  check_nonatomic(node, node.first_node)
end

#visitOpAsgnNode(node) ⇒ Object



25
26
27
# File 'lib/jruby/lint/checkers/nonatomic.rb', line 25

def visitOpAsgnNode(node)
  check_nonatomic(node, node.receiver_node, node.variable_name)
end

#visitOpAsgnOrNode(node) ⇒ Object



10
11
12
13
# File 'lib/jruby/lint/checkers/nonatomic.rb', line 10

def visitOpAsgnOrNode(node)
  @last = node
  check_nonatomic(node, node.first_node)
end

#visitOpElementAsgnNode(node) ⇒ Object



20
21
22
23
# File 'lib/jruby/lint/checkers/nonatomic.rb', line 20

def visitOpElementAsgnNode(node)
  name = src_line(node.line).split(node.operator_name + '=', 2)[0].strip
  add_finding(collector, node, name)
end