Module: Rust::Merge

Defined in:
lib/rust/merge.rb,
lib/rust/merge/version.rb

Defined Under Namespace

Modules: Version

Constant Summary collapse

PACKAGE_NAME =
"rust-merge"
TREE_SITTER_BACKEND =
TreeHaver::KREUZBERG_LANGUAGE_PACK_BACKEND
DESTINATION_WINS_ARRAY_POLICY =
{ surface: "array", name: "destination_wins_array" }.freeze
VERSION =
Version::VERSION

Class Method Summary collapse

Class Method Details

.available_rust_backendsObject



17
18
19
# File 'lib/rust/merge.rb', line 17

def available_rust_backends
  [TREE_SITTER_BACKEND]
end

.match_rust_owners(template, destination) ⇒ Object



52
53
54
55
56
57
58
59
60
# File 'lib/rust/merge.rb', line 52

def match_rust_owners(template, destination)
  destination_paths = destination[:owners].to_h { |owner| [owner[:path], true] }
  template_paths = template[:owners].to_h { |owner| [owner[:path], true] }
  {
    matched: template[:owners].filter { |owner| destination_paths[owner[:path]] }.map { |owner| { template_path: owner[:path], destination_path: owner[:path] } },
    unmatched_template: template[:owners].map { |owner| owner[:path] }.reject { |path| destination_paths[path] },
    unmatched_destination: destination[:owners].map { |owner| owner[:path] }.reject { |path| template_paths[path] }
  }
end

.merge_rust(template_source, destination_source, dialect) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rust/merge.rb', line 62

def merge_rust(template_source, destination_source, dialect)
  template = parse_rust(template_source, dialect)
  return { ok: false, diagnostics: template[:diagnostics], policies: [] } unless template[:ok]
  destination = parse_rust(destination_source, dialect)
  unless destination[:ok]
    return {
      ok: false,
      diagnostics: destination[:diagnostics].map { |diagnostic| diagnostic[:category] == "parse_error" ? diagnostic.merge(category: "destination_parse_error") : diagnostic },
      policies: []
    }
  end

  destination_declarations = destination.dig(:analysis, :declarations).to_h { |item| [item[:path], item] }
  merged_declaration_texts = destination.dig(:analysis, :declarations).map { |item| item[:text] } +
    template.dig(:analysis, :declarations).reject { |item| destination_declarations[item[:path]] }.map { |item| item[:text] }
  import_block = destination.dig(:analysis, :imports).map { |item| item[:text] }.join
  declaration_block = merged_declaration_texts.join("\n").rstrip
  sections = [import_block.rstrip, declaration_block].reject(&:empty?)
  { ok: true, diagnostics: [], output: "#{sections.join("\n\n").rstrip}\n", policies: [DESTINATION_WINS_ARRAY_POLICY] }
end

.parse_rust(source, dialect) ⇒ Object



46
47
48
49
50
# File 'lib/rust/merge.rb', line 46

def parse_rust(source, dialect)
  return analyze_rust_module(source) if dialect == "rust"

  { ok: false, diagnostics: [{ severity: "error", category: "unsupported_feature", message: "Unsupported Rust dialect #{dialect}." }], policies: [] }
end

.rust_backend_feature_profile(backend: nil) ⇒ Object



21
22
23
24
25
26
27
28
29
30
# File 'lib/rust/merge.rb', line 21

def rust_backend_feature_profile(backend: nil)
  requested = backend.to_s.empty? ? TREE_SITTER_BACKEND.id : backend.to_s
  return unsupported_feature_result("Unsupported Rust backend #{requested}.") unless requested == TREE_SITTER_BACKEND.id

  rust_feature_profile.merge(
    backend: requested,
    backend_ref: TREE_SITTER_BACKEND.to_h,
    supports_dialects: true
  )
end

.rust_feature_profileObject



13
14
15
# File 'lib/rust/merge.rb', line 13

def rust_feature_profile
  { family: "rust", supported_dialects: ["rust"], supported_policies: [DESTINATION_WINS_ARRAY_POLICY] }
end

.rust_plan_context(backend: nil) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/rust/merge.rb', line 32

def rust_plan_context(backend: nil)
  profile = rust_backend_feature_profile(backend: backend)
  return profile if profile[:ok] == false

  {
    family_profile: rust_feature_profile,
    feature_profile: {
      backend: profile[:backend],
      supports_dialects: true,
      supported_policies: profile[:supported_policies]
    }
  }
end