# Class: YARD::CodeObjects::MacroObject

Inherits:
  Base
  - Object
  - Base
  - YARD::CodeObjects::MacroObject
  show all

Defined in:
  lib/yard/code_objects/macro_object.rb

## Overview

A MacroObject represents a docstring defined through `@!macro NAME` and can be reused by specifying the tag `@!macro NAME`. You can also provide the `attached` type flag to the macro definition to have it attached to the specific DSL method so it will be implicitly reused.

Macros are fully described in the Tags Overview document.

#### Examples:

#####

Creating a basic named macro

    # @!macro prop
    #   @!method $1(${3-})
    #   @return [$2] the value of the $0
    property :foo, String, :a, :b

    # @!macro prop
    property :bar, Numeric, :value

#####

Creating a macro that is attached to the method call

    # @!macro [attach] prop2
    #   @!method $1(value)
    property :foo

    # Extra data added to docstring
    property :bar

## Constant Summary collapse

MACRO_MATCH =

      /(\\)?\$(?:\{(-?\d+|\*)(-)?(-?\d+)?\}|(-?\d+|\*))/

## Instance Attribute Summary collapse

- #macro_data ⇒ String

  The macro data stored on the object.

- #method_object ⇒ CodeObjects::Base

  The method object that this macro is attached to.

## Class Method Summary collapse

- .apply(docstring, call_params = [], full_source = '', block_source = '', _method_object = nil) ⇒ String

  Applies a macro on a docstring by creating any macro data inside of the docstring first.

- .apply_macro(macro, docstring, call_params = [], full_source = '', block_source = '') ⇒ String

  Applies a macro to a docstring, interpolating the macro’s data on the docstring and appending any extra local docstring data that was in the original `docstring` object.

- .create(macro_name, data, method_object = nil) ⇒ MacroObject

  Creates a new macro and fills in the relevant properties.

- .expand(macro_data, call_params = [], full_source = '', block_source = '') ⇒ Object

  Expands `macro_data` using the interpolation parameters.

- .find(macro_name) ⇒ MacroObject?

  Finds a macro using `macro_name`.

- .find_or_create(macro_name, data, method_object = nil) ⇒ MacroObject? (also: create_docstring)

  Parses a given docstring and determines if the macro is “new” or not.

## Instance Method Summary collapse

- #attached? ⇒ Boolean

  Whether this macro is attached to a method.

- #expand(call_params = [], full_source = '', block_source = '') ⇒ Object

  Expands the macro using.

- #path ⇒ Object

  Overrides Base#path so the macro path is “.macro.MACRONAME”.

- #sep ⇒ Object

  Overrides the separator to be ‘.’.

## Constructor Details

This class inherits a constructor from YARD::CodeObjects::Base

## Dynamic Method Handling

This class handles dynamic methods through the `method_missing` method in the class YARD::CodeObjects::Base

## Instance Attribute Details

### #macro_data ⇒ `String`

Returns the macro data stored on the object.

Returns:

- (`String`) —

  the macro data stored on the object

    141
    142
    143

    # File 'lib/yard/code_objects/macro_object.rb', line 141

    def macro_data
      @macro_data
    end

### #method_object ⇒ `CodeObjects::Base`

Returns the method object that this macro is attached to.

Returns:

- (`CodeObjects::Base`) —

  the method object that this macro is attached to.

    145
    146
    147

    # File 'lib/yard/code_objects/macro_object.rb', line 145

    def method_object
      @method_object
    end

## Class Method Details

### .apply(docstring, call_params = [], full_source = '', block_source = '', _method_object = nil) ⇒ `String`

Applies a macro on a docstring by creating any macro data inside of the docstring first. Equivalent to calling find_or_create and apply_macro on the new macro object.

Parameters:

- docstring (`Docstring`) —

  the docstring to create a macro out of

- call_params (`Array<String>`) (defaults to: `[]`) —

  the method name and parameters to the method call. These arguments will fill $0-N

- full_source (`String`) (defaults to: `''`) —

  the full source line (excluding block) interpolated as $*

- block_source (`String`) (defaults to: `''`) —

  Currently unused. Will support interpolating the block data as a variable.

Returns:

- (`String`) —

  the expanded macro data

See Also:

- find_or_create

    119
    120
    121
    122
    123
    124
    125
    126
    127

    # File 'lib/yard/code_objects/macro_object.rb', line 119

    def apply(docstring, call_params = [], full_source = '', block_source = '', _method_object = nil) # rubocop:disable Lint/UnusedMethodArgument
      docstring = docstring.all if Docstring === docstring
      parser = Docstring.parser
      handler = OpenStruct.new
      handler.call_params = call_params[1..-1]
      handler.caller_method = call_params.first
      handler.statement = OpenStruct.new(:source => full_source)
      parser.parse(docstring, nil, handler).to_docstring.to_raw
    end

### .apply_macro(macro, docstring, call_params = [], full_source = '', block_source = '') ⇒ `String`

Applies a macro to a docstring, interpolating the macro’s data on the docstring and appending any extra local docstring data that was in the original `docstring` object.

Parameters:

- macro (`MacroObject`) —

  the macro object

- call_params (`Array<String>`) (defaults to: `[]`) —

  the method name and parameters to the method call. These arguments will fill $0-N

- full_source (`String`) (defaults to: `''`) —

  the full source line (excluding block) interpolated as $*

- block_source (`String`) (defaults to: `''`) —

  Currently unused. Will support interpolating the block data as a variable.

Returns:

- (`String`) —

  the expanded macro data

    135
    136
    137

    # File 'lib/yard/code_objects/macro_object.rb', line 135

    def apply_macro(macro, docstring, call_params = [], full_source = '', block_source = '') # rubocop:disable Lint/UnusedMethodArgument
      apply(docstring, call_params, full_source, block_source)
    end

### .create(macro_name, data, method_object = nil) ⇒ `MacroObject`

Creates a new macro and fills in the relevant properties.

Parameters:

- macro_name (`String`) —

  the name of the macro, must be unique.

- data (`String`) —

  the data the macro should expand when re-used

- method_object (`CodeObjects::Base`) (defaults to: `nil`) —

  an object to attach this macro to. If supplied, #attached? will be true

Returns:

- (`MacroObject`) —

  the newly created object

    39
    40
    41
    42
    43
    44

    # File 'lib/yard/code_objects/macro_object.rb', line 39

    def create(macro_name, data, method_object = nil)
      obj = new(:root, macro_name)
      obj.macro_data = data
      obj.method_object = method_object
      obj
    end

### .expand(macro_data, call_params = [], full_source = '', block_source = '') ⇒ `Object`

Expands `macro_data` using the interpolation parameters.

Interpolation rules:

- $0, $1, $2, … = the Nth parameter in `call_params`

- $* = the full statement source (excluding block)

- Also supports ${N-M} ranges, as well as negative indexes on N or M

- Use $ to escape the variable name in a macro.

Parameters:

- macro_data (`String`) —

  the macro data to expand (taken from #macro_data)

    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110

    # File 'lib/yard/code_objects/macro_object.rb', line 92

    def expand(macro_data, call_params = [], full_source = '', block_source = '') # rubocop:disable Lint/UnusedMethodArgument
      macro_data = macro_data.all if macro_data.is_a?(Docstring)
      macro_data.gsub(MACRO_MATCH) do
        escape = $1
        first = $2 || $5
        last = $4
        rng = $3 ? true : false
        next $&[1..-1] if escape
        if first == '*'
          last ? $& : full_source
        else
          first_i = first.to_i
          last_i = (last ? last.to_i : call_params.size)
          last_i = first_i unless rng
          params = call_params[first_i..last_i]
          params ? params.join(", ") : ''
        end
      end
    end

### .find(macro_name) ⇒ `MacroObject`?

Finds a macro using `macro_name`

Parameters:

- macro_name (`#to_s`) —

  the name of the macro

Returns:

- (`MacroObject`) —

  if a macro is found

- (`nil`) —

  if there is no registered macro by that name

    50
    51
    52

    # File 'lib/yard/code_objects/macro_object.rb', line 50

    def find(macro_name)
      Registry.at('.macro.' + macro_name.to_s)
    end

### .find_or_create(macro_name, data, method_object = nil) ⇒ `MacroObject`? Also known as: create_docstring

Parses a given docstring and determines if the macro is “new” or not. If the macro has $variable names or if it has a @!macro tag with the [new] or [attached] flag, it is considered new.

If a new macro is found, the macro is created and registered. Otherwise the macro name is searched and returned. If a macro is not found, nil is returned.

Parameters:

- macro_name (`#to_s`) —

  the name of the macro

- method_object (`CodeObjects::Base`) (defaults to: `nil`) —

  an optional method to attach the macro to. Only used if the macro is being created, otherwise this argument is ignored.

Returns:

- (`MacroObject`) —

  the newly created or existing macro, depending on whether the @!macro tag was a new tag or not.

- (`nil`) —

  if the `data` has no macro tag or if the macro is not new and no macro by the macro name is found.

    70
    71
    72

    # File 'lib/yard/code_objects/macro_object.rb', line 70

    def find_or_create(macro_name, data, method_object = nil)
      find(name) || create(macro_name, data, method_object)
    end

## Instance Method Details

### #attached? ⇒ `Boolean`

Returns whether this macro is attached to a method.

Returns:

- (`Boolean`) —

  whether this macro is attached to a method

    148

    # File 'lib/yard/code_objects/macro_object.rb', line 148

    def attached?; method_object ? true : false end

### #expand(call_params = [], full_source = '', block_source = '') ⇒ `Object`

Expands the macro using

#### Examples:

#####

Expanding a Macro

    macro.expand(%w(property foo bar), 'property :foo, :bar', '') #=>
      "...macro data interpolating this line of code..."

Parameters:

- call_params (`Array<String>`) (defaults to: `[]`) —

  a list of tokens that are passed to the method call

- full_source (`String`) (defaults to: `''`) —

  the full method call (not including the block)

- block_source (`String`) (defaults to: `''`) —

  the source passed in the block of the method call, if there is a block.

See Also:

- expand

    166
    167
    168

    # File 'lib/yard/code_objects/macro_object.rb', line 166

    def expand(call_params = [], full_source = '', block_source = '')
      self.class.expand(macro_data, call_params, full_source, block_source)
    end

### #path ⇒ `Object`

Overrides Base#path so the macro path is “.macro.MACRONAME”

    151

    # File 'lib/yard/code_objects/macro_object.rb', line 151

    def path; '.macro.' + name.to_s end

### #sep ⇒ `Object`

Overrides the separator to be ‘.’

    154

    # File 'lib/yard/code_objects/macro_object.rb', line 154

    def sep; '.' end