Module: Spoom::Context::Sorbet

Extended by:
T::Helpers
Defined in:
lib/spoom/context/sorbet.rb

Overview

Sorbet features for a context

Instance Method Summary collapse

Instance Method Details

#has_sorbet_config?Boolean

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

Returns:

  • (Boolean)


106
107
108
# File 'lib/spoom/context/sorbet.rb', line 106

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?



129
130
131
# File 'lib/spoom/context/sorbet.rb', line 129

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



117
118
119
# File 'lib/spoom/context/sorbet.rb', line 117

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

#sorbet_configObject

: -> Spoom::Sorbet::Config



111
112
113
# File 'lib/spoom/context/sorbet.rb', line 111

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?



135
136
137
138
139
140
141
142
143
# File 'lib/spoom/context/sorbet.rb', line 135

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?



147
148
149
150
151
152
153
154
155
# File 'lib/spoom/context/sorbet.rb', line 147

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



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

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



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
85
86
87
# File 'lib/spoom/context/sorbet.rb', line 58

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



91
92
93
94
# File 'lib/spoom/context/sorbet.rb', line 91

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]?



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

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::MetricsParser.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



32
33
34
35
# File 'lib/spoom/context/sorbet.rb', line 32

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?



97
98
99
100
101
102
# File 'lib/spoom/context/sorbet.rb', line 97

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



123
124
125
# File 'lib/spoom/context/sorbet.rb', line 123

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