spoom 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,36 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require 'stringio'
5
-
6
- module Spoom
7
- module Cli
8
- module Commands
9
- class Base < Thor
10
- no_commands do
11
- def say_error(message, status = "Error")
12
- status = set_color(status, :red)
13
-
14
- buffer = StringIO.new
15
- buffer << "#{status}: #{message}"
16
- buffer << "\n" unless message.end_with?("\n")
17
-
18
- $stderr.print(buffer.string)
19
- $stderr.flush
20
- end
21
-
22
- def in_sorbet_project?
23
- File.file?(Spoom::Config::SORBET_CONFIG)
24
- end
25
-
26
- def in_sorbet_project!
27
- unless in_sorbet_project?
28
- say_error("not in a Sorbet project (no sorbet/config)")
29
- exit(1)
30
- end
31
- end
32
- end
33
- end
34
- end
35
- end
36
- end
@@ -1,67 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require_relative "base"
5
- require_relative "../../sorbet/config"
6
-
7
- module Spoom
8
- module Cli
9
- module Commands
10
- class Config < Base
11
- default_task :show
12
-
13
- desc "show", "show Sorbet config"
14
- def show
15
- in_sorbet_project!
16
- config = Spoom::Sorbet::Config.parse_file(Spoom::Config::SORBET_CONFIG)
17
-
18
- say("Found Sorbet config at `#{Spoom::Config::SORBET_CONFIG}`.")
19
-
20
- say("\nPaths typechecked:")
21
- if config.paths.empty?
22
- say(" * (default: .)")
23
- else
24
- config.paths.each do |path|
25
- say(" * #{path}")
26
- end
27
- end
28
-
29
- say("\nPaths ignored:")
30
- if config.ignore.empty?
31
- say(" * (default: none)")
32
- else
33
- config.ignore.each do |path|
34
- say(" * #{path}")
35
- end
36
- end
37
-
38
- say("\nAllowed extensions:")
39
- if config.allowed_extensions.empty?
40
- say(" * .rb (default)")
41
- say(" * .rbi (default)")
42
- else
43
- config.allowed_extensions.each do |ext|
44
- say(" * #{ext}")
45
- end
46
- end
47
- end
48
-
49
- desc "files", "show files matching Sorbet config"
50
- def files
51
- in_sorbet_project!
52
- config = Spoom::Sorbet::Config.parse_file(Spoom::Config::SORBET_CONFIG)
53
- files = Spoom::Sorbet.srb_files(config)
54
-
55
- say("Files matching `#{Spoom::Config::SORBET_CONFIG}`:")
56
- if files.empty?
57
- say(" NONE")
58
- else
59
- files.each do |path|
60
- say(" * #{path}")
61
- end
62
- end
63
- end
64
- end
65
- end
66
- end
67
- end
@@ -1,156 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require 'shellwords'
5
-
6
- require_relative "base"
7
- require_relative "../symbol_printer"
8
- require_relative "../../sorbet/lsp"
9
-
10
- module Spoom
11
- module Cli
12
- module Commands
13
- class LSP < Base
14
- default_task :show
15
-
16
- desc "interactive", "interactive LSP mode"
17
- def show
18
- in_sorbet_project!
19
- lsp = lsp_client
20
- # TODO: run interactive mode
21
- puts lsp
22
- end
23
-
24
- desc "list", "list all known symbols"
25
- # TODO: options, filter, limit, kind etc.. filter rbi
26
- def list
27
- run do |client|
28
- Dir["**/*.rb"].each do |file|
29
- res = client.document_symbols(file.to_uri)
30
- next if res.empty?
31
- puts "Symbols from `#{file}`:"
32
- SymbolPrinter.print_object(res, options["no_color"])
33
- end
34
- end
35
- end
36
-
37
- desc "hover", "request hover informations"
38
- # TODO: options, filter, limit, kind etc.. filter rbi
39
- def hover(file, line, col)
40
- run do |client|
41
- res = client.hover(file.to_uri, line.to_i, col.to_i)
42
- say "Hovering `#{file}:#{line}:#{col}`:"
43
- if res
44
- SymbolPrinter.print_object(res, options["no_color"])
45
- else
46
- puts "<no data>"
47
- end
48
- end
49
- end
50
-
51
- desc "defs", "list definitions of a symbol"
52
- # TODO: options, filter, limit, kind etc.. filter rbi
53
- def defs(file, line, col)
54
- run do |client|
55
- res = client.definitions(file.to_uri, line.to_i, col.to_i)
56
- puts "Definitions for `#{file}:#{line}:#{col}`:"
57
- SymbolPrinter.print_list(res, options["no_color"])
58
- end
59
- end
60
-
61
- desc "find", "find symbols matching a query"
62
- # TODO: options, filter, limit, kind etc.. filter rbi
63
- def find(query)
64
- run do |client|
65
- res = client.symbols(query)
66
- puts "Symbols matching `#{query}`:"
67
- printer = SymbolPrinter.new(2, options["no_color"])
68
- res.each do |symbol|
69
- next if symbol.location.uri.start_with?("https")
70
- printer.visit(symbol)
71
- end
72
- end
73
- end
74
-
75
- desc "symbols", "list symbols from a file"
76
- # TODO: options, filter, limit, kind etc.. filter rbi
77
- def symbols(file)
78
- run do |client|
79
- res = client.document_symbols(file.to_uri)
80
- puts "Symbols from `#{file}`:"
81
- SymbolPrinter.print_object(res, options["no_color"])
82
- end
83
- end
84
-
85
- desc "refs", "list references to a symbol"
86
- # TODO: options, filter, limit, kind etc.. filter rbi
87
- def refs(file, line, col)
88
- run do |client|
89
- res = client.references(file.to_uri, line.to_i, col.to_i)
90
- puts "References to `#{file}:#{line}:#{col}`:"
91
- SymbolPrinter.print_list(res, options["no_color"])
92
- end
93
- end
94
-
95
- desc "sigs", "list signatures for a symbol"
96
- # TODO: options, filter, limit, kind etc.. filter rbi
97
- def sigs(file, line, col)
98
- run do |client|
99
- res = client.signatures(file.to_uri, line.to_i, col.to_i)
100
- puts "Signature for `#{file}:#{line}:#{col}`:"
101
- SymbolPrinter.print_list(res, options["no_color"])
102
- end
103
- end
104
-
105
- desc "types", "display type of a symbol"
106
- # TODO: options, filter, limit, kind etc.. filter rbi
107
- def types(file, line, col)
108
- run do |client|
109
- res = client.type_definitions(file.to_uri, line.to_i, col.to_i)
110
- say "Type for `#{file}:#{line}:#{col}`:"
111
- SymbolPrinter.print_list(res, options["no_color"])
112
- end
113
- end
114
-
115
- no_commands do
116
- def lsp_client
117
- in_sorbet_project!
118
- client = Spoom::LSP::Client.new(
119
- Spoom::Config::SORBET_PATH,
120
- "--lsp",
121
- "--enable-all-experimental-lsp-features",
122
- "--disable-watchman",
123
- )
124
- client.open(Spoom::Config::WORKSPACE_PATH)
125
- client
126
- end
127
-
128
- def run(&block)
129
- client = lsp_client
130
- block.call(client)
131
- rescue Spoom::LSP::Error::Diagnostics => err
132
- say_error("Sorbet returned typechecking errors for `#{err.uri.from_uri}`")
133
- err.diagnostics.each do |d|
134
- say_error("#{d.message} (#{d.code})", " #{d.range}")
135
- end
136
- exit(1)
137
- rescue Spoom::LSP::Error::BadHeaders => err
138
- say_error("Sorbet didn't answer correctly (#{err.message})")
139
- exit(1)
140
- rescue Spoom::LSP::Error => err
141
- say_error(err.message)
142
- exit(1)
143
- ensure
144
- begin
145
- client&.close
146
- rescue
147
- # We can't do much if Sorbet refuse to close.
148
- # We kill the parent process and let the child be killed.
149
- exit(1)
150
- end
151
- end
152
- end
153
- end
154
- end
155
- end
156
- end
@@ -1,92 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require_relative "base"
5
-
6
- module Spoom
7
- module Cli
8
- module Commands
9
- class Run < Base
10
- default_task :tc
11
-
12
- desc "tc", "run srb tc"
13
- option :limit, type: :numeric, aliases: :l
14
- option :code, type: :numeric, aliases: :c
15
- option :sort, type: :string, aliases: :s
16
- def tc
17
- in_sorbet_project!
18
-
19
- limit = options[:limit]
20
- sort = options[:sort]
21
- code = options[:code]
22
- colors = !options[:no_color]
23
-
24
- unless limit || code || sort
25
- return Spoom::Sorbet.srb_tc(capture_err: false).last
26
- end
27
-
28
- output, status = Spoom::Sorbet.srb_tc(capture_err: true)
29
- if status
30
- $stderr.print(output)
31
- return 0
32
- end
33
-
34
- errors = Spoom::Sorbet::Errors::Parser.parse_string(output)
35
- errors_count = errors.size
36
-
37
- errors = sort == "code" ? errors.sort_by { |e| [e.code, e.file, e.line, e.message] } : errors.sort
38
- errors = errors.select { |e| e.code == code } if code
39
- errors = T.must(errors.slice(0, limit)) if limit
40
-
41
- errors.each do |e|
42
- code = colorize_code(e.code, colors)
43
- message = colorize_message(e.message, colors)
44
- $stderr.puts "#{code} - #{e.file}:#{e.line}: #{message}"
45
- end
46
-
47
- if errors_count == errors.size
48
- $stderr.puts "Errors: #{errors_count}"
49
- else
50
- $stderr.puts "Errors: #{errors.size} shown, #{errors_count} total"
51
- end
52
-
53
- 1
54
- end
55
-
56
- desc "metrics", "run srb tc and display metrics"
57
- def metrics
58
- in_sorbet_project!
59
-
60
- metrics = Spoom::Sorbet.srb_metrics(capture_err: false)
61
- if metrics
62
- metrics.show
63
- else
64
- puts "no data"
65
- end
66
- end
67
-
68
- no_commands do
69
- def colorize_code(code, colors = true)
70
- return code.to_s unless colors
71
- code.to_s.light_black
72
- end
73
-
74
- def colorize_message(message, colors = true)
75
- return message unless colors
76
-
77
- cyan = T.let(false, T::Boolean)
78
- word = StringIO.new
79
- message.chars.each do |c|
80
- if c == '`'
81
- cyan = !cyan
82
- next
83
- end
84
- word << (cyan ? c.cyan : c.red)
85
- end
86
- word.string
87
- end
88
- end
89
- end
90
- end
91
- end
92
- end
@@ -1,71 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require "colorize"
5
-
6
- module Spoom
7
- module Cli
8
- class SymbolPrinter
9
- attr_accessor :seen, :no_color
10
-
11
- def self.print_list(list, no_color)
12
- printer = SymbolPrinter.new(2, no_color)
13
- list.each do |item|
14
- printer.print(" * ")
15
- printer.visit(item)
16
- printer.printn
17
- end
18
- end
19
-
20
- def self.print_object(object, no_color)
21
- printer = SymbolPrinter.new(2, no_color)
22
- printer.visit(object)
23
- end
24
-
25
- def initialize(default_indent, no_color = false)
26
- @seen = Set.new
27
- @current_indent = default_indent
28
- @no_color = no_color
29
- String.disable_colorization = no_color
30
- end
31
-
32
- def indent
33
- @current_indent += 2
34
- end
35
-
36
- def dedent
37
- @current_indent -= 2
38
- end
39
-
40
- def print(string)
41
- Kernel.print(string)
42
- end
43
-
44
- def printn
45
- print("\n")
46
- end
47
-
48
- def printt
49
- print(" " * @current_indent)
50
- end
51
-
52
- def visit(object)
53
- if object.is_a?(Array)
54
- object.each { |e| visit(e) }
55
- else
56
- object.accept_printer(self)
57
- end
58
- end
59
- end
60
- end
61
- end
62
-
63
- class String
64
- def to_uri
65
- "file://" + File.join(Spoom::Config::WORKSPACE_PATH, self)
66
- end
67
-
68
- def from_uri
69
- sub("file://#{Spoom::Config::WORKSPACE_PATH}", "")
70
- end
71
- end