Module: Spoom::Context::Sorbet

Defined in:
lib/spoom/context/sorbet.rb

Overview

Sorbet features for a context @requires_ancestor: Context

Instance Method Summary collapse

Instance Method Details

#has_sorbet_config?Boolean

Does this context has a ‘sorbet/config` file? : -> bool

Returns:

  • (Boolean)


103
104
105
# File 'lib/spoom/context/sorbet.rb', line 103

def has_sorbet_config?
  file?(Spoom::Sorbet::CONFIG_PATH)
end

#read_file_strictness(relative_path) ⇒ Object

Read the strictness sigil from the file at ‘relative_path` (returns `nil` if no sigil) : (String relative_path) -> String?



126
127
128
# File 'lib/spoom/context/sorbet.rb', line 126

def read_file_strictness(relative_path)
  Spoom::Sorbet::Sigils.file_strictness(absolute_path_to(relative_path))
end

#read_sorbet_configObject

Read the contents of ‘sorbet/config` in this context directory : -> String



114
115
116
# File 'lib/spoom/context/sorbet.rb', line 114

def read_sorbet_config
  read(Spoom::Sorbet::CONFIG_PATH)
end

#sorbet_configObject

: -> Spoom::Sorbet::Config



108
109
110
# File 'lib/spoom/context/sorbet.rb', line 108

def sorbet_config
  Spoom::Sorbet::Config.parse_string(read_sorbet_config)
end

#sorbet_intro_commitObject

Get the commit introducing the ‘sorbet/config` file : -> Spoom::Git::Commit?



132
133
134
135
136
137
138
139
140
# File 'lib/spoom/context/sorbet.rb', line 132

def sorbet_intro_commit
  res = git_log("--diff-filter=A --format='%h %at' -1 -- sorbet/config")
  return unless res.status

  out = res.out.strip
  return if out.empty?

  Spoom::Git::Commit.parse_line(out)
end

#sorbet_removal_commitObject

Get the commit removing the ‘sorbet/config` file : -> Spoom::Git::Commit?



144
145
146
147
148
149
150
151
152
# File 'lib/spoom/context/sorbet.rb', line 144

def sorbet_removal_commit
  res = git_log("--diff-filter=D --format='%h %at' -1 -- sorbet/config")
  return unless res.status

  out = res.out.strip
  return if out.empty?

  Spoom::Git::Commit.parse_line(out)
end

#srb(*arg, sorbet_bin: nil, capture_err: true) ⇒ Object

Run ‘bundle exec srb` in this context directory : (*String arg, ?sorbet_bin: String?, ?capture_err: bool) -> ExecResult



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/spoom/context/sorbet.rb', line 11

def srb(*arg, sorbet_bin: nil, capture_err: true)
  res = if sorbet_bin
    exec("#{sorbet_bin} #{arg.join(" ")}", capture_err: capture_err)
  else
    bundle_exec("srb #{arg.join(" ")}", capture_err: capture_err)
  end

  case res.exit_code
  when Spoom::Sorbet::KILLED_CODE
    raise Spoom::Sorbet::Error::Killed.new("Sorbet was killed.", res)
  when Spoom::Sorbet::SEGFAULT_CODE
    raise Spoom::Sorbet::Error::Segfault.new("Sorbet segfaulted.", res)
  end

  res
end

#srb_files(with_config: nil, include_rbis: true) ⇒ Object

List all files typechecked by Sorbet from its ‘config` : (?with_config: Spoom::Sorbet::Config?, ?include_rbis: bool) -> Array



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/spoom/context/sorbet.rb', line 55

def srb_files(with_config: nil, include_rbis: true)
  config = with_config || sorbet_config

  allowed_extensions = config.allowed_extensions
  allowed_extensions = Spoom::Sorbet::Config::DEFAULT_ALLOWED_EXTENSIONS if allowed_extensions.empty?
  allowed_extensions -= [".rbi"] unless include_rbis

  excluded_patterns = config.ignore.map do |string|
    # We need to simulate the behavior of Sorbet's `--ignore` flag.
    #
    # From Sorbet docs on `--ignore`:
    # > Ignores input files that contain the given string in their paths (relative to the input path passed to
    # > Sorbet). Strings beginning with / match against the prefix of these relative paths; others are substring
    # > matches. Matches must be against whole folder and file names, so `foo` matches `/foo/bar.rb` and
    # > `/bar/foo/baz.rb` but not `/foo.rb` or `/foo2/bar.rb`.
    string = if string.start_with?("/")
      # Strings beginning with / match against the prefix of these relative paths
      File.join(absolute_path, string)
    else
      # Others are substring matches
      File.join(absolute_path, "**", string)
    end
    # Matches must be against whole folder and file names
    "#{string.delete_suffix("/")}{,/**}"
  end

  collector = FileCollector.new(allow_extensions: allowed_extensions, exclude_patterns: excluded_patterns)
  collector.visit_paths(config.paths.map { |path| absolute_path_to(path) })
  collector.files.map { |file| file.delete_prefix("#{absolute_path}/") }.sort
end

#srb_files_with_strictness(strictness, with_config: nil, include_rbis: true) ⇒ Object

List all files typechecked by Sorbet from its ‘config` that matches `strictness` : (String strictness, ?with_config: Spoom::Sorbet::Config?, ?include_rbis: bool) -> Array



88
89
90
91
# File 'lib/spoom/context/sorbet.rb', line 88

def srb_files_with_strictness(strictness, with_config: nil, include_rbis: true)
  srb_files(with_config: with_config, include_rbis: include_rbis)
    .select { |file| read_file_strictness(file) == strictness }
end

#srb_metrics(*arg, sorbet_bin: nil, capture_err: true) ⇒ Object

: (*String arg, ?sorbet_bin: String?, ?capture_err: bool) -> Hash[String, Integer]?



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/spoom/context/sorbet.rb', line 35

def srb_metrics(*arg, sorbet_bin: nil, capture_err: true)
  metrics_file = "metrics.tmp"

  T.unsafe(self).srb_tc(
    "--metrics-file",
    metrics_file,
    *arg,
    sorbet_bin: sorbet_bin,
    capture_err: capture_err,
  )
  return unless file?(metrics_file)

  metrics_path = absolute_path_to(metrics_file)
  metrics = Spoom::Sorbet::Metrics::MetricsFileParser.parse_file(metrics_path)
  remove!(metrics_file)
  metrics
end

#srb_tc(*arg, sorbet_bin: nil, capture_err: true) ⇒ Object

: (*String arg, ?sorbet_bin: String?, ?capture_err: bool) -> ExecResult



29
30
31
32
# File 'lib/spoom/context/sorbet.rb', line 29

def srb_tc(*arg, sorbet_bin: nil, capture_err: true)
  arg.prepend("tc") unless sorbet_bin
  T.unsafe(self).srb(*arg, sorbet_bin: sorbet_bin, capture_err: capture_err)
end

#srb_version(*arg, sorbet_bin: nil, capture_err: true) ⇒ Object

: (*String arg, ?sorbet_bin: String?, ?capture_err: bool) -> String?



94
95
96
97
98
99
# File 'lib/spoom/context/sorbet.rb', line 94

def srb_version(*arg, sorbet_bin: nil, capture_err: true)
  res = T.unsafe(self).srb_tc("--no-config", "--version", *arg, sorbet_bin: sorbet_bin, capture_err: capture_err)
  return unless res.status

  res.out.split(" ")[2]
end

#write_sorbet_config!(contents, append: false) ⇒ Object

Set the ‘contents` of `sorbet/config` in this context directory : (String contents, ?append: bool) -> void



120
121
122
# File 'lib/spoom/context/sorbet.rb', line 120

def write_sorbet_config!(contents, append: false)
  write!(Spoom::Sorbet::CONFIG_PATH, contents, append: append)
end