Module: Toml::Merge

Defined in:
lib/toml/merge.rb,
lib/toml/merge/emitter.rb,
lib/toml/merge/version.rb,
lib/toml/merge/provider.rb,
lib/toml/merge/key_sorter.rb,
lib/toml/merge/debug_logger.rb,
lib/toml/merge/merge_result.rb,
lib/toml/merge/node_wrapper.rb,
lib/toml/merge/smart_merger.rb,
lib/toml/merge/file_analysis.rb,
lib/toml/merge/comment_tracker.rb,
lib/toml/merge/conflict_resolver.rb,
lib/toml/merge/table_match_refiner.rb,
lib/toml/merge/node_type_normalizer.rb,
lib/toml/merge/source_preserving_provider.rb,
sig/toml/merge.rbs

Overview

Portable TOML workflow integration.

Defined Under Namespace

Modules: DebugLogger, NodeTypeNormalizer, Version Classes: CommentTracker, ConflictResolver, CorruptionDetectedError, DestinationParseError, Emitter, Error, FileAnalysis, KeySorter, MergeResult, NodeWrapper, ParseError, Provider, SmartMerger, SourcePreservingProvider, TableMatchRefiner, TemplateParseError

Constant Summary collapse

PACKAGE_NAME =
'toml-merge'
DESTINATION_WINS_ARRAY_POLICY =
{
  surface: 'array',
  name: 'destination_wins_array'
}.freeze
TREE_SITTER_BACKEND_REFERENCE =
TreeHaver::BackendReference.new(id: 'kreuzberg-language-pack',
family: 'tree-sitter').freeze
BACKEND_REGISTRY =
Struct.new(:registered, :mutex).new(false, Mutex.new)
VERSION =

Current gem version exposed at the traditional constant location.

Returns:

  • (String)
Version::VERSION
NodeTypingNormalizer =

Alias for the shared normalizer module from ast-merge

Ast::Merge::NodeTyping::Normalizer

Class Method Summary collapse

Class Method Details

.analyze_toml_source(source, dialect) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/toml/merge.rb', line 165

def analyze_toml_source(source, dialect)
  return unsupported_feature_parse_result("Unsupported TOML dialect #{dialect}.") unless dialect == 'toml'

  analysis = FileAnalysis.new(source)
  return parse_error_result(analysis.errors.map(&:to_s).join('; ')) unless analysis.valid?

  {
    ok: true,
    diagnostics: [],
    analysis: {
      kind: 'toml',
      dialect: 'toml',
      normalized_source: normalize_toml_source(source),
      root_kind: 'table',
      owners: collect_file_analysis_owners(analysis)
    },
    policies: []
  }
rescue StandardError => e
  parse_error_result(e.message)
end

.available_toml_backendsObject



123
124
125
# File 'lib/toml/merge.rb', line 123

def available_toml_backends
  toml_backend_available_for_analysis?(TREE_SITTER_BACKEND_REFERENCE.id) ? [TREE_SITTER_BACKEND_REFERENCE] : []
end

.match_toml_owners(template, destination) ⇒ Object



187
188
189
# File 'lib/toml/merge.rb', line 187

def match_toml_owners(template, destination)
  Ast::Merge::OwnerSelection.match_by_path(template, destination)
end

.merge_providerProvider

Returns:



16
17
18
# File 'lib/toml/merge/provider.rb', line 16

def merge_provider
  @merge_provider ||= Provider.new
end

.merge_toml(template_source, destination_source, dialect, backend: nil) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/toml/merge.rb', line 191

def merge_toml(template_source, destination_source, dialect, backend: nil)
  return unsupported_feature_merge_result("Unsupported TOML dialect #{dialect}.") unless dialect == 'toml'

  requested = requested_toml_backend_id(backend)
  return unsupported_feature_merge_result("Unsupported TOML backend #{requested}.") unless available_toml_backends.any? do |candidate|
    candidate.id == requested
  end

  output = TreeHaver.with_backend(requested) do
    SmartMerger.new(
      template_source,
      destination_source,
      preference: :destination,
      add_template_only_nodes: true
    ).merge_result.to_toml
  end

  {
    ok: true,
    diagnostics: [],
    output: output,
    policies: [DESTINATION_WINS_ARRAY_POLICY]
  }
rescue TemplateParseError => e
  { ok: false, diagnostics: [diagnostic('error', 'template_parse_error', e.message)], policies: [] }
rescue DestinationParseError => e
  { ok: false, diagnostics: [diagnostic('error', 'destination_parse_error', e.message)], policies: [] }
rescue StandardError => e
  { ok: false, diagnostics: [diagnostic('error', 'merge_error', e.message)], policies: [] }
end

.merge_toml_with_parser(template_source, destination_source, dialect) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/toml/merge.rb', line 222

def merge_toml_with_parser(template_source, destination_source, dialect)
  return unsupported_feature_merge_result("Unsupported TOML dialect #{dialect}.") unless dialect == 'toml'
  raise ArgumentError, 'merge_toml_with_parser requires a parser block' unless block_given?

  template_parse = yield(template_source, dialect)
  return provider_parse_failure(:template_parse_error, template_parse) unless template_parse[:ok]

  destination_parse = yield(destination_source, dialect)
  return provider_parse_failure(:destination_parse_error, destination_parse) unless destination_parse[:ok]

  output = SmartMerger.new(
    template_source,
    destination_source,
    preference: :destination,
    add_template_only_nodes: true
  ).merge_result.to_toml

  {
    ok: true,
    diagnostics: [],
    output: output,
    policies: [DESTINATION_WINS_ARRAY_POLICY]
  }
rescue TemplateParseError => e
  { ok: false, diagnostics: [diagnostic('error', 'template_parse_error', e.message)], policies: [] }
rescue DestinationParseError => e
  { ok: false, diagnostics: [diagnostic('error', 'destination_parse_error', e.message)], policies: [] }
rescue StandardError => e
  { ok: false, diagnostics: [diagnostic('error', 'merge_error', e.message)], policies: [] }
end

.parse_toml(source, dialect, backend: nil) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/toml/merge.rb', line 152

def parse_toml(source, dialect, backend: nil)
  return unsupported_feature_parse_result("Unsupported TOML dialect #{dialect}.") unless dialect == 'toml'

  requested = requested_toml_backend_id(backend)
  return unsupported_feature_parse_result("Unsupported TOML backend #{requested}.") unless available_toml_backends.any? do |candidate|
    candidate.id == requested
  end

  TreeHaver.with_backend(requested) { analyze_toml_source(source, dialect) }
rescue StandardError => e
  parse_error_result(e.message)
end

.register_backend!Object



253
254
255
256
257
258
259
260
261
262
263
# File 'lib/toml/merge.rb', line 253

def register_backend!
  BACKEND_REGISTRY.mutex.synchronize do
    return if BACKEND_REGISTRY.registered && TreeHaver.registered_languages(:toml).any?

    TreeHaver::BackendRegistry.register(TREE_SITTER_BACKEND_REFERENCE)

    register_tree_sitter_backend!

    BACKEND_REGISTRY.registered = true
  end
end

.register_provider!(replace: false) ⇒ Object

Parameters:

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

Returns:

  • (Object)


20
21
22
# File 'lib/toml/merge/provider.rb', line 20

def register_provider!(replace: false)
  Ast::Merge.register_provider(merge_provider, replace: replace)
end

.toml_backend_feature_profile(backend: nil) ⇒ Object



127
128
129
130
131
132
133
134
135
136
# File 'lib/toml/merge.rb', line 127

def toml_backend_feature_profile(backend: nil)
  requested = requested_toml_backend_id(backend)
  backend_ref = available_toml_backends.find { |candidate| candidate.id == requested }
  return unsupported_feature_result("Unsupported TOML backend #{requested}.") unless backend_ref

  toml_feature_profile.merge(
    backend: backend_ref.id,
    backend_ref: backend_ref.to_h
  )
end

.toml_feature_profileObject



115
116
117
118
119
120
121
# File 'lib/toml/merge.rb', line 115

def toml_feature_profile
  {
    family: 'toml',
    supported_dialects: ['toml'],
    supported_policies: [DESTINATION_WINS_ARRAY_POLICY]
  }
end

.toml_plan_context(backend: nil) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/toml/merge.rb', line 138

def toml_plan_context(backend: nil)
  profile = toml_backend_feature_profile(backend: backend)
  return profile if profile[:ok] == false

  {
    family_profile: toml_feature_profile,
    feature_profile: {
      backend: profile[:backend],
      supports_dialects: false,
      supported_policies: profile[:supported_policies]
    }
  }
end