module SlimLint::SexpVisitor::DSL

Exposes a convenient Domain-specific Language (DSL) that makes declaring Sexp match patterns very easy.

Include them with `extend SlimLint::SexpVisitor::DSL`

Attributes

captures[R]

@return [Hash] map of capture names to captured values

patterns[R]

Registered patterns that this visitor will look for when traversing the {SlimLint::Sexp}.

Public Instance Methods

anything() click to toggle source

Represents a pattern that matches anything.

@return [SlimLint::Matcher::Anything]

# File lib/slim_lint/sexp_visitor.rb, line 128
def anything
  SlimLint::Matcher::Anything.new
end
capture(capture_name, matcher) click to toggle source

Represents a pattern that matches the specified matcher, storing the matched value in the captures list under the given name.

@param capture_name [Symbol] @param matcher [SlimLint::Matcher::Base] @return [SlimLint::Matcher::Capture]

# File lib/slim_lint/sexp_visitor.rb, line 138
def capture(capture_name, matcher)
  @captures ||= SlimLint::CaptureMap.new

  @captures[capture_name] =
    SlimLint::Matcher::Capture.from_matcher(matcher)
end
on(sexp_pattern, &block) click to toggle source

DSL helper that defines a sexp pattern and block that will be executed if the given pattern is found.

@param sexp_pattern [Sexp] @yield block to execute when the specified pattern is matched @yieldparam sexp [SlimLint::Sexp] Sexp that matched the pattern @yieldreturn [SlimLint::Sexp,Symbol,void]

If a Sexp is returned, indicates that traversal should jump directly
to that Sexp.
If `:stop` is returned, halts further traversal down this branch
(i.e. stops recursing, but traversal at higher levels will continue).
Otherwise traversal will continue as normal.
# File lib/slim_lint/sexp_visitor.rb, line 100
def on(sexp_pattern, &block)
  # TODO: Index Sexps on creation so we can quickly jump to potential
  # matches instead of checking array.
  @patterns ||= []
  @pattern_number ||= 1

  # Use a monotonically increasing number to identify the method so that in
  # debugging we can simply look at the nth defintion in the class.
  unique_method_name = :"on_pattern_#{@pattern_number}"
  define_method(unique_method_name, block)

  @pattern_number += 1
  @patterns << SexpPattern.new(sexp_pattern, unique_method_name)
end
on_start(&block) click to toggle source

Define a block of code to run before checking for any pattern matches.

@yield block to execute @yieldparam sexp [SlimLint::Sexp] the root Sexp @yieldreturn [Symbol] if `:stop`, indicates that no further processing

should occur
# File lib/slim_lint/sexp_visitor.rb, line 121
def on_start(&block)
  define_method(:on_start, block)
end