Class: Audition::Rewriters::WriteOnce::Variables

Inherits:
Prism::Visitor
  • Object
show all
Defined in:
lib/audition/rewriters.rb

Overview

Collects either global or class variable operations. Globals group process-wide; class variables group per namespace so a name reused in two classes never merges. assignable marks writes at a scope where a constant assignment would be legal (no surrounding def or block).

Constant Summary collapse

SKIP_GLOBALS =
(
  Static::Checks::GlobalVariables::SAFE_READS +
  Static::Checks::GlobalVariables::SAFE_WRITES +
  Static::Checks::GlobalVariables::LOAD_PATH_GLOBALS
).freeze
GVAR_NODES =
{
  visit_global_variable_read_node: :read,
  visit_global_variable_write_node: :write,
  visit_global_variable_operator_write_node: :other,
  visit_global_variable_or_write_node: :other,
  visit_global_variable_and_write_node: :other,
  visit_global_variable_target_node: :other
}.freeze
CVAR_NODES =
{
  visit_class_variable_read_node: :read,
  visit_class_variable_write_node: :write,
  visit_class_variable_operator_write_node: :other,
  visit_class_variable_or_write_node: :other,
  visit_class_variable_and_write_node: :other,
  visit_class_variable_target_node: :other
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mode) ⇒ Variables

Returns a new instance of Variables.



910
911
912
913
914
915
916
917
918
919
920
921
# File 'lib/audition/rewriters.rb', line 910

def initialize(mode)
  @mode = mode
  @groups = Hash.new { |h, k| h[k] = [] }
  @taken_constants = []
  @receiver_reads = {}
  @escaping_reads = {}
  @namespace = []
  @def_depth = 0
  @block_depth = 0
  @conditional_depth = 0
  super()
end

Instance Attribute Details

#escaping_readsObject (readonly)

Returns the value of attribute escaping_reads.



907
908
909
# File 'lib/audition/rewriters.rb', line 907

def escaping_reads
  @escaping_reads
end

#groupsObject (readonly)

Returns the value of attribute groups.



907
908
909
# File 'lib/audition/rewriters.rb', line 907

def groups
  @groups
end

#receiver_readsObject (readonly)

Returns the value of attribute receiver_reads.



907
908
909
# File 'lib/audition/rewriters.rb', line 907

def receiver_reads
  @receiver_reads
end

#taken_constantsObject (readonly)

Returns the value of attribute taken_constants.



907
908
909
# File 'lib/audition/rewriters.rb', line 907

def taken_constants
  @taken_constants
end

Instance Method Details

#conditionallyObject



970
971
972
973
974
975
# File 'lib/audition/rewriters.rb', line 970

def conditionally
  @conditional_depth += 1
  yield
ensure
  @conditional_depth -= 1
end

#visit_begin_node(node) ⇒ Object



977
978
979
980
981
982
983
984
985
986
987
988
# File 'lib/audition/rewriters.rb', line 977

def visit_begin_node(node)
  if node.rescue_clause
    @conditional_depth += 1
    begin
      super
    ensure
      @conditional_depth -= 1
    end
  else
    super
  end
end

#visit_block_node(node) ⇒ Object



1011
1012
1013
1014
1015
1016
# File 'lib/audition/rewriters.rb', line 1011

def visit_block_node(node)
  @block_depth += 1
  super
ensure
  @block_depth -= 1
end

#visit_call_node(node) ⇒ Object



923
924
925
926
927
928
929
930
931
932
# File 'lib/audition/rewriters.rb', line 923

def visit_call_node(node)
  receiver = node.receiver
  if receiver.is_a?(Prism::GlobalVariableReadNode) ||
      receiver.is_a?(Prism::ClassVariableReadNode)
    @receiver_reads[receiver.object_id] = true
  end
  arguments = node.arguments&.arguments || []
  arguments.each { |argument| mark_escape(argument) }
  super
end

#visit_class_node(node) ⇒ Object



990
991
992
993
994
995
# File 'lib/audition/rewriters.rb', line 990

def visit_class_node(node)
  @namespace.push(node.constant_path.location.slice)
  super
ensure
  @namespace.pop
end

#visit_constant_read_node(node) ⇒ Object



1030
1031
1032
1033
# File 'lib/audition/rewriters.rb', line 1030

def visit_constant_read_node(node)
  @taken_constants << node.name.to_s
  super
end

#visit_constant_write_node(node) ⇒ Object



1025
1026
1027
1028
# File 'lib/audition/rewriters.rb', line 1025

def visit_constant_write_node(node)
  @taken_constants << node.name.to_s
  super
end

#visit_def_node(node) ⇒ Object



1004
1005
1006
1007
1008
1009
# File 'lib/audition/rewriters.rb', line 1004

def visit_def_node(node)
  @def_depth += 1
  super
ensure
  @def_depth -= 1
end

#visit_lambda_node(node) ⇒ Object



1018
1019
1020
1021
1022
1023
# File 'lib/audition/rewriters.rb', line 1018

def visit_lambda_node(node)
  @block_depth += 1
  super
ensure
  @block_depth -= 1
end

#visit_module_node(node) ⇒ Object



997
998
999
1000
1001
1002
# File 'lib/audition/rewriters.rb', line 997

def visit_module_node(node)
  @namespace.push(node.constant_path.location.slice)
  super
ensure
  @namespace.pop
end