Class: Markdown::Merge::SourcePreservingProvider

Inherits:
Object
  • Object
show all
Defined in:
lib/markdown/merge/source_preserving_provider.rb,
sig/markdown/merge.rbs

Overview

Base-aware source-preserving provider for a deliberately small Markdown subset: complete documents partitioned by unique, same-level ATX headings. rubocop:disable Metrics/AbcSize, Metrics/ClassLength, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/ParameterLists, Metrics/PerceivedComplexity -- parsing, ownership, rendering, and verification are one safety boundary

Direct Known Subclasses

Provider

Defined Under Namespace

Classes: Decision, Document, ExactDocument, Owner

Constant Summary collapse

DEFAULT_PROFILE =
:source_preserving

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(provider_id:, role:, backend:) ⇒ SourcePreservingProvider

Returns a new instance of SourcePreservingProvider.

Parameters:



146
147
148
149
150
# File 'lib/markdown/merge/source_preserving_provider.rb', line 146

def initialize(provider_id:, role:, backend:)
  @provider_id = provider_id
  @role = role.to_sym
  @backend = backend
end

Instance Attribute Details

#backendProviderBackend (readonly)

Returns the value of attribute backend.

Returns:



144
145
146
# File 'lib/markdown/merge/source_preserving_provider.rb', line 144

def backend
  @backend
end

#provider_idString (readonly)

Returns the value of attribute provider_id.

Returns:



144
145
146
# File 'lib/markdown/merge/source_preserving_provider.rb', line 144

def provider_id
  @provider_id
end

Instance Method Details

#analyze(request) ⇒ Hash[Symbol, untyped]

Parameters:

Returns:



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/markdown/merge/source_preserving_provider.rb', line 166

def analyze(request)
  document = parse_document(:analyze, request, :source)
  return document if provider_failure?(document)

  result(
    :analyze,
    request,
    analysis: {
      backend: backend.id,
      delegated_backend: backend.id,
      valid: true,
      owners: document.owners.map { |owner| owner_description(owner) }
    },
    verification: { source_parsed: true, ast_headings_verified: true }
  )
end

#capabilitiesHash[Symbol, untyped]

Returns:



154
155
156
157
158
159
160
161
162
163
164
# File 'lib/markdown/merge/source_preserving_provider.rb', line 154

def capabilities
  {
    operations: Ast::Merge::ProviderContract::OPERATIONS,
    dialects: backend.dialects,
    backends: [backend.id],
    profiles: [DEFAULT_PROFILE],
    role: @role,
    ast_ownership: :unique_same_level_atx_heading_sections,
    source_preservation: i[exact_source exact_fragments byte_provenance reparse semantic_verification]
  }.freeze
end

#diff2(request) ⇒ Hash[Symbol, untyped]

Parameters:

Returns:



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/markdown/merge/source_preserving_provider.rb', line 183

def diff2(request)
  before = parse_document(:diff2, request, :before)
  return before if provider_failure?(before)

  after = parse_document(:diff2, request, :after)
  return after if provider_failure?(after)

  changes = diff_documents(before, after)
  result(
    :diff2,
    request,
    diff: { changes: changes },
    changes: changes,
    verification: { before_parsed: true, after_parsed: true, ast_headings_verified: true }
  )
end

#familyString

Returns:



152
# File 'lib/markdown/merge/source_preserving_provider.rb', line 152

def family = 'markdown'

#merge2(request) ⇒ Hash[Symbol, untyped]

Parameters:

Returns:



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/markdown/merge/source_preserving_provider.rb', line 200

def merge2(request)
  current = parse_document(:merge2, request, :current)
  return current if provider_failure?(current)

  incoming = parse_document(:merge2, request, :incoming)
  return incoming if provider_failure?(incoming)

  choices = current.owners.to_h { |owner| [owner.id, :current] }
  incoming.owners.each { |owner| choices[owner.id] ||= :incoming }
  decision = Decision.new(changes: [], conflicts: [], choices: choices.freeze)
  documents = { current: current, incoming: incoming }.freeze
  ordered = merged_order(documents, decision)
  return unsafe_merge2_order_failure(request) unless ordered

  fragments = ordered.map do |id|
    role = decision.choices.fetch(id)
    [documents.fetch(role).by_id.fetch(id), role]
  end
  output = composite_prefix(documents, :current) + fragments.map { |owner, _role| owner.source_text }.join
  expected = fragments.map { |owner, _role| [owner.signature, owner.fingerprint] }
  verification = verify_composite(output, expected)
  unless verification[:semantic_match]
    return render_failure(request, verification, :exact_markdown_composite, operation: :merge2)
  end

  output_document = parse_source(output, :output)
  changes = diff_documents(current, output_document)
  result(
    :merge2,
    request,
    output: output,
    changes: changes,
    render_report: composite_render_report(fragments, output),
    verification: verification
  )
end

#merge3(request) ⇒ Hash[Symbol, untyped]

Parameters:

Returns:



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/markdown/merge/source_preserving_provider.rb', line 237

def merge3(request)
  exact_role = exact_revision_role(request)
  return merge3_exact(request, exact_role) if exact_role

  documents = parse_merge3_documents(request)
  return documents if provider_failure?(documents)

  identity_failure = changed_identity_failure(request, documents)
  return identity_failure if identity_failure

  decision = decide(documents)
  return render_conflicts(request, documents, decision) unless decision.conflicts.empty?

  render_composite(request, documents, decision)
end