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.
@@ -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.targets.flat_map {|target| target.source_files.keys }
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::FULL
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()
@@ -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
- Steep.logger.debug "Updateing source: path=#{path}, version=#{version}, size=#{text.bytesize}"
16
-
17
- project.targets.each do |target|
18
- case
19
- when target.source_file?(path)
20
- target.update_source path, text
21
- when target.possible_source_file?(path)
22
- target.add_source path, text
23
- when target.signature_file?(path)
24
- target.update_signature path, text
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)
@@ -65,11 +65,11 @@ module Steep
65
65
  parser.tokenize(buffer)
66
66
  end
67
67
 
68
- buffer = AST::Buffer.new(name: path, content: source_code)
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 = AST::Location.new(buffer: buffer,
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&.loc&.last_line || node.children[0].loc.last_line
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
@@ -29,7 +29,7 @@ module Steep
29
29
  else
30
30
  ""
31
31
  end
32
- buffer = AST::Buffer.new(name: source.path, content: content)
32
+ buffer = RBS::Buffer.new(name: source.path, content: content)
33
33
  new(buffer: buffer, context: context, range: range || 0..buffer.content.size)
34
34
  end
35
35
 
@@ -207,6 +207,12 @@ module Steep
207
207
  [type]
208
208
  ]
209
209
 
210
+ when AST::Types::Name::Interface
211
+ [
212
+ [instance_type],
213
+ [type]
214
+ ]
215
+
210
216
  else
211
217
  [
212
218
  [],
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.29.0"
2
+ VERSION = "0.33.0"
3
3
  end
@@ -0,0 +1,8 @@
1
+ class Fun
2
+ def foo(v)
3
+ !v.nil? && foo2(v)
4
+ end
5
+
6
+ def foo2(_)
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ class Fun
2
+ def foo: (Integer?) -> void
3
+ def foo2: (Integer) -> void
4
+ end
@@ -0,0 +1,5 @@
1
+ target :test do
2
+ typing_options :strict
3
+ check "*.rb"
4
+ signature "*.rbs"
5
+ end
@@ -0,0 +1,4 @@
1
+ # !expects MethodBodyTypeMismatch: method=fizz_buzz, expected=::String, actual=nil
2
+ def fizz_buzz(n)
3
+ nil
4
+ end
@@ -0,0 +1,3 @@
1
+ class Object
2
+ def fizz_buzz: (Integer) -> String
3
+ end
@@ -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.1"
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.29.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-09-28 00:00:00.000000000 Z
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.1'
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.1'
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
@@ -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