Class: DSLCompose::Parser::ForChildrenOfParser::ForDSLParser
- Inherits:
-
Object
- Object
- DSLCompose::Parser::ForChildrenOfParser::ForDSLParser
- Defined in:
- lib/dsl_compose/parser/for_children_of_parser/for_dsl_parser.rb,
lib/dsl_compose/parser/for_children_of_parser/for_dsl_parser/for_method_parser.rb
Defined Under Namespace
Classes: AllBlockParametersMustBeKeywordParametersError, DSLDoesNotExistError, DSLNamesShouldBeSymbolsError, ForMethodParser, NoBlockProvided
Instance Method Summary collapse
-
#initialize(base_class, child_class, dsl_names, on_current_class, on_ancestor_class, first_use_only, &block) ⇒ ForDSLParser
constructor
This class will yield to the provided block once for each time a DSL of the provided name is used by the child class.
Constructor Details
#initialize(base_class, child_class, dsl_names, on_current_class, on_ancestor_class, first_use_only, &block) ⇒ ForDSLParser
This class will yield to the provided block once for each time a DSL of the provided name is used by the child class.
base_class and child_class are set from the ForChildrenOfParser
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/dsl_compose/parser/for_children_of_parser/for_dsl_parser.rb', line 23 def initialize base_class, child_class, dsl_names, on_current_class, on_ancestor_class, first_use_only, &block @base_class = base_class @child_class = child_class @dsl_names = dsl_names # assert that a block was provided unless block raise NoBlockProvided end # if any arguments were provided, then assert that they are valid if block&.parameters&.any? # all parameters must be keyword arguments if block.parameters.filter { |p| p.first != :keyreq }.any? raise AllBlockParametersMustBeKeywordParametersError, "All block parameters must be keyword parameters, i.e. `for_dsl :dsl_name do |dsl_name:|`" end end # if the provided dsl name is a symbol, then convert it to an array if dsl_names.is_a? Symbol dsl_names = [dsl_names] end # assert that the provided dsl name is an array unless dsl_names.is_a? Array raise DSLNamesShouldBeSymbolsError, "DSL names `#{dsl_names}` must be provided with a symbol or array of symbols" end # assert that the provided dsl name is an array of symbols unless dsl_names.all? { |dsl_name| dsl_name.is_a? Symbol } raise DSLNamesShouldBeSymbolsError, "DSL names `#{dsl_names}` must be provided with a symbol or array of symbols" end # assert that the provided dsl names all exist unless dsl_names.all? { |dsl_name| DSLs.class_dsl_exists?(base_class, dsl_name) } raise DSLDoesNotExistError, "DSLs named `#{dsl_names}` must all exist" end # for each provided dsl name, yield to the provided block dsl_names.each do |dsl_name| # a dsl can be execued multiple times on a class, so we find all of the executions # here and then yield the block once for each execution base_class.dsls.class_dsl_executions(child_class, dsl_name, on_current_class, on_ancestor_class, first_use_only).each do |dsl_execution| # we only provide the requested arguments to the block, this allows # us to use keyword arguments to force a naming convention on these arguments # and to validate their use args = {} # the dsl name (if it's requested) if BlockArguments.accepts_argument?(:dsl_name, &block) args[:dsl_name] = dsl_execution.dsl.name end # the dsl_execution (if it's requested) if BlockArguments.accepts_argument?(:dsl_execution, &block) args[:dsl_execution] = dsl_execution end # a hash representation of all the dsl arguments, if requested if BlockArguments.accepts_argument?(:dsl_arguments, &block) args[:dsl_arguments] = {} # process each argument, because we might need to coerce it dsl_execution.arguments.arguments.each do |name, value| # if this value is a ClassCoerce object, then convert it from its original # string value to a class args[:dsl_arguments][name] = value.is_a?(ClassCoerce) ? value.to_class : value end end # an ExecutionReader object to access the exections methods (if it's requested) if BlockArguments.accepts_argument?(:reader, &block) args[:reader] = Reader::ExecutionReader.new(dsl_execution) end # add any arguments that were provided to the DSL dsl_execution.arguments.arguments.each do |name, value| if BlockArguments.accepts_argument?(name, &block) # if this value is a ClassCoerce object, then convert it from its original # string value to a class args[name] = value.is_a?(ClassCoerce) ? value.to_class : value end end # set the dsl_execution in an instance variable so that method calls to `for_method` # from within the block will have access to it @dsl_execution = dsl_execution # yield the block in the context of this class instance_exec(**args, &block) rescue => e # if this is an InterpreterError, then it already has the called_from metadata # just continue raising the original error if e.is_a? Interpreter::InterpreterError raise end # otherwise, decorate the error with where the DSL was defined raise e, "#{e.}\nparsing class: #{child_class.name}\ndsl name: #{dsl_name}\ndsl source: #{dsl_execution.called_from}", e.backtrace end end end |