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?

Signature:

  • -> bool

Returns:

  • (Boolean)


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

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)

Signature:

  • (String relative_path) -> String?



131
132
133
# File 'lib/spoom/context/sorbet.rb', line 131

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

Signature:

  • -> String



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

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

#sorbet_configObject

Signature:

  • -> Spoom::Sorbet::Config



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

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

#sorbet_intro_commitObject

Get the commit introducing the sorbet/config file

Signature:

  • -> Spoom::Git::Commit?



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

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

Signature:

  • -> Spoom::Git::Commit?



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

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

Signature:

  • (*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

Signature:

  • (?with_config: Spoom::Sorbet::Config?, ?include_rbis: bool) -> Array[String]



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
88
89
# File 'lib/spoom/context/sorbet.rb', line 60

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

Signature:

  • (String strictness, ?with_config: Spoom::Sorbet::Config?, ?include_rbis: bool) -> Array[String]



93
94
95
96
# File 'lib/spoom/context/sorbet.rb', line 93

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

Signature:

  • (*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
52
53
54
55
56
# 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,
  )

  metrics_path = absolute_path_to(metrics_file)

  begin
    metrics = Spoom::Sorbet::Metrics::MetricsFileParser.parse_file(metrics_path)
  rescue Errno::ENOENT, Errno::EACCES
    return
  end

  remove!(metrics_file)
  metrics
end

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

Signature:

  • (*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

Signature:

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



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

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

Signature:

  • (String contents, ?append: bool) -> void



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

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