steep 0.29.0 → 0.33.0
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/CHANGELOG.md +25 -0
- data/bin/steep-prof +1 -2
- data/lib/steep.rb +2 -3
- data/lib/steep/ast/types/factory.rb +43 -28
- data/lib/steep/project.rb +25 -0
- data/lib/steep/project/completion_provider.rb +9 -7
- data/lib/steep/project/file_loader.rb +7 -2
- data/lib/steep/project/hover_content.rb +91 -80
- data/lib/steep/project/signature_file.rb +33 -0
- data/lib/steep/project/{file.rb → source_file.rb} +21 -51
- data/lib/steep/project/target.rb +31 -12
- data/lib/steep/server/code_worker.rb +30 -46
- data/lib/steep/server/interaction_worker.rb +42 -38
- data/lib/steep/server/master.rb +13 -30
- data/lib/steep/server/utils.rb +46 -13
- data/lib/steep/server/worker_process.rb +4 -2
- data/lib/steep/source.rb +60 -3
- data/lib/steep/type_inference/context_array.rb +1 -1
- data/lib/steep/type_inference/logic_type_interpreter.rb +6 -0
- data/lib/steep/version.rb +1 -1
- data/smoke/regression/fun.rb +8 -0
- data/smoke/regression/fun.rbs +4 -0
- data/smoke/toplevel/Steepfile +5 -0
- data/smoke/toplevel/a.rb +4 -0
- data/smoke/toplevel/a.rbs +3 -0
- data/steep.gemspec +1 -1
- metadata +11 -7
- data/lib/steep/ast/buffer.rb +0 -51
- data/lib/steep/ast/location.rb +0 -86
data/lib/steep/server/master.rb
CHANGED
@@ -14,6 +14,8 @@ module Steep
|
|
14
14
|
attr_reader :signature_worker
|
15
15
|
attr_reader :code_workers
|
16
16
|
|
17
|
+
include Utils
|
18
|
+
|
17
19
|
def initialize(project:, reader:, writer:, interaction_worker:, signature_worker:, code_workers:, queue: Queue.new)
|
18
20
|
@project = project
|
19
21
|
@reader = reader
|
@@ -27,19 +29,24 @@ module Steep
|
|
27
29
|
end
|
28
30
|
|
29
31
|
def start
|
30
|
-
source_paths = project.
|
32
|
+
source_paths = project.all_source_files
|
31
33
|
bin_size = (source_paths.size / code_workers.size) + 1
|
32
34
|
source_paths.each_slice(bin_size).with_index do |paths, index|
|
33
35
|
register_code_to_worker(paths, worker: code_workers[index])
|
34
36
|
end
|
35
37
|
|
38
|
+
tags = Steep.logger.formatter.current_tags.dup
|
39
|
+
tags << "master"
|
40
|
+
|
36
41
|
Thread.new do
|
42
|
+
Steep.logger.formatter.push_tags(*tags, "from-worker@interaction")
|
37
43
|
interaction_worker.reader.read do |message|
|
38
44
|
process_message_from_worker(message)
|
39
45
|
end
|
40
46
|
end
|
41
47
|
|
42
48
|
Thread.new do
|
49
|
+
Steep.logger.formatter.push_tags(*tags, "from-worker@signature")
|
43
50
|
signature_worker.reader.read do |message|
|
44
51
|
process_message_from_worker(message)
|
45
52
|
end
|
@@ -47,6 +54,7 @@ module Steep
|
|
47
54
|
|
48
55
|
code_workers.each do |worker|
|
49
56
|
Thread.new do
|
57
|
+
Steep.logger.formatter.push_tags(*tags, "from-worker@#{worker.name}")
|
50
58
|
worker.reader.read do |message|
|
51
59
|
process_message_from_worker(message)
|
52
60
|
end
|
@@ -54,6 +62,7 @@ module Steep
|
|
54
62
|
end
|
55
63
|
|
56
64
|
Thread.new do
|
65
|
+
Steep.logger.formatter.push_tags(*tags, "from-client")
|
57
66
|
reader.read do |request|
|
58
67
|
process_message_from_client(request)
|
59
68
|
end
|
@@ -97,7 +106,7 @@ module Steep
|
|
97
106
|
result: LSP::Interface::InitializeResult.new(
|
98
107
|
capabilities: LSP::Interface::ServerCapabilities.new(
|
99
108
|
text_document_sync: LSP::Interface::TextDocumentSyncOptions.new(
|
100
|
-
change: LSP::Constant::TextDocumentSyncKind::
|
109
|
+
change: LSP::Constant::TextDocumentSyncKind::INCREMENTAL
|
101
110
|
),
|
102
111
|
hover_provider: true,
|
103
112
|
completion_provider: LSP::Interface::CompletionOptions.new(
|
@@ -112,36 +121,10 @@ module Steep
|
|
112
121
|
end
|
113
122
|
|
114
123
|
when "textDocument/didChange"
|
124
|
+
update_source(message)
|
125
|
+
|
115
126
|
uri = URI.parse(message[:params][:textDocument][:uri])
|
116
127
|
path = project.relative_path(Pathname(uri.path))
|
117
|
-
text = message[:params][:contentChanges][0][:text]
|
118
|
-
|
119
|
-
project.targets.each do |target|
|
120
|
-
case
|
121
|
-
when target.source_file?(path)
|
122
|
-
if text.empty? && !path.file?
|
123
|
-
Steep.logger.info { "Deleting source file: #{path}..." }
|
124
|
-
target.remove_source(path)
|
125
|
-
else
|
126
|
-
Steep.logger.info { "Updating source file: #{path}..." }
|
127
|
-
target.update_source(path, text)
|
128
|
-
end
|
129
|
-
when target.possible_source_file?(path)
|
130
|
-
Steep.logger.info { "Adding source file: #{path}..." }
|
131
|
-
target.add_source(path, text)
|
132
|
-
when target.signature_file?(path)
|
133
|
-
if text.empty? && !path.file?
|
134
|
-
Steep.logger.info { "Deleting signature file: #{path}..." }
|
135
|
-
target.remove_signature(path)
|
136
|
-
else
|
137
|
-
Steep.logger.info { "Updating signature file: #{path}..." }
|
138
|
-
target.update_signature(path, text)
|
139
|
-
end
|
140
|
-
when target.possible_signature_file?(path)
|
141
|
-
Steep.logger.info { "Adding signature file: #{path}..." }
|
142
|
-
target.add_signature(path, text)
|
143
|
-
end
|
144
|
-
end
|
145
128
|
|
146
129
|
unless registered_path?(path)
|
147
130
|
register_code_to_worker [path], worker: least_busy_worker()
|
data/lib/steep/server/utils.rb
CHANGED
@@ -7,23 +7,56 @@ module Steep
|
|
7
7
|
project.relative_path(Pathname(uri.path))
|
8
8
|
end
|
9
9
|
|
10
|
+
def apply_change(change, text)
|
11
|
+
range = change[:range]
|
12
|
+
|
13
|
+
if range
|
14
|
+
text = text.dup
|
15
|
+
|
16
|
+
buf = RBS::Buffer.new(name: :_, content: text)
|
17
|
+
|
18
|
+
start_pos = buf.loc_to_pos(range[:start].yield_self {|pos| [pos[:line]+1, pos[:character]] })
|
19
|
+
end_pos = buf.loc_to_pos(range[:end].yield_self {|pos| [pos[:line]+1, pos[:character]] })
|
20
|
+
|
21
|
+
text[start_pos...end_pos] = change[:text]
|
22
|
+
text
|
23
|
+
else
|
24
|
+
change[:text]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
10
28
|
def update_source(request)
|
11
29
|
path = source_path(URI.parse(request[:params][:textDocument][:uri]))
|
12
|
-
text = request[:params][:contentChanges][0][:text]
|
13
30
|
version = request[:params][:textDocument][:version]
|
31
|
+
Steep.logger.info { "Updating source: path=#{path}, version=#{version}..." }
|
32
|
+
|
33
|
+
changes = request[:params][:contentChanges]
|
34
|
+
|
35
|
+
source_target, signature_targets = project.targets_for_path(path)
|
36
|
+
|
37
|
+
if source_target
|
38
|
+
changes.each do |change|
|
39
|
+
case
|
40
|
+
when source_target.source_file?(path)
|
41
|
+
Steep.logger.debug { "Updating source in #{source_target.name}: path=#{path}" }
|
42
|
+
source_target.update_source(path) {|text| apply_change(change, text) }
|
43
|
+
when source_target.possible_source_file?(path)
|
44
|
+
Steep.logger.debug { "Adding source to #{source_target.name}: path=#{path}" }
|
45
|
+
source_target.add_source(path, change[:text])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
14
49
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
when target.possible_signature_file?(path)
|
26
|
-
target.add_signature path, text
|
50
|
+
signature_targets.each do |target|
|
51
|
+
changes.each do |change|
|
52
|
+
case
|
53
|
+
when target.signature_file?(path)
|
54
|
+
Steep.logger.debug { "Updating signature in #{target.name}: path=#{path}" }
|
55
|
+
target.update_signature(path) {|text| apply_change(change, text) }
|
56
|
+
when target.possible_signature_file?(path)
|
57
|
+
Steep.logger.debug { "Adding signature to #{target.name}: path=#{path}" }
|
58
|
+
target.add_signature(path, change[:text])
|
59
|
+
end
|
27
60
|
end
|
28
61
|
end
|
29
62
|
|
@@ -5,13 +5,15 @@ module Steep
|
|
5
5
|
attr_reader :writer
|
6
6
|
attr_reader :stderr
|
7
7
|
|
8
|
+
attr_reader :name
|
8
9
|
attr_reader :wait_thread
|
9
10
|
|
10
|
-
def initialize(reader:, writer:, stderr:, wait_thread:)
|
11
|
+
def initialize(reader:, writer:, stderr:, wait_thread:, name:)
|
11
12
|
@reader = reader
|
12
13
|
@writer = writer
|
13
14
|
@stderr = stderr
|
14
15
|
@wait_thread = wait_thread
|
16
|
+
@name = name
|
15
17
|
end
|
16
18
|
|
17
19
|
def self.spawn_worker(type, name:, steepfile:)
|
@@ -33,7 +35,7 @@ module Steep
|
|
33
35
|
writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin)
|
34
36
|
reader = LanguageServer::Protocol::Transport::Io::Reader.new(stdout)
|
35
37
|
|
36
|
-
new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread)
|
38
|
+
new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name)
|
37
39
|
end
|
38
40
|
|
39
41
|
def self.spawn_code_workers(steepfile:, count: [Etc.nprocessors-3, 1].max)
|
data/lib/steep/source.rb
CHANGED
@@ -65,11 +65,11 @@ module Steep
|
|
65
65
|
parser.tokenize(buffer)
|
66
66
|
end
|
67
67
|
|
68
|
-
buffer =
|
68
|
+
buffer = RBS::Buffer.new(name: path, content: source_code)
|
69
69
|
|
70
70
|
comments.each do |comment|
|
71
71
|
src = comment.text.gsub(/\A#\s*/, '')
|
72
|
-
location =
|
72
|
+
location = RBS::Location.new(buffer: buffer,
|
73
73
|
start_pos: comment.location.expression.begin_pos + 1,
|
74
74
|
end_pos: comment.location.expression.end_pos)
|
75
75
|
annotation = AnnotationParser.new(factory: factory).parse(src, location: location)
|
@@ -107,7 +107,7 @@ module Steep
|
|
107
107
|
|
108
108
|
if node.children[1]
|
109
109
|
if node.loc.keyword.source == "if" || node.loc.keyword.source == "elsif"
|
110
|
-
then_start = node.loc.begin&.
|
110
|
+
then_start = node.loc.begin&.last_line || node.children[0].loc.last_line
|
111
111
|
then_end = node.children[2] ? node.loc.else.line : node.loc.last_line
|
112
112
|
else
|
113
113
|
then_start = node.loc.else.last_line
|
@@ -276,6 +276,18 @@ module Steep
|
|
276
276
|
end
|
277
277
|
end
|
278
278
|
|
279
|
+
def self.map_child_nodes(node)
|
280
|
+
children = node.children.map do |child|
|
281
|
+
if child.is_a?(::AST::Node)
|
282
|
+
yield child
|
283
|
+
else
|
284
|
+
child
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
node.updated(nil, children)
|
289
|
+
end
|
290
|
+
|
279
291
|
def annotations(block:, factory:, current_module:)
|
280
292
|
AST::Annotation::Collection.new(
|
281
293
|
annotations: mapping[block.__id__] || [],
|
@@ -316,5 +328,50 @@ module Steep
|
|
316
328
|
end
|
317
329
|
end
|
318
330
|
end
|
331
|
+
|
332
|
+
def self.delete_defs(node, allow_list)
|
333
|
+
case node.type
|
334
|
+
when :def
|
335
|
+
if allow_list.include?(node)
|
336
|
+
node
|
337
|
+
else
|
338
|
+
node.updated(:nil, [])
|
339
|
+
end
|
340
|
+
when :defs
|
341
|
+
if allow_list.include?(node)
|
342
|
+
node
|
343
|
+
else
|
344
|
+
delete_defs(node.children[0], allow_list)
|
345
|
+
end
|
346
|
+
else
|
347
|
+
map_child_nodes(node) do |child|
|
348
|
+
delete_defs(child, allow_list)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def without_unrelated_defs(line:, column:)
|
354
|
+
nodes = find_nodes(line: line, column: column) || []
|
355
|
+
defs = Set[].compare_by_identity.merge(nodes.select {|node| node.type == :def || node.type == :defs })
|
356
|
+
|
357
|
+
node_ = Source.delete_defs(node, defs)
|
358
|
+
|
359
|
+
Source.new(path: path, node: node_, mapping: mapping)
|
360
|
+
end
|
361
|
+
|
362
|
+
def compact_siblings(node)
|
363
|
+
case node
|
364
|
+
when :def
|
365
|
+
node.updated(:nil, [])
|
366
|
+
when :defs
|
367
|
+
node.children[0]
|
368
|
+
when :class
|
369
|
+
node.updated(:class, [node.children[0], node.children[1], nil])
|
370
|
+
when :module
|
371
|
+
node.updated(:module, [node.children[0], nil])
|
372
|
+
else
|
373
|
+
node
|
374
|
+
end
|
375
|
+
end
|
319
376
|
end
|
320
377
|
end
|
data/lib/steep/version.rb
CHANGED
data/smoke/toplevel/a.rb
ADDED
data/steep.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_runtime_dependency "ast_utils", "~> 0.3.0"
|
33
33
|
spec.add_runtime_dependency "activesupport", ">= 5.1"
|
34
34
|
spec.add_runtime_dependency "rainbow", ">= 2.2.2", "< 4.0"
|
35
|
-
spec.add_runtime_dependency "listen", "~> 3.
|
35
|
+
spec.add_runtime_dependency "listen", "~> 3.0"
|
36
36
|
spec.add_runtime_dependency "language_server-protocol", "~> 3.15.0.1"
|
37
37
|
spec.add_runtime_dependency "rbs", "~> 0.12.0"
|
38
38
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.33.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soutaro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -78,14 +78,14 @@ dependencies:
|
|
78
78
|
requirements:
|
79
79
|
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version: '3.
|
81
|
+
version: '3.0'
|
82
82
|
type: :runtime
|
83
83
|
prerelease: false
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
86
|
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version: '3.
|
88
|
+
version: '3.0'
|
89
89
|
- !ruby/object:Gem::Dependency
|
90
90
|
name: language_server-protocol
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -140,9 +140,7 @@ files:
|
|
140
140
|
- lib/steep/annotation_parser.rb
|
141
141
|
- lib/steep/ast/annotation.rb
|
142
142
|
- lib/steep/ast/annotation/collection.rb
|
143
|
-
- lib/steep/ast/buffer.rb
|
144
143
|
- lib/steep/ast/builtin.rb
|
145
|
-
- lib/steep/ast/location.rb
|
146
144
|
- lib/steep/ast/type_params.rb
|
147
145
|
- lib/steep/ast/types.rb
|
148
146
|
- lib/steep/ast/types/any.rb
|
@@ -187,10 +185,11 @@ files:
|
|
187
185
|
- lib/steep/project.rb
|
188
186
|
- lib/steep/project/completion_provider.rb
|
189
187
|
- lib/steep/project/dsl.rb
|
190
|
-
- lib/steep/project/file.rb
|
191
188
|
- lib/steep/project/file_loader.rb
|
192
189
|
- lib/steep/project/hover_content.rb
|
193
190
|
- lib/steep/project/options.rb
|
191
|
+
- lib/steep/project/signature_file.rb
|
192
|
+
- lib/steep/project/source_file.rb
|
194
193
|
- lib/steep/project/target.rb
|
195
194
|
- lib/steep/server/base_worker.rb
|
196
195
|
- lib/steep/server/code_worker.rb
|
@@ -330,6 +329,8 @@ files:
|
|
330
329
|
- smoke/regexp/b.rb
|
331
330
|
- smoke/regression/Steepfile
|
332
331
|
- smoke/regression/array.rb
|
332
|
+
- smoke/regression/fun.rb
|
333
|
+
- smoke/regression/fun.rbs
|
333
334
|
- smoke/regression/hash.rb
|
334
335
|
- smoke/regression/poly_new.rb
|
335
336
|
- smoke/regression/poly_new.rbs
|
@@ -347,6 +348,9 @@ files:
|
|
347
348
|
- smoke/super/Steepfile
|
348
349
|
- smoke/super/a.rb
|
349
350
|
- smoke/super/a.rbs
|
351
|
+
- smoke/toplevel/Steepfile
|
352
|
+
- smoke/toplevel/a.rb
|
353
|
+
- smoke/toplevel/a.rbs
|
350
354
|
- smoke/type_case/Steepfile
|
351
355
|
- smoke/type_case/a.rb
|
352
356
|
- smoke/yield/Steepfile
|
data/lib/steep/ast/buffer.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
module Steep
|
2
|
-
module AST
|
3
|
-
class Buffer
|
4
|
-
attr_reader :name
|
5
|
-
attr_reader :content
|
6
|
-
attr_reader :lines
|
7
|
-
attr_reader :ranges
|
8
|
-
|
9
|
-
def initialize(name:, content:)
|
10
|
-
@name = name
|
11
|
-
@content = content
|
12
|
-
|
13
|
-
@lines = content.split(/\n/, -1)
|
14
|
-
|
15
|
-
@ranges = []
|
16
|
-
offset = 0
|
17
|
-
lines.each.with_index do |line, index|
|
18
|
-
if index == lines.size - 1
|
19
|
-
ranges << (offset..offset)
|
20
|
-
else
|
21
|
-
size = line.size
|
22
|
-
range = offset..(offset+size)
|
23
|
-
ranges << range
|
24
|
-
offset += size+1
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def pos_to_loc(pos)
|
30
|
-
index = ranges.bsearch_index do |range|
|
31
|
-
pos <= range.end
|
32
|
-
end
|
33
|
-
|
34
|
-
if index
|
35
|
-
[index + 1, pos - ranges[index].begin]
|
36
|
-
else
|
37
|
-
[1, pos]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def loc_to_pos(loc)
|
42
|
-
line, column = loc
|
43
|
-
ranges[line - 1].begin + column
|
44
|
-
end
|
45
|
-
|
46
|
-
def source(range)
|
47
|
-
content[range]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|