Class: PartializerConfig

Inherits:
Object show all
Includes:
Partials
Defined in:
lib/ceedling/partials/partializer_config.rb

Defined Under Namespace

Classes: Config, PartialFunctions

Constant Summary collapse

MACRO_NAMES =

Macro names for all partial configuration macros

[
  'TEST_PARTIAL_PUBLIC_MODULE',
  'TEST_PARTIAL_PRIVATE_MODULE',
  'MOCK_PARTIAL_PUBLIC_MODULE',
  'MOCK_PARTIAL_PRIVATE_MODULE',
  'TEST_PARTIAL_MODULE',
  'MOCK_PARTIAL_MODULE',
  'TEST_PARTIAL_ALL_MODULE',
  'MOCK_PARTIAL_ALL_MODULE',
  'TEST_PARTIAL_CONFIG',
  'MOCK_PARTIAL_CONFIG',
].freeze

Constants included from Partials

Partials::ACCUMULATE, Partials::DEDUCT, Partials::MOCK_PRIVATE, Partials::MOCK_PUBLIC, Partials::PRIVATE, Partials::PUBLIC, Partials::TEST_PRIVATE, Partials::TEST_PUBLIC

Instance Method Summary collapse

Methods included from Partials

manufacture_function_declaration, manufacture_function_definition

Instance Method Details

#extract_configs(content) ⇒ Object

Core three-pass extraction:

Pass 1 — MODULE macros: build Config entries, set types
Pass 2 — CONFIG macros: populate additions/subtractions
Pass 3 — Validation: raise if any Config has no meaningful content


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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/ceedling/partials/partializer_config.rb', line 86

def extract_configs(content)
  scanner = StringScanner.new(content)
  calls   = @c_extractor_preprocessing.try_extract_macro_calls(scanner, MACRO_NAMES)

  configs      = {}  # module_name => Config
  config_calls = []  # deferred: [macro_name, params] for CONFIG macros

  # --- Pass 1: MODULE macros ---
  calls.each do |call_str|
    macro_name, params = @c_extractor_preprocessing.parse_macro_call(call_str)
    next if macro_name.nil?

    if macro_name.end_with?('_CONFIG')
      config_calls << [macro_name, params]
      next
    end

    mod = _strip_quotes(params[0])
    configs[mod] ||= Config.new(module: mod)

    case macro_name
    when 'TEST_PARTIAL_PUBLIC_MODULE'
      _check_type_unset!(configs[mod].tests, mod, macro_name)
      configs[mod].tests.type = PUBLIC
    when 'TEST_PARTIAL_PRIVATE_MODULE'
      _check_type_unset!(configs[mod].tests, mod, macro_name)
      configs[mod].tests.type = PRIVATE
    when 'MOCK_PARTIAL_PUBLIC_MODULE'
      _check_type_unset!(configs[mod].mocks, mod, macro_name)
      configs[mod].mocks.type = PUBLIC
    when 'MOCK_PARTIAL_PRIVATE_MODULE'
      _check_type_unset!(configs[mod].mocks, mod, macro_name)
      configs[mod].mocks.type = PRIVATE
    when 'TEST_PARTIAL_MODULE'
      _check_type_unset!(configs[mod].tests, mod, macro_name)
      configs[mod].tests.type = ACCUMULATE
    when 'MOCK_PARTIAL_MODULE'
      _check_type_unset!(configs[mod].mocks, mod, macro_name)
      configs[mod].mocks.type = ACCUMULATE
    when 'TEST_PARTIAL_ALL_MODULE'
      _check_type_unset!(configs[mod].tests, mod, macro_name)
      configs[mod].tests.type = DEDUCT
    when 'MOCK_PARTIAL_ALL_MODULE'
      _check_type_unset!(configs[mod].mocks, mod, macro_name)
      configs[mod].mocks.type = DEDUCT
    end
  end

  # --- Pass 2: CONFIG macros ---
  config_calls.each do |macro_name, params|
    mod = _strip_quotes(params[0])
    unless configs.key?(mod)
      raise CeedlingException.new(
        "#{macro_name} references module '#{mod}' but no corresponding MODULE Partial macro directive for that module was found"
      )
    end

    target = macro_name.start_with?('TEST_') ? configs[mod].tests : configs[mod].mocks

    params[1..].each do |raw|
      name = _strip_quotes(raw)
      if name.start_with?('-')
        target.subtractions << name[1..]
      else
        target.additions << name.delete_prefix('+')
      end
    end

    target.subtractions.uniq!
    target.additions.uniq!
  end

  # --- Pass 3: Validation ---
  configs.each do |mod, config|
    if config.tests.type == ACCUMULATE && config.tests.additions.empty?
      raise CeedlingException.new(
        "TEST Partial for module '#{mod}' uses TEST_PARTIAL_MODULE() but no function additions were specified — " \
        "add at least one function name via TEST_PARTIAL_CONFIG()"
      )
    end

    if config.mocks.type == ACCUMULATE && config.mocks.additions.empty?
      raise CeedlingException.new(
        "MOCK Partial for module '#{mod}' uses MOCK_PARTIAL_MODULE() but no function additions were specified — " \
        "add at least one function name via MOCK_PARTIAL_CONFIG()"
      )
    end

    # Rule 1: subtractions are illegal with ACCUMULATE
    [[:tests, 'TEST'], [:mocks, 'MOCK']].each do |field, label|
      pf = config.send(field)
      if pf.type == ACCUMULATE && !pf.subtractions.empty?
        raise CeedlingException.new(
          "#{label} configuration for '#{mod}' Partial cannot contain subtractions because only additions are available with PARTIAL_#{label}_MODULE()"
        )
      end
    end

    # Rule 2: additions are illegal with DEDUCT
    [[:tests, 'TEST'], [:mocks, 'MOCK']].each do |field, label|
      pf = config.send(field)
      if pf.type == DEDUCT && !pf.additions.empty?
        raise CeedlingException.new(
          "#{label} configuration for '#{mod}' Partial cannot contain additions because only subtractions are available with #{label}_PARTIAL_ALL_MODULE()"
        )
      end
    end
  end

  return configs
end

#extract_configs_from_file(filepath) ⇒ Object

Extract partial configuration macros from a file. Returns a hash of module_name => Config.



78
79
80
# File 'lib/ceedling/partials/partializer_config.rb', line 78

def extract_configs_from_file(filepath)
  extract_configs( File.read(filepath).clean_encoding )
end

#extract_configs_from_string(string) ⇒ Object

Extract partial configuration macros from a string. Returns a hash of module_name => Config.



72
73
74
# File 'lib/ceedling/partials/partializer_config.rb', line 72

def extract_configs_from_string(string)
  extract_configs( string.clean_encoding )
end