Module: MilkTea::CLI::CommandDebug

Included in:
MilkTea::CLI
Defined in:
lib/milk_tea/tooling/cli/commands/debug.rb

Instance Method Summary collapse

Instance Method Details

#debug_commandObject



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/milk_tea/tooling/cli/commands/debug.rb', line 6

def debug_command
  unless @argv.any?
    @err.puts("missing source file path")
    print_usage(@err)
    return 1
  end

  resolution = extract_resolution_flags!
  input_paths = @argv.dup
  return 1 unless ensure_known_source_operands!("debug", input_paths)

  path = expand_source_paths(input_paths).first
  unless path
    @err.puts("no .mt files found in #{input_paths.join(', ')}")
    return 1
  end

  ensure_current_lockfile!(path) if resolution[:frozen]

  source = read_source_file(path)
  resolved_path = File.expand_path(path)

  tokens = MilkTea::Lexer.lex(source, path: resolved_path)

  parse_result = MilkTea::Parser.parse_collecting_errors(source, path: resolved_path)
  ast = parse_result.ast
  parse_errors = parse_result.errors.dup

  facts = nil
  snapshot = nil
  loader_ast = ast

  if ast && parse_errors.empty?
    begin
      loader = make_module_loader(path, locked: resolution[:locked], platform: ModuleLoader.default_host_platform)
      loader_ast = loader.load_file(resolved_path)

      import_result = loader.send(:imported_modules_for_ast_collecting_errors, loader_ast, importer_path: resolved_path)
      import_errors = import_result.respond_to?(:errors) ? import_result.errors : []
      parse_errors.concat(import_errors) unless import_errors.empty?

      snapshot = MilkTea::SemanticAnalyzer.tooling_snapshot(
        loader_ast,
        imported_modules: import_result.modules,
        allow_missing_imports: true,
        path: resolved_path,
      )
      facts = snapshot&.facts
    rescue MilkTea::LexError, MilkTea::ParseError, ModuleLoadError, SemanticError => e
      parse_errors << e
    end
  end

  text = DebugInfoFormatter.format_all(
    content: source,
    tokens: tokens,
    ast: loader_ast,
    parse_errors: parse_errors,
    facts: facts,
    snapshot: snapshot,
    path: resolved_path,
  )

  @out.puts(text)
  0
rescue MilkTea::LexError => e
  @err.puts(ErrorFormatter.format(e, color: error_color?(@err)))
  1
end