Class: Reek::Context::CodeContext
- Inherits:
-
Object
- Object
- Reek::Context::CodeContext
- Extended by:
- Forwardable
- Includes:
- Enumerable
- Defined in:
- lib/reek/context/code_context.rb
Overview
Superclass for all types of source code context. Each instance represents a code element of some kind, and each provides behaviour relevant to that code element. CodeContexts form a tree in the same way the code does, with each context holding a reference to a unique outer context.
Direct Known Subclasses
AttributeContext, MethodContext, ModuleContext, RootContext, SendContext
Instance Attribute Summary collapse
-
#children ⇒ Object
readonly
Returns the value of attribute children.
-
#exp ⇒ Object
readonly
Returns the value of attribute exp.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
-
#refs ⇒ Object
readonly
private
Returns the value of attribute refs.
-
#statement_counter ⇒ Object
readonly
Returns the value of attribute statement_counter.
Instance Method Summary collapse
-
#append_child_context(child) ⇒ Object
Register a context as a child context of this context.
- #apply_current_visibility(_current_visibility) ⇒ Object
- #config_for(detector_class) ⇒ Object
- #configuration_via_code_commment ⇒ Object private
-
#each { ... } ⇒ Enumerator
Iterate over ‘self` and child contexts.
- #full_comment ⇒ Object private
- #full_name ⇒ Object
-
#initialize(exp) ⇒ CodeContext
constructor
Initializes a new CodeContext.
- #instance_method? ⇒ Boolean
-
#local_nodes(type, ignored = []) { ... } ⇒ Object
Iterate over each AST node (see ‘Reek::AST::Node`) of a given type for the current expression.
- #matches?(candidates) ⇒ Boolean
- #number_of_statements ⇒ Object
- #parent_config_for(detector_class) ⇒ Object private
- #record_call_to(exp) ⇒ Object
- #record_use_of_self ⇒ Object
-
#register_with_parent(parent) ⇒ Object
Link the present context to its parent.
- #singleton_method? ⇒ Boolean
Constructor Details
#initialize(exp) ⇒ CodeContext
Initializes a new CodeContext.
29 30 31 32 33 34 |
# File 'lib/reek/context/code_context.rb', line 29 def initialize(exp) @exp = exp @children = [] @statement_counter = StatementCounter.new @refs = AST::ObjectRefs.new end |
Instance Attribute Details
#children ⇒ Object (readonly)
Returns the value of attribute children.
24 25 26 |
# File 'lib/reek/context/code_context.rb', line 24 def children @children end |
#exp ⇒ Object (readonly)
Returns the value of attribute exp.
24 25 26 |
# File 'lib/reek/context/code_context.rb', line 24 def exp @exp end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
24 25 26 |
# File 'lib/reek/context/code_context.rb', line 24 def parent @parent end |
#refs ⇒ Object (readonly, private)
Returns the value of attribute refs.
166 167 168 |
# File 'lib/reek/context/code_context.rb', line 166 def refs @refs end |
#statement_counter ⇒ Object (readonly)
Returns the value of attribute statement_counter.
24 25 26 |
# File 'lib/reek/context/code_context.rb', line 24 def statement_counter @statement_counter end |
Instance Method Details
#append_child_context(child) ⇒ Object
Register a context as a child context of this context. This is generally used by a child context to register itself with its parent.
108 109 110 111 |
# File 'lib/reek/context/code_context.rb', line 108 def append_child_context(child) children << child self end |
#apply_current_visibility(_current_visibility) ⇒ Object
160 161 162 |
# File 'lib/reek/context/code_context.rb', line 160 def apply_current_visibility(_current_visibility) # Nothing to do by default end |
#config_for(detector_class) ⇒ Object
143 144 145 146 |
# File 'lib/reek/context/code_context.rb', line 143 def config_for(detector_class) parent_config_for(detector_class).merge( configuration_via_code_commment[detector_class.smell_type] || {}) end |
#configuration_via_code_commment ⇒ Object (private)
168 169 170 171 172 |
# File 'lib/reek/context/code_context.rb', line 168 def configuration_via_code_commment @configuration_via_code_commment ||= CodeComment.new(comment: full_comment, line: exp.line, source: exp.source).config end |
#each { ... } ⇒ Enumerator
Iterate over ‘self` and child contexts. The main difference (among others) to `local_nodes` is that we are traversing `CodeContexts` here, not AST nodes (see `Reek::AST::Node`).
53 54 55 56 57 58 59 60 |
# File 'lib/reek/context/code_context.rb', line 53 def each(&block) return enum_for(:each) unless block yield self children.each do |child| child.each(&block) end end |
#full_comment ⇒ Object (private)
174 175 176 |
# File 'lib/reek/context/code_context.rb', line 174 def full_comment exp.full_comment || '' end |
#full_name ⇒ Object
139 140 141 |
# File 'lib/reek/context/code_context.rb', line 139 def full_name exp.full_name(parent ? parent.full_name : '') end |
#instance_method? ⇒ Boolean
156 157 158 |
# File 'lib/reek/context/code_context.rb', line 156 def instance_method? false end |
#local_nodes(type, ignored = []) { ... } ⇒ Object
Iterate over each AST node (see ‘Reek::AST::Node`) of a given type for the current expression.
41 42 43 44 |
# File 'lib/reek/context/code_context.rb', line 41 def local_nodes(type, ignored = [], &blk) ignored |= [:class, :module] exp.each_node(type, ignored, &blk) end |
#matches?(candidates) ⇒ Boolean
131 132 133 134 135 136 137 |
# File 'lib/reek/context/code_context.rb', line 131 def matches?(candidates) my_fq_name = full_name candidates.any? do |candidate| candidate = Regexp.quote(candidate) if candidate.is_a?(String) /#{candidate}/ =~ my_fq_name end end |
#number_of_statements ⇒ Object
148 149 150 |
# File 'lib/reek/context/code_context.rb', line 148 def number_of_statements statement_counter.value end |
#parent_config_for(detector_class) ⇒ Object (private)
178 179 180 |
# File 'lib/reek/context/code_context.rb', line 178 def parent_config_for(detector_class) parent ? parent.config_for(detector_class) : {} end |
#record_call_to(exp) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/reek/context/code_context.rb', line 115 def record_call_to(exp) receiver = exp.receiver type = receiver ? receiver.type : :self line = exp.line case type when :lvar, :lvasgn refs.record_reference(name: receiver.name, line: line) unless exp.object_creation_call? when :self refs.record_reference(name: :self, line: line) end end |
#record_use_of_self ⇒ Object
127 128 129 |
# File 'lib/reek/context/code_context.rb', line 127 def record_use_of_self refs.record_reference(name: :self) end |
#register_with_parent(parent) ⇒ Object
Link the present context to its parent.
For example, given the following code:
class Omg
def foo(x)
puts x
end
end
The Reek::ContextBuilder object first instantiates a RootContext, which has no parent.
Next, it instantiates a ModuleContext, with exp
looking like this:
(class
(const nil :Omg) nil
(def :foo
(args
(arg :x))
(send nil :puts
(lvar :x))))
It will then call #register_with_parent on the ModuleContext, passing in the parent RootContext.
Finally, Reek::ContextBuilder will instantiate a MethodContext. This time, exp
is:
(def :foo
(args
(arg :x))
(send nil :puts
(lvar :x)))
Then it will call #register_with_parent on the MethodContext, passing in the parent ModuleContext.
100 101 102 |
# File 'lib/reek/context/code_context.rb', line 100 def register_with_parent(parent) @parent = parent.append_child_context(self) if parent end |
#singleton_method? ⇒ Boolean
152 153 154 |
# File 'lib/reek/context/code_context.rb', line 152 def singleton_method? false end |