spoom 1.1.11 → 1.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +6 -0
- data/Rakefile +1 -0
- data/lib/spoom/cli/bump.rb +17 -12
- data/lib/spoom/cli/coverage.rb +20 -17
- data/lib/spoom/cli/helper.rb +6 -5
- data/lib/spoom/cli/lsp.rb +4 -3
- data/lib/spoom/cli/run.rb +18 -8
- data/lib/spoom/cli.rb +6 -4
- data/lib/spoom/context.rb +219 -0
- data/lib/spoom/coverage/d3/base.rb +12 -8
- data/lib/spoom/coverage/d3/circle_map.rb +40 -37
- data/lib/spoom/coverage/d3/pie.rb +41 -30
- data/lib/spoom/coverage/d3/timeline.rb +95 -88
- data/lib/spoom/coverage/d3.rb +72 -70
- data/lib/spoom/coverage/report.rb +6 -6
- data/lib/spoom/coverage/snapshot.rb +65 -34
- data/lib/spoom/coverage.rb +104 -81
- data/lib/spoom/file_tree.rb +5 -3
- data/lib/spoom/git.rb +102 -96
- data/lib/spoom/printer.rb +4 -0
- data/lib/spoom/sorbet/errors.rb +30 -12
- data/lib/spoom/sorbet/lsp/base.rb +1 -1
- data/lib/spoom/sorbet/lsp/errors.rb +23 -17
- data/lib/spoom/sorbet/lsp/structures.rb +86 -55
- data/lib/spoom/sorbet/lsp.rb +78 -70
- data/lib/spoom/sorbet/metrics.rb +18 -16
- data/lib/spoom/sorbet/sigils.rb +59 -54
- data/lib/spoom/sorbet.rb +17 -14
- data/lib/spoom/timeline.rb +6 -5
- data/lib/spoom/version.rb +1 -1
- data/lib/spoom.rb +43 -25
- metadata +20 -20
- data/lib/spoom/test_helpers/project.rb +0 -138
data/lib/spoom/git.rb
CHANGED
@@ -6,119 +6,125 @@ require "time"
|
|
6
6
|
module Spoom
|
7
7
|
# Execute git commands
|
8
8
|
module Git
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
exit_code: 1
|
19
|
-
) unless File.directory?(path)
|
20
|
-
|
21
|
-
T.unsafe(Open3).popen3(command, *arg, chdir: path) do |_, stdout, stderr, thread|
|
22
|
-
status = T.cast(thread.value, Process::Status)
|
23
|
-
ExecResult.new(
|
24
|
-
out: stdout.read,
|
25
|
-
err: stderr.read,
|
26
|
-
status: T.must(status.success?),
|
27
|
-
exit_code: T.must(status.exitstatus)
|
28
|
-
)
|
9
|
+
class Commit < T::Struct
|
10
|
+
extend T::Sig
|
11
|
+
|
12
|
+
const :sha, String
|
13
|
+
const :time, Time
|
14
|
+
|
15
|
+
sig { returns(Integer) }
|
16
|
+
def timestamp
|
17
|
+
time.to_i
|
29
18
|
end
|
30
19
|
end
|
31
20
|
|
32
|
-
|
21
|
+
class << self
|
22
|
+
extend T::Sig
|
23
|
+
|
24
|
+
# Execute a `command`
|
25
|
+
sig { params(command: String, arg: String, path: String).returns(ExecResult) }
|
26
|
+
def exec(command, *arg, path: ".")
|
27
|
+
return ExecResult.new(
|
28
|
+
out: "",
|
29
|
+
err: "Error: `#{path}` is not a directory.",
|
30
|
+
status: false,
|
31
|
+
exit_code: 1,
|
32
|
+
) unless File.directory?(path)
|
33
|
+
|
34
|
+
T.unsafe(Open3).popen3(command, *arg, chdir: path) do |_, stdout, stderr, thread|
|
35
|
+
status = T.cast(thread.value, Process::Status)
|
36
|
+
ExecResult.new(
|
37
|
+
out: stdout.read,
|
38
|
+
err: stderr.read,
|
39
|
+
status: T.must(status.success?),
|
40
|
+
exit_code: T.must(status.exitstatus),
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
33
44
|
|
34
|
-
|
35
|
-
def self.checkout(*arg, path: ".")
|
36
|
-
exec("git checkout -q #{arg.join(' ')}", path: path)
|
37
|
-
end
|
45
|
+
# Git commands
|
38
46
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
47
|
+
sig { params(arg: String, path: String).returns(ExecResult) }
|
48
|
+
def checkout(*arg, path: ".")
|
49
|
+
exec("git checkout -q #{arg.join(" ")}", path: path)
|
50
|
+
end
|
43
51
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
52
|
+
sig { params(arg: String, path: String).returns(ExecResult) }
|
53
|
+
def diff(*arg, path: ".")
|
54
|
+
exec("git diff #{arg.join(" ")}", path: path)
|
55
|
+
end
|
48
56
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
57
|
+
sig { params(arg: String, path: String).returns(ExecResult) }
|
58
|
+
def log(*arg, path: ".")
|
59
|
+
exec("git log #{arg.join(" ")}", path: path)
|
60
|
+
end
|
53
61
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
62
|
+
sig { params(arg: String, path: String).returns(ExecResult) }
|
63
|
+
def show(*arg, path: ".")
|
64
|
+
exec("git show #{arg.join(" ")}", path: path)
|
65
|
+
end
|
58
66
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
result.out.strip
|
64
|
-
end
|
67
|
+
sig { params(path: String).returns(T.nilable(String)) }
|
68
|
+
def current_branch(path: ".")
|
69
|
+
result = exec("git branch --show-current", path: path)
|
70
|
+
return nil unless result.status
|
65
71
|
|
66
|
-
|
72
|
+
result.out.strip
|
73
|
+
end
|
67
74
|
|
68
|
-
|
69
|
-
sig { params(sha: String, path: String).returns(T.nilable(Integer)) }
|
70
|
-
def self.commit_timestamp(sha, path: ".")
|
71
|
-
result = show("--no-notes --no-patch --pretty=%at #{sha}", path: path)
|
72
|
-
return nil unless result.status
|
73
|
-
result.out.strip.to_i
|
74
|
-
end
|
75
|
+
# Utils
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
epoch_to_time(timestamp.to_s)
|
82
|
-
end
|
77
|
+
# Get the last commit in the currently checked out branch
|
78
|
+
sig { params(path: String).returns(T.nilable(Commit)) }
|
79
|
+
def last_commit(path: ".")
|
80
|
+
result = log("HEAD --format='%h %at' -1", path: path)
|
81
|
+
return nil unless result.status
|
83
82
|
|
84
|
-
|
85
|
-
|
86
|
-
def self.last_commit(path: ".")
|
87
|
-
result = rev_parse("HEAD", path: path)
|
88
|
-
return nil unless result.status
|
89
|
-
result.out.strip
|
90
|
-
end
|
83
|
+
out = result.out.strip
|
84
|
+
return nil if out.empty?
|
91
85
|
|
92
|
-
|
93
|
-
|
94
|
-
def self.epoch_to_time(timestamp)
|
95
|
-
Time.strptime(timestamp, "%s")
|
96
|
-
end
|
86
|
+
parse_commit(out)
|
87
|
+
end
|
97
88
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
89
|
+
# Is there uncommited changes in `path`?
|
90
|
+
sig { params(path: String).returns(T::Boolean) }
|
91
|
+
def workdir_clean?(path: ".")
|
92
|
+
diff("HEAD", path: path).out.empty?
|
93
|
+
end
|
103
94
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
out = result.out.strip
|
110
|
-
return nil if out.empty?
|
111
|
-
out
|
112
|
-
end
|
95
|
+
# Get the commit introducing the `sorbet/config` file
|
96
|
+
sig { params(path: String).returns(T.nilable(Commit)) }
|
97
|
+
def sorbet_intro_commit(path: ".")
|
98
|
+
result = log("--diff-filter=A --format='%h %at' -1 -- sorbet/config", path: path)
|
99
|
+
return nil unless result.status
|
113
100
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
101
|
+
out = result.out.strip
|
102
|
+
return nil if out.empty?
|
103
|
+
|
104
|
+
parse_commit(out)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Get the commit removing the `sorbet/config` file
|
108
|
+
sig { params(path: String).returns(T.nilable(Commit)) }
|
109
|
+
def sorbet_removal_commit(path: ".")
|
110
|
+
result = log("--diff-filter=D --format='%h %at' -1 -- sorbet/config", path: path)
|
111
|
+
return nil unless result.status
|
112
|
+
|
113
|
+
out = result.out.strip
|
114
|
+
return nil if out.empty?
|
115
|
+
|
116
|
+
parse_commit(out)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Parse a line formated as `%h %at` into a `Commit`
|
120
|
+
sig { params(string: String).returns(T.nilable(Commit)) }
|
121
|
+
def parse_commit(string)
|
122
|
+
sha, epoch = string.split(" ", 2)
|
123
|
+
return nil unless sha && epoch
|
124
|
+
|
125
|
+
time = Time.strptime(epoch, "%s")
|
126
|
+
Commit.new(sha: sha, time: time)
|
127
|
+
end
|
122
128
|
end
|
123
129
|
end
|
124
130
|
end
|
data/lib/spoom/printer.rb
CHANGED
@@ -38,6 +38,7 @@ module Spoom
|
|
38
38
|
sig { params(string: T.nilable(String)).void }
|
39
39
|
def print(string)
|
40
40
|
return unless string
|
41
|
+
|
41
42
|
@out.print(string)
|
42
43
|
end
|
43
44
|
|
@@ -47,6 +48,7 @@ module Spoom
|
|
47
48
|
sig { params(string: T.nilable(String), color: Color).void }
|
48
49
|
def print_colored(string, *color)
|
49
50
|
return unless string
|
51
|
+
|
50
52
|
string = T.unsafe(self).colorize(string, *color)
|
51
53
|
@out.print(string)
|
52
54
|
end
|
@@ -61,6 +63,7 @@ module Spoom
|
|
61
63
|
sig { params(string: T.nilable(String)).void }
|
62
64
|
def printl(string)
|
63
65
|
return unless string
|
66
|
+
|
64
67
|
printt
|
65
68
|
print(string)
|
66
69
|
printn
|
@@ -76,6 +79,7 @@ module Spoom
|
|
76
79
|
sig { params(string: String, color: Spoom::Color).returns(String) }
|
77
80
|
def colorize(string, *color)
|
78
81
|
return string unless @colors
|
82
|
+
|
79
83
|
T.unsafe(self).set_color(string, *color)
|
80
84
|
end
|
81
85
|
end
|
data/lib/spoom/sorbet/errors.rb
CHANGED
@@ -4,10 +4,16 @@
|
|
4
4
|
module Spoom
|
5
5
|
module Sorbet
|
6
6
|
module Errors
|
7
|
-
extend T::Sig
|
8
|
-
|
9
7
|
DEFAULT_ERROR_URL_BASE = "https://srb.help/"
|
10
8
|
|
9
|
+
class << self
|
10
|
+
extend T::Sig
|
11
|
+
|
12
|
+
sig { params(errors: T::Array[Error]).returns(T::Array[Error]) }
|
13
|
+
def sort_errors_by_code(errors)
|
14
|
+
errors.sort_by { |e| [e.code, e.file, e.line, e.message] }
|
15
|
+
end
|
16
|
+
end
|
11
17
|
# Parse errors from Sorbet output
|
12
18
|
class Parser
|
13
19
|
extend T::Sig
|
@@ -20,10 +26,14 @@ module Spoom
|
|
20
26
|
"or set SORBET_SILENCE_DEV_MESSAGE=1 in your shell environment.",
|
21
27
|
], T::Array[String])
|
22
28
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
29
|
+
class << self
|
30
|
+
extend T::Sig
|
31
|
+
|
32
|
+
sig { params(output: String, error_url_base: String).returns(T::Array[Error]) }
|
33
|
+
def parse_string(output, error_url_base: DEFAULT_ERROR_URL_BASE)
|
34
|
+
parser = Spoom::Sorbet::Errors::Parser.new(error_url_base: error_url_base)
|
35
|
+
parser.parse(output)
|
36
|
+
end
|
27
37
|
end
|
28
38
|
|
29
39
|
sig { params(error_url_base: String).void }
|
@@ -85,12 +95,14 @@ module Spoom
|
|
85
95
|
sig { params(error: Error).void }
|
86
96
|
def open_error(error)
|
87
97
|
raise "Error: Already parsing an error!" if @current_error
|
98
|
+
|
88
99
|
@current_error = error
|
89
100
|
end
|
90
101
|
|
91
102
|
sig { void }
|
92
103
|
def close_error
|
93
104
|
raise "Error: Not already parsing an error!" unless @current_error
|
105
|
+
|
94
106
|
@errors << @current_error
|
95
107
|
@current_error = nil
|
96
108
|
end
|
@@ -98,6 +110,11 @@ module Spoom
|
|
98
110
|
sig { params(line: String).void }
|
99
111
|
def append_error(line)
|
100
112
|
raise "Error: Not already parsing an error!" unless @current_error
|
113
|
+
|
114
|
+
filepath_match = line.match(/^ (.*?):\d+/)
|
115
|
+
if filepath_match && filepath_match[1]
|
116
|
+
@current_error.files_from_error_sections << T.must(filepath_match[1])
|
117
|
+
end
|
101
118
|
@current_error.more << line
|
102
119
|
end
|
103
120
|
end
|
@@ -115,13 +132,17 @@ module Spoom
|
|
115
132
|
sig { returns(T::Array[String]) }
|
116
133
|
attr_reader :more
|
117
134
|
|
135
|
+
# Other files associated with the error
|
136
|
+
sig { returns(T::Set[String]) }
|
137
|
+
attr_reader :files_from_error_sections
|
138
|
+
|
118
139
|
sig do
|
119
140
|
params(
|
120
141
|
file: T.nilable(String),
|
121
142
|
line: T.nilable(Integer),
|
122
143
|
message: T.nilable(String),
|
123
144
|
code: T.nilable(Integer),
|
124
|
-
more: T::Array[String]
|
145
|
+
more: T::Array[String],
|
125
146
|
).void
|
126
147
|
end
|
127
148
|
def initialize(file, line, message, code, more = [])
|
@@ -130,12 +151,14 @@ module Spoom
|
|
130
151
|
@message = message
|
131
152
|
@code = code
|
132
153
|
@more = more
|
154
|
+
@files_from_error_sections = T.let(Set.new, T::Set[String])
|
133
155
|
end
|
134
156
|
|
135
157
|
# By default errors are sorted by location
|
136
158
|
sig { params(other: T.untyped).returns(Integer) }
|
137
159
|
def <=>(other)
|
138
160
|
return 0 unless other.is_a?(Error)
|
161
|
+
|
139
162
|
[file, line, code, message] <=> [other.file, other.line, other.code, other.message]
|
140
163
|
end
|
141
164
|
|
@@ -144,11 +167,6 @@ module Spoom
|
|
144
167
|
"#{file}:#{line}: #{message} (#{code})"
|
145
168
|
end
|
146
169
|
end
|
147
|
-
|
148
|
-
sig { params(errors: T::Array[Error]).returns(T::Array[Error]) }
|
149
|
-
def self.sort_errors_by_code(errors)
|
150
|
-
errors.sort_by { |e| [e.code, e.file, e.line, e.message] }
|
151
|
-
end
|
152
170
|
end
|
153
171
|
end
|
154
172
|
end
|
@@ -16,18 +16,23 @@ module Spoom
|
|
16
16
|
sig { returns(T::Array[Diagnostic]) }
|
17
17
|
attr_reader :diagnostics
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
class << self
|
20
|
+
extend T::Sig
|
21
|
+
|
22
|
+
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(Diagnostics) }
|
23
|
+
def from_json(json)
|
24
|
+
Diagnostics.new(
|
25
|
+
json["uri"],
|
26
|
+
json["diagnostics"].map { |d| Diagnostic.from_json(d) },
|
27
|
+
)
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
sig { params(uri: String, diagnostics: T::Array[Diagnostic]).void }
|
28
32
|
def initialize(uri, diagnostics)
|
29
33
|
@uri = uri
|
30
34
|
@diagnostics = diagnostics
|
35
|
+
super()
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
@@ -38,25 +43,26 @@ module Spoom
|
|
38
43
|
sig { returns(Integer) }
|
39
44
|
attr_reader :code
|
40
45
|
|
41
|
-
sig { returns(String) }
|
42
|
-
attr_reader :message
|
43
|
-
|
44
46
|
sig { returns(T::Hash[T.untyped, T.untyped]) }
|
45
47
|
attr_reader :data
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
class << self
|
50
|
+
extend T::Sig
|
51
|
+
|
52
|
+
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(ResponseError) }
|
53
|
+
def from_json(json)
|
54
|
+
ResponseError.new(
|
55
|
+
json["code"],
|
56
|
+
json["message"],
|
57
|
+
json["data"],
|
58
|
+
)
|
59
|
+
end
|
54
60
|
end
|
55
61
|
|
56
62
|
sig { params(code: Integer, message: String, data: T::Hash[T.untyped, T.untyped]).void }
|
57
63
|
def initialize(code, message, data)
|
64
|
+
super(message)
|
58
65
|
@code = code
|
59
|
-
@message = message
|
60
66
|
@data = data
|
61
67
|
end
|
62
68
|
end
|
@@ -23,12 +23,16 @@ module Spoom
|
|
23
23
|
const :contents, String
|
24
24
|
const :range, T.nilable(Range)
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
class << self
|
27
|
+
extend T::Sig
|
28
|
+
|
29
|
+
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(Hover) }
|
30
|
+
def from_json(json)
|
31
|
+
Hover.new(
|
32
|
+
contents: json["contents"]["value"],
|
33
|
+
range: json["range"] ? Range.from_json(json["range"]) : nil,
|
34
|
+
)
|
35
|
+
end
|
32
36
|
end
|
33
37
|
|
34
38
|
sig { override.params(printer: SymbolPrinter).void }
|
@@ -50,12 +54,16 @@ module Spoom
|
|
50
54
|
const :line, Integer
|
51
55
|
const :char, Integer
|
52
56
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
class << self
|
58
|
+
extend T::Sig
|
59
|
+
|
60
|
+
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(Position) }
|
61
|
+
def from_json(json)
|
62
|
+
Position.new(
|
63
|
+
line: json["line"].to_i,
|
64
|
+
char: json["character"].to_i,
|
65
|
+
)
|
66
|
+
end
|
59
67
|
end
|
60
68
|
|
61
69
|
sig { override.params(printer: SymbolPrinter).void }
|
@@ -76,12 +84,16 @@ module Spoom
|
|
76
84
|
const :start, Position
|
77
85
|
const :end, Position
|
78
86
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
87
|
+
class << self
|
88
|
+
extend T::Sig
|
89
|
+
|
90
|
+
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(Range) }
|
91
|
+
def from_json(json)
|
92
|
+
Range.new(
|
93
|
+
start: Position.from_json(json["start"]),
|
94
|
+
end: Position.from_json(json["end"]),
|
95
|
+
)
|
96
|
+
end
|
85
97
|
end
|
86
98
|
|
87
99
|
sig { override.params(printer: SymbolPrinter).void }
|
@@ -104,12 +116,16 @@ module Spoom
|
|
104
116
|
const :uri, String
|
105
117
|
const :range, LSP::Range
|
106
118
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
119
|
+
class << self
|
120
|
+
extend T::Sig
|
121
|
+
|
122
|
+
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(Location) }
|
123
|
+
def from_json(json)
|
124
|
+
Location.new(
|
125
|
+
uri: json["uri"],
|
126
|
+
range: Range.from_json(json["range"]),
|
127
|
+
)
|
128
|
+
end
|
113
129
|
end
|
114
130
|
|
115
131
|
sig { override.params(printer: SymbolPrinter).void }
|
@@ -132,20 +148,24 @@ module Spoom
|
|
132
148
|
const :doc, Object # TODO
|
133
149
|
const :params, T::Array[T.untyped] # TODO
|
134
150
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
151
|
+
class << self
|
152
|
+
extend T::Sig
|
153
|
+
|
154
|
+
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(SignatureHelp) }
|
155
|
+
def from_json(json)
|
156
|
+
SignatureHelp.new(
|
157
|
+
label: json["label"],
|
158
|
+
doc: json["documentation"],
|
159
|
+
params: json["parameters"],
|
160
|
+
)
|
161
|
+
end
|
142
162
|
end
|
143
163
|
|
144
164
|
sig { override.params(printer: SymbolPrinter).void }
|
145
165
|
def accept_printer(printer)
|
146
166
|
printer.print(label)
|
147
167
|
printer.print("(")
|
148
|
-
printer.print(params.map { |l| "#{l[
|
168
|
+
printer.print(params.map { |l| "#{l["label"]}: #{l["documentation"]}" }.join(", "))
|
149
169
|
printer.print(")")
|
150
170
|
end
|
151
171
|
|
@@ -164,14 +184,18 @@ module Spoom
|
|
164
184
|
const :message, String
|
165
185
|
const :informations, Object
|
166
186
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
187
|
+
class << self
|
188
|
+
extend T::Sig
|
189
|
+
|
190
|
+
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(Diagnostic) }
|
191
|
+
def from_json(json)
|
192
|
+
Diagnostic.new(
|
193
|
+
range: Range.from_json(json["range"]),
|
194
|
+
code: json["code"].to_i,
|
195
|
+
message: json["message"],
|
196
|
+
informations: json["relatedInformation"],
|
197
|
+
)
|
198
|
+
end
|
175
199
|
end
|
176
200
|
|
177
201
|
sig { override.params(printer: SymbolPrinter).void }
|
@@ -196,35 +220,40 @@ module Spoom
|
|
196
220
|
const :range, T.nilable(Range)
|
197
221
|
const :children, T::Array[DocumentSymbol]
|
198
222
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
223
|
+
class << self
|
224
|
+
extend T::Sig
|
225
|
+
|
226
|
+
sig { params(json: T::Hash[T.untyped, T.untyped]).returns(DocumentSymbol) }
|
227
|
+
def from_json(json)
|
228
|
+
DocumentSymbol.new(
|
229
|
+
name: json["name"],
|
230
|
+
detail: json["detail"],
|
231
|
+
kind: json["kind"],
|
232
|
+
location: json["location"] ? Location.from_json(json["location"]) : nil,
|
233
|
+
range: json["range"] ? Range.from_json(json["range"]) : nil,
|
234
|
+
children: json["children"] ? json["children"].map { |symbol| DocumentSymbol.from_json(symbol) } : [],
|
235
|
+
)
|
236
|
+
end
|
209
237
|
end
|
210
238
|
|
211
239
|
sig { override.params(printer: SymbolPrinter).void }
|
212
240
|
def accept_printer(printer)
|
213
241
|
h = serialize.hash
|
214
242
|
return if printer.seen.include?(h)
|
243
|
+
|
215
244
|
printer.seen.add(h)
|
216
245
|
|
217
246
|
printer.printt
|
218
247
|
printer.print(kind_string)
|
219
|
-
printer.print(
|
248
|
+
printer.print(" ")
|
220
249
|
printer.print_colored(name, Color::BLUE, Color::BOLD)
|
221
|
-
printer.print_colored(
|
250
|
+
printer.print_colored(" (", Color::LIGHT_BLACK)
|
222
251
|
if range
|
223
252
|
printer.print_object(range)
|
224
253
|
elsif location
|
225
254
|
printer.print_object(location)
|
226
255
|
end
|
227
|
-
printer.print_colored(
|
256
|
+
printer.print_colored(")", Color::LIGHT_BLACK)
|
228
257
|
printer.printn
|
229
258
|
unless children.empty?
|
230
259
|
printer.indent
|
@@ -288,7 +317,7 @@ module Spoom
|
|
288
317
|
out: T.any(IO, StringIO),
|
289
318
|
colors: T::Boolean,
|
290
319
|
indent_level: Integer,
|
291
|
-
prefix: T.nilable(String)
|
320
|
+
prefix: T.nilable(String),
|
292
321
|
).void
|
293
322
|
end
|
294
323
|
def initialize(out: $stdout, colors: true, indent_level: 0, prefix: nil)
|
@@ -303,6 +332,7 @@ module Spoom
|
|
303
332
|
sig { params(object: T.nilable(PrintableSymbol)).void }
|
304
333
|
def print_object(object)
|
305
334
|
return unless object
|
335
|
+
|
306
336
|
object.accept_printer(self)
|
307
337
|
end
|
308
338
|
|
@@ -315,6 +345,7 @@ module Spoom
|
|
315
345
|
def clean_uri(uri)
|
316
346
|
prefix = self.prefix
|
317
347
|
return uri unless prefix
|
348
|
+
|
318
349
|
uri.delete_prefix(prefix)
|
319
350
|
end
|
320
351
|
|
@@ -322,7 +353,7 @@ module Spoom
|
|
322
353
|
def print_list(objects)
|
323
354
|
objects.each do |object|
|
324
355
|
printt
|
325
|
-
print
|
356
|
+
print("* ")
|
326
357
|
print_object(object)
|
327
358
|
printn
|
328
359
|
end
|