Class: AppMap::Feature::Base
- Inherits:
-
FeatureStruct
- Object
- Struct
- FeatureStruct
- AppMap::Feature::Base
- Defined in:
- lib/appmap/feature.rb
Overview
Base is an abstract base class for features.
Instance Attribute Summary collapse
-
#children ⇒ Object
readonly
Returns the value of attribute children.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
Attributes inherited from FeatureStruct
Class Method Summary collapse
Instance Method Summary collapse
- #add_child(child) ⇒ Object
-
#collect_functions(accumulator = []) ⇒ Object
yield each function to a block.
-
#enclosing_type_name ⇒ Object
Gets an array containing the type names which enclose this feature.
-
#enclosing_type_name? ⇒ Boolean
true iff this feature has an enclosing type.
-
#include_option ⇒ Object
The ‘include’ attribute can indicate which elements of the parse subtree to automatically add as features.
-
#initialize(name, location, attributes) ⇒ Base
constructor
A new instance of Base.
-
#prune(parent = nil) ⇒ Object
Determines if this feature should be dropped from the feature tree.
- #prune? ⇒ Boolean
- #remove_child(child) ⇒ Object
-
#reparent(parent = nil, features_by_type = {}) ⇒ Object
Determines if this feature should be re-parented as a child of a different feature.
- #to_h ⇒ Object
- #to_json(*opts) ⇒ Object
- #type? ⇒ Boolean
- #valid? ⇒ Boolean
Constructor Details
#initialize(name, location, attributes) ⇒ Base
Returns a new instance of Base.
50 51 52 53 54 55 |
# File 'lib/appmap/feature.rb', line 50 def initialize(name, location, attributes) super(name, self.class.(location), attributes) @parent = nil @children = [] end |
Instance Attribute Details
#children ⇒ Object (readonly)
Returns the value of attribute children.
48 49 50 |
# File 'lib/appmap/feature.rb', line 48 def children @children end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
48 49 50 |
# File 'lib/appmap/feature.rb', line 48 def parent @parent end |
Class Method Details
.expand_path(location) ⇒ Object
42 43 44 45 |
# File 'lib/appmap/feature.rb', line 42 def (location) path, lineno = location.split(':') [ path, lineno ].compact.join(':') end |
Instance Method Details
#add_child(child) ⇒ Object
63 64 65 66 |
# File 'lib/appmap/feature.rb', line 63 def add_child(child) @children << child child.instance_variable_set('@parent', self) end |
#collect_functions(accumulator = []) ⇒ Object
yield each function to a block.
92 93 94 95 96 97 |
# File 'lib/appmap/feature.rb', line 92 def collect_functions(accumulator = []) accumulator.tap do |_| accumulator << self if is_a?(Function) children.each { |child| child.collect_functions(accumulator) } end end |
#enclosing_type_name ⇒ Object
Gets an array containing the type names which enclose this feature.
69 70 71 72 73 74 75 76 |
# File 'lib/appmap/feature.rb', line 69 def enclosing_type_name @enclosing_type_name ||= [].tap do |names| p = self while (p = p.parent) && p.type? names << p.name end end.reverse end |
#enclosing_type_name? ⇒ Boolean
true iff this feature has an enclosing type. An example of when this is false: when the parent of the feature is not a type (e.g. it’s a location).
80 81 82 |
# File 'lib/appmap/feature.rb', line 80 def enclosing_type_name? !enclosing_type_name.empty? end |
#include_option ⇒ Object
The ‘include’ attribute can indicate which elements of the parse subtree to automatically add as features. For example: public_classes, public_modules, public_methods.
87 88 89 |
# File 'lib/appmap/feature.rb', line 87 def include_option (attributes[:include] || '').split(',') end |
#prune(parent = nil) ⇒ Object
Determines if this feature should be dropped from the feature tree. A feature is dropped from the feature tree if it doesn’t add useful information for the user. Performing this operation removes feature nodes that don’t add anything useful to the user. For example, empty classes.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/appmap/feature.rb', line 125 def prune(parent = nil) should_prune = prune? && !parent.nil? parent = self unless should_prune children.dup.each do |child| child.prune(parent) end # Perform the prune in post-fix traversal order, otherwise the # features will get confused about whether they should prune or not. if should_prune parent.remove_child(self) children.each do |child| parent.add_child(child) end end end |
#prune? ⇒ Boolean
177 178 179 |
# File 'lib/appmap/feature.rb', line 177 def prune? false end |
#remove_child(child) ⇒ Object
57 58 59 60 61 |
# File 'lib/appmap/feature.rb', line 57 def remove_child(child) # TODO: Encountered this indexing appland with active_dispatch children.delete(child) or warn "Unable to remove #{name.inspect} from parent" # or raise "No such child : #{child}" child.instance_variable_set('@parent', nil) end |
#reparent(parent = nil, features_by_type = {}) ⇒ Object
Determines if this feature should be re-parented as a child of a different feature.
A feature is re-parented if the enclosing type of the feature has already been defined in the tree.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/appmap/feature.rb', line 147 def reparent(parent = nil, features_by_type = {}) # Determine if the enclosing type of the feature is defined. # Generally, it should be. existing_enclosing_type = features_by_type[enclosing_type_name] if enclosing_type_name? if existing_enclosing_type parent = existing_enclosing_type end # Determine if this feature is a type which is already defined. type_exists = true if type? && features_by_type.key?(type_name) # If this feature is a type that's already defined, skip over it and # add the children to the existing feature. Otherwise, clone this feature # under the parent and use the cloned object as the parent of the compacted # children. if type_exists features_by_type[type_name] else clone.tap do |f| parent.add_child(f) if parent features_by_type[type_name] = f if type? end end.tap do |updated_parent| children.each do |child| child.reparent(updated_parent, features_by_type) end end end |
#to_h ⇒ Object
111 112 113 114 115 116 117 118 119 |
# File 'lib/appmap/feature.rb', line 111 def to_h super.tap do |map| map.delete(:parent) class_name = self.class.name.underscore.split('/')[-1] map[:type] = TYPE_MAP[class_name] || class_name map[:children] = @children.map(&:to_h) unless @children.empty? map.delete(:attributes) if map[:attributes].empty? end end |
#to_json(*opts) ⇒ Object
107 108 109 |
# File 'lib/appmap/feature.rb', line 107 def to_json(*opts) to_h.to_json(*opts) end |
#type? ⇒ Boolean
99 100 101 |
# File 'lib/appmap/feature.rb', line 99 def type? false end |
#valid? ⇒ Boolean
103 104 105 |
# File 'lib/appmap/feature.rb', line 103 def valid? !name.blank? && !location.blank? end |