Module: TypeScript::Merge

Defined in:
lib/typescript/merge.rb,
lib/typescript/merge/version.rb,
sig/typescript/merge.rbs

Defined Under Namespace

Modules: Version

Constant Summary collapse

PACKAGE_NAME =
'typescript-merge'
TREE_SITTER_BACKEND =
TreeHaver::KREUZBERG_LANGUAGE_PACK_BACKEND
DESTINATION_WINS_ARRAY_POLICY =
{ surface: 'array', name: 'destination_wins_array' }.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

Class Method Summary collapse

Class Method Details

.available_type_script_backendsObject



33
34
35
# File 'lib/typescript/merge.rb', line 33

def available_type_script_backends
  type_script_backend_available_for_analysis?(TREE_SITTER_BACKEND.id) ? [TREE_SITTER_BACKEND] : []
end

.match_type_script_owners(template, destination) ⇒ Object



96
97
98
# File 'lib/typescript/merge.rb', line 96

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

.merge_type_script(template_source, destination_source, dialect) ⇒ Object



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
# File 'lib/typescript/merge.rb', line 100

def merge_type_script(template_source, destination_source, dialect)
  template = parse_type_script(template_source, dialect)
  return { ok: false, diagnostics: template[:diagnostics], policies: [] } unless template[:ok]

  destination = parse_type_script(destination_source, dialect)
  unless destination[:ok]
    return {
      ok: false,
      diagnostics: destination[:diagnostics].map do |diagnostic|
        diagnostic[:category] == 'parse_error' ? diagnostic.merge(category: 'destination_parse_error') : diagnostic
      end,
      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 do |item|
                               destination_declarations[item[:path]]
                             end.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_type_script(source, dialect) ⇒ Object



64
65
66
67
68
69
70
71
72
73
# File 'lib/typescript/merge.rb', line 64

def parse_type_script(source, dialect)
  unless type_script_backend_available_for_analysis?(nil)
    diagnostic_backend = TreeHaver.current_backend_id || 'tree-sitter'
    return unsupported_feature_result("Unsupported TypeScript backend #{diagnostic_backend}.")
  end
  return analyze_type_script_module(source) if dialect == 'typescript'

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

.register_backend!Object



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/typescript/merge.rb', line 16

def register_backend!
  BACKEND_REGISTRY.mutex.synchronize do
    return if BACKEND_REGISTRY.registered

    TreeHaver::BackendRegistry.register(TREE_SITTER_BACKEND)

    grammar_finder = TreeHaver::GrammarFinder.new(:typescript)
    grammar_finder.register! if grammar_finder.available?

    BACKEND_REGISTRY.registered = true
  end
end

.type_script_backend_available_for_analysis?(backend_id) ⇒ Boolean

Returns:

  • (Boolean)


75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/typescript/merge.rb', line 75

def type_script_backend_available_for_analysis?(backend_id)
  register_backend!

  if backend_id.to_s.empty?
    TreeHaver.parser_for(:typescript, backend_type: :tree_sitter)
  else
    TreeHaver.with_backend(backend_id) { TreeHaver.parser_for(:typescript, backend_type: :tree_sitter) }
  end
  true
rescue TreeHaver::Error, ArgumentError
  false
end

.type_script_backend_feature_profile(backend: nil) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/typescript/merge.rb', line 37

def type_script_backend_feature_profile(backend: nil)
  requested = requested_tree_sitter_backend_id(backend)
  unless type_script_backend_available_for_analysis?(requested)
    return unsupported_feature_result("Unsupported TypeScript backend #{requested}.")
  end

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

.type_script_feature_profileObject



29
30
31
# File 'lib/typescript/merge.rb', line 29

def type_script_feature_profile
  { family: 'typescript', supported_dialects: ['typescript'], supported_policies: [DESTINATION_WINS_ARRAY_POLICY] }
end

.type_script_plan_context(backend: nil) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/typescript/merge.rb', line 50

def type_script_plan_context(backend: nil)
  profile = type_script_backend_feature_profile(backend: backend)
  return profile if profile[:ok] == false

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