Class: Ryac::Pipeline::AttrDeclShorten

Inherits:
Stage
  • Object
show all
Includes:
RenamePatcher
Defined in:
lib/ryac/pipeline/attr_decl_shorten.rb,
sig/ryac/pipeline/attr_decl_shorten.rbs

Overview

attr_reader :a → attr :a (the same method, four bytes shorter) and single-name attr_accessor → the two-argument attr form, for declarations type analysis recognized as meta calls. This stage owns the attr rewrite at every level: with rename_attrs the declared symbols are additionally mapped through the analysis' attr rename map, keeping declarations in sync with call sites the method renamer renames.

Instance Method Summary collapse

Methods included from RenamePatcher

#patch_assoc, #patch_block_param_node, #patch_block_params, #patch_def_params, #patch_for_node, #patch_keyword_hash, #patch_keyword_params, #patch_keyword_rest, #patch_multi_target_params, #patch_named_param, #patch_optional_params, #patch_post_params, #patch_required_params, #patch_rest_param, #patch_variable, #patch_variable_name_only, #prism_location_key, #walk_prism

Methods inherited from Stage

#analysis, #analysis_options, #call, #finish, #fixpoint?, new

Methods included from SourcePatcher

#apply_patches, #mk, #src, #verify_parses

Constructor Details

#initialize(rename_attrs: false) ⇒ AttrDeclShorten

Returns a new instance of AttrDeclShorten.

Parameters:

  • rename_attrs: (Boolean) (defaults to: false)


16
17
18
# File 'lib/ryac/pipeline/attr_decl_shorten.rb', line 16

def initialize(rename_attrs: false)
  @rename_attrs = rename_attrs
end

Instance Method Details

#collect(ctx, patches) ⇒ void

This method returns an undefined value.

Parameters:



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/ryac/pipeline/attr_decl_shorten.rb', line 20

def collect(ctx, patches)
  analysis = analysis(ctx)
  attr_rename_map = analysis.attr_rename_map if @rename_attrs
  walk_prism(ctx.ast) do |subnode|
    next unless subnode.is_a?(Prism::CallNode)

    key = prism_location_key(subnode)
    meta = analysis.meta_node_map[key]
    next unless meta

    args = meta[:args] || []
    next unless args.any?

    names = args.map { |sym| attr_rename_map&.dig(key, sym) || sym.to_s }
    replacement = render_attr_declaration(meta[:type], names)
    next unless replacement && replacement != subnode.slice

    loc = subnode.location
    patches << { start: loc.start_offset, end: loc.end_offset, replacement: replacement }
  end
end

#needs_analysis? ⇒ Boolean

Returns:

  • (Boolean)


14
# File 'lib/ryac/pipeline/attr_decl_shorten.rb', line 14

def needs_analysis? = true

#render_attr_declaration(type, names) ⇒ String?

The compact spelling of an attr declaration: attr_reader collapses to attr, a single-name attr_accessor takes the two-argument attr form, a multi-name accessor has no shorter spelling.

Parameters:

  • type (Symbol)
  • names (Array[String])

Returns:

  • (String, nil)


47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/ryac/pipeline/attr_decl_shorten.rb', line 47

def render_attr_declaration(type, names)
  case type
  when :attr_reader
    "attr #{names.map { |n| ":#{n}" }.join(',')}"
  when :attr_accessor
    if names.size == 1
      "attr :#{names[0]},!!1"
    else
      "attr_accessor #{names.map { |n| ":#{n}" }.join(',')}"
    end
  end
end