Class: ArchSpec::Analyzer::SyntaxOverlay
- Inherits:
-
Object
- Object
- ArchSpec::Analyzer::SyntaxOverlay
- Defined in:
- lib/archspec/analyzer.rb
Overview
Rubydex supplies the semantic graph. This pass records the few facts whose syntax matters to ArchSpec's rules or that Rubydex does not model.
Defined Under Namespace
Classes: CallResolution, CallSite, ConstantSite, DeclarationFallback, DeclarationName, GeneratedMethod, MethodFallback, MethodOwner, MixinFallback, Owner
Constant Summary collapse
- DYNAMIC_MESSAGES =
%i[ class_eval const_get const_set define_method instance_eval method_missing module_eval public_send send ].freeze
- GENERATED_METHOD_MACROS =
{ attr_reader: %i[reader], attr_writer: %i[writer], attr_accessor: %i[reader writer], attribute: %i[reader writer], delegate: %i[reader], alias_attribute: %i[reader writer], enum: %i[reader writer], store_accessor: %i[reader writer], belongs_to: %i[reader writer], has_one: %i[reader writer], has_many: %i[reader writer], has_and_belongs_to_many: %i[reader writer] }.freeze
- SINGLE_NAME_MACROS =
%i[ attribute alias_attribute enum belongs_to has_one has_many has_and_belongs_to_many ].freeze
- SINGULAR_ASSOCIATION_MACROS =
%i[belongs_to has_one].freeze
- SINGULAR_ASSOCIATION_HELPERS =
['build_%s', 'create_%s', 'create_%s!', 'reload_%s'].freeze
- BUILDER_KINDS =
{ %w[Class new] => :class, %w[Struct new] => :class, %w[Data define] => :class, %w[Module new] => :module }.freeze
- MIXIN_EDGE_TYPES =
{ include: :includes, prepend: :prepends, extend: :extends }.freeze
- VISIBILITY_MODIFIERS =
{ private: [:private, nil], protected: [:protected, nil], public: [:public, nil], private_class_method: [:private, :class], public_class_method: [:public, :class] }.freeze
Instance Attribute Summary collapse
-
#call_sites ⇒ Object
readonly
Returns the value of attribute call_sites.
-
#constant_sites ⇒ Object
readonly
Returns the value of attribute constant_sites.
Instance Method Summary collapse
- #apply(graph, call_resolutions: {}) ⇒ Object
- #constant_name_at(path, location) ⇒ Object
- #declaration_kind(name, path) ⇒ Object
- #declaration_name(name, path = nil, location = nil) ⇒ Object
-
#initialize ⇒ SyntaxOverlay
constructor
A new instance of SyntaxOverlay.
- #method_owner(name, scope) ⇒ Object
- #method_owner_override(path, location) ⇒ Object
- #scan(path, node) ⇒ Object
- #superclass_fallback(name, path) ⇒ Object
- #superclass_override(name, path) ⇒ Object
Constructor Details
#initialize ⇒ SyntaxOverlay
Returns a new instance of SyntaxOverlay.
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/archspec/analyzer.rb', line 209 def initialize @constant_sites = [] @constant_sites_by_path = Hash.new { |hash, key| hash[key] = [] } @call_sites = [] @generated_methods = [] @declaration_fallbacks = [] @method_fallbacks = [] @mixin_fallbacks = [] @extra_edges = [] @namespace_flags = Hash.new { |hash, key| hash[key] = [] } @declaration_kinds = {} @declaration_names = [] @superclass_overrides = {} @superclass_fallbacks = {} @method_owner_overrides = [] end |
Instance Attribute Details
#call_sites ⇒ Object (readonly)
Returns the value of attribute call_sites.
207 208 209 |
# File 'lib/archspec/analyzer.rb', line 207 def call_sites @call_sites end |
#constant_sites ⇒ Object (readonly)
Returns the value of attribute constant_sites.
207 208 209 |
# File 'lib/archspec/analyzer.rb', line 207 def constant_sites @constant_sites end |
Instance Method Details
#apply(graph, call_resolutions: {}) ⇒ Object
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/archspec/analyzer.rb', line 230 def apply(graph, call_resolutions: {}) @declaration_fallbacks.each do |fallback| constant = graph.constants_named(fallback.name).find { |candidate| candidate.path == fallback.path } unless constant constant = graph.add_constant( name: fallback.name, kind: fallback.kind, path: fallback.path, location: fallback.location, nesting: fallback.nesting ) constant.superclass = fallback.superclass if constant.class? end add_fallback_ancestry(graph, fallback) end apply_method_fallbacks(graph) apply_mixin_fallbacks(graph) @namespace_flags.each do |(name, path), flags| graph.set_namespace_only(name, path, flags.all?) end apply_generated_methods(graph) @extra_edges.each { |edge| graph.add_edge(**edge) } call_sites.each do |site| resolution = call_resolutions[site] resolved_method = graph.resolve_method_alias(resolution.receiver, site.name, resolution.scope) if resolution graph.add_edge( type: :calls_named_method, from_path: site.path, from_constant: site.owner, to: site.name, location: site.location, receiver: site.receiver, resolved_receiver: resolution&.receiver, receiver_scope: resolution&.scope, resolved_method: resolved_method ) end end |
#constant_name_at(path, location) ⇒ Object
294 295 296 297 |
# File 'lib/archspec/analyzer.rb', line 294 def constant_name_at(path, location) sites = @constant_sites_by_path[path].select { |site| contains?(site.location, location) } sites.max_by { |site| site.name.length }&.name end |
#declaration_kind(name, path) ⇒ Object
269 270 271 |
# File 'lib/archspec/analyzer.rb', line 269 def declaration_kind(name, path) @declaration_kinds[[normalize(name), path]] end |
#declaration_name(name, path = nil, location = nil) ⇒ Object
273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/archspec/analyzer.rb', line 273 def declaration_name(name, path = nil, location = nil) normalized = normalize(name) return normalized unless path candidates = @declaration_names.select do |candidate| candidate.path == path && (normalized == candidate.raw || normalized.start_with?("#{candidate.raw}::")) end candidates.select! { |candidate| contains?(candidate.location, location) } if location mapping = candidates.max_by { |candidate| candidate.raw.length } mapping ? "#{mapping.qualified}#{normalized.delete_prefix(mapping.raw)}" : normalized end |
#method_owner(name, scope) ⇒ Object
306 307 308 |
# File 'lib/archspec/analyzer.rb', line 306 def method_owner(name, scope) Owner.new(name, scope) if name end |
#method_owner_override(path, location) ⇒ Object
299 300 301 302 303 304 |
# File 'lib/archspec/analyzer.rb', line 299 def method_owner_override(path, location) override = @method_owner_overrides.reverse_each.find do |candidate| candidate.path == path && contains?(candidate.location, location) end override&.owner end |
#scan(path, node) ⇒ Object
226 227 228 |
# File 'lib/archspec/analyzer.rb', line 226 def scan(path, node) visit(File.(path), node) end |
#superclass_fallback(name, path) ⇒ Object
290 291 292 |
# File 'lib/archspec/analyzer.rb', line 290 def superclass_fallback(name, path) @superclass_fallbacks[[normalize(name), path]] end |
#superclass_override(name, path) ⇒ Object
286 287 288 |
# File 'lib/archspec/analyzer.rb', line 286 def superclass_override(name, path) @superclass_overrides[[normalize(name), path]] end |