steep 0.15.0 → 0.16.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.
@@ -0,0 +1,62 @@
1
+ module Steep
2
+ module Server
3
+ class WorkerProcess
4
+ attr_reader :reader
5
+ attr_reader :writer
6
+ attr_reader :stderr
7
+
8
+ attr_reader :wait_thread
9
+
10
+ def initialize(reader:, writer:, stderr:, wait_thread:)
11
+ @reader = reader
12
+ @writer = writer
13
+ @stderr = stderr
14
+ @wait_thread = wait_thread
15
+ end
16
+
17
+ def self.spawn_worker(type, name:, steepfile:)
18
+ log_level = %w(debug info warn error fatal unknown)[Steep.logger.level]
19
+ command = case type
20
+ when :code
21
+ ["steep", "worker", "--code", "--name=#{name}", "--log-level=#{log_level}", "--steepfile=#{steepfile}"]
22
+ when :signature
23
+ ["steep", "worker", "--signature", "--name=#{name}", "--log-level=#{log_level}", "--steepfile=#{steepfile}"]
24
+ when :interaction
25
+ ["steep", "worker", "--interaction", "--name=#{name}", "--log-level=#{log_level}", "--steepfile=#{steepfile}"]
26
+ else
27
+ raise
28
+ end
29
+
30
+ stdin, stdout, thread = Open3.popen2(*command, pgroup: true)
31
+ stderr = nil
32
+
33
+ writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin)
34
+ reader = LanguageServer::Protocol::Transport::Io::Reader.new(stdout)
35
+
36
+ new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread)
37
+ end
38
+
39
+ def self.spawn_code_workers(steepfile:, count: [Etc.nprocessors-3, 1].max)
40
+ count.times.map do |i|
41
+ spawn_worker(:code, name: "code@#{i}", steepfile: steepfile)
42
+ end
43
+ end
44
+
45
+ def <<(message)
46
+ writer.write(message)
47
+ end
48
+
49
+ def read(&block)
50
+ reader.read(&block)
51
+ end
52
+
53
+ def shutdown
54
+ self << { method: :shutdown, params: nil }
55
+ self << { method: :exit, params: nil }
56
+
57
+ writer.io.close()
58
+ @wait_thread.join()
59
+ end
60
+ end
61
+ end
62
+ end
@@ -51,7 +51,7 @@ module Steep
51
51
  case decl
52
52
  when Declarations::Class
53
53
  rescue_validation_errors do
54
- Steep.logger.info "#{Location.to_string decl.location}:\tValidating class definition `#{name}`..."
54
+ Steep.logger.debug "#{Location.to_string decl.location}:\tValidating class definition `#{name}`..."
55
55
  builder.build_instance(decl.name.absolute!).each_type do |type|
56
56
  env.validate type, namespace: RBS::Namespace.root
57
57
  end
@@ -61,7 +61,7 @@ module Steep
61
61
  end
62
62
  when Declarations::Interface
63
63
  rescue_validation_errors do
64
- Steep.logger.info "#{Location.to_string decl.location}:\tValidating interface `#{name}`..."
64
+ Steep.logger.debug "#{Location.to_string decl.location}:\tValidating interface `#{name}`..."
65
65
  builder.build_interface(decl.name.absolute!, decl).each_type do |type|
66
66
  env.validate type, namespace: RBS::Namespace.root
67
67
  end
@@ -78,7 +78,7 @@ module Steep
78
78
  def validate_const
79
79
  env.each_constant do |name, decl|
80
80
  rescue_validation_errors do
81
- Steep.logger.info "#{Location.to_string decl.location}:\tValidating constant `#{name}`..."
81
+ Steep.logger.debug "#{Location.to_string decl.location}:\tValidating constant `#{name}`..."
82
82
  env.validate(decl.type, namespace: name.namespace)
83
83
  end
84
84
  end
@@ -87,7 +87,7 @@ module Steep
87
87
  def validate_global
88
88
  env.each_global do |name, decl|
89
89
  rescue_validation_errors do
90
- Steep.logger.info "#{Location.to_string decl.location}:\tValidating global `#{name}`..."
90
+ Steep.logger.debug "#{Location.to_string decl.location}:\tValidating global `#{name}`..."
91
91
  env.validate(decl.type, namespace: RBS::Namespace.root)
92
92
  end
93
93
  end
@@ -96,7 +96,7 @@ module Steep
96
96
  def validate_alias
97
97
  env.each_alias do |name, decl|
98
98
  rescue_validation_errors do
99
- Steep.logger.info "#{Location.to_string decl.location}:\tValidating alias `#{name}`..."
99
+ Steep.logger.debug "#{Location.to_string decl.location}:\tValidating alias `#{name}`..."
100
100
  env.validate(decl.type, namespace: name.namespace)
101
101
  end
102
102
  end
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.15.0"
2
+ VERSION = "0.16.0"
3
3
  end
data/lib/steep.rb CHANGED
@@ -10,6 +10,8 @@ require "rainbow"
10
10
  require "listen"
11
11
  require 'pry'
12
12
  require 'language_server-protocol'
13
+ require "etc"
14
+ require "open3"
13
15
 
14
16
  require "rbs"
15
17
 
@@ -70,6 +72,14 @@ require "steep/type_inference/local_variable_type_env"
70
72
  require "steep/type_inference/logic"
71
73
  require "steep/ast/types"
72
74
 
75
+ require "steep/server/utils"
76
+ require "steep/server/base_worker"
77
+ require "steep/server/code_worker"
78
+ require "steep/server/signature_worker"
79
+ require "steep/server/worker_process"
80
+ require "steep/server/interaction_worker"
81
+ require "steep/server/master"
82
+
73
83
  require "steep/project"
74
84
  require "steep/project/file"
75
85
  require "steep/project/options"
@@ -89,6 +99,7 @@ require "steep/drivers/trace_printer"
89
99
  require "steep/drivers/print_project"
90
100
  require "steep/drivers/init"
91
101
  require "steep/drivers/vendor"
102
+ require "steep/drivers/worker"
92
103
 
93
104
  if ENV["NO_COLOR"]
94
105
  Rainbow.enabled = false
data/steep.gemspec CHANGED
@@ -42,5 +42,5 @@ Gem::Specification.new do |spec|
42
42
  spec.add_runtime_dependency "rainbow", ">= 2.2.2", "< 4.0"
43
43
  spec.add_runtime_dependency "listen", "~> 3.1"
44
44
  spec.add_runtime_dependency "pry", "~> 0.12.2"
45
- spec.add_runtime_dependency "language_server-protocol", "~> 3.14.0.1"
45
+ spec.add_runtime_dependency "language_server-protocol", "~> 3.14.0.2"
46
46
  end
@@ -10,51 +10,51 @@ You need to install the dependencies, and build its parser with `bin/setup`.
10
10
 
11
11
  ```
12
12
  $ bin/setup
13
- $ bundle exec exe/ruby-signature
13
+ $ bundle exec exe/rbs
14
14
  ```
15
15
 
16
16
  ## Usage
17
17
 
18
18
  ```
19
- $ ruby-signature list
20
- $ ruby-signature ancestors ::Object
21
- $ ruby-signature methods ::Object
22
- $ ruby-signature method ::Object tap
19
+ $ rbs list
20
+ $ rbs ancestors ::Object
21
+ $ rbs methods ::Object
22
+ $ rbs method ::Object tap
23
23
  ```
24
24
 
25
- ### ruby-signature [--class|--module|interface] list
25
+ ### rbs [--class|--module|interface] list
26
26
 
27
27
  ```
28
- $ ruby-signature list
28
+ $ rbs list
29
29
  ```
30
30
 
31
31
  This command lists all of the classes/modules/interfaces defined in `.rbs` files.
32
32
 
33
- ### ruby-signature ancestors [--singleton|--instance] CLASS
33
+ ### rbs ancestors [--singleton|--instance] CLASS
34
34
 
35
35
  ```
36
- $ ruby-signature ancestors Array # ([].class.ancestors)
37
- $ ruby-signature ancestors --singleton Array # (Array.class.ancestors)
36
+ $ rbs ancestors Array # ([].class.ancestors)
37
+ $ rbs ancestors --singleton Array # (Array.class.ancestors)
38
38
  ```
39
39
 
40
40
  This command prints the _ancestors_ of the class.
41
41
  The name of the command is borrowed from `Class#ancestors`, but the semantics is a bit different.
42
42
  The `ancestors` command is more precise (I believe).
43
43
 
44
- ### ruby-signature methods [--singleton|--instance] CLASS
44
+ ### rbs methods [--singleton|--instance] CLASS
45
45
 
46
46
  ```
47
- $ ruby-signature methods ::Integer # 1.methods
48
- $ ruby-signature methods --singleton ::Object # Object.methods
47
+ $ rbs methods ::Integer # 1.methods
48
+ $ rbs methods --singleton ::Object # Object.methods
49
49
  ```
50
50
 
51
51
  This command prints all methods provided for the class.
52
52
 
53
- ### ruby-signature method [--singleton|--instance] CLASS METHOD
53
+ ### rbs method [--singleton|--instance] CLASS METHOD
54
54
 
55
55
  ```
56
- $ ruby-signature method ::Integer '+' # 1+2
57
- $ ruby-signature method --singleton ::Object tap # Object.tap { ... }
56
+ $ rbs method ::Integer '+' # 1+2
57
+ $ rbs method --singleton ::Object tap # Object.tap { ... }
58
58
  ```
59
59
 
60
60
  This command prints type and properties of the method.
@@ -66,13 +66,13 @@ It accepts two global options, `-r` and `-I`.
66
66
  `-r` is for libraries. You can specify the names of libraries.
67
67
 
68
68
  ```
69
- $ ruby-signature -r set list
69
+ $ rbs -r set list
70
70
  ```
71
71
 
72
72
  `-I` is for application signatures. You can specify the name of directory.
73
73
 
74
74
  ```
75
- $ ruby-signature -I sig list
75
+ $ rbs -I sig list
76
76
  ```
77
77
 
78
78
  ## Guides
@@ -15,7 +15,7 @@ task :validate => :parser do
15
15
  sh "rbs validate"
16
16
  end
17
17
 
18
- FileList["test/stdlib/*_test.rb"].each do |test|
18
+ FileList["test/stdlib/**/*_test.rb"].each do |test|
19
19
  multitask test => :parser do
20
20
  sh "ruby bin/test_runner.rb #{test}"
21
21
  end
@@ -44,21 +44,96 @@ namespace :generate do
44
44
  path = Pathname("test/stdlib/#{klass}_test.rb")
45
45
  raise "#{path} already exists!" if path.exist?
46
46
 
47
- path.write <<~RUBY
48
- require_relative "test_helper"
49
-
50
- class #{klass}Test < StdlibTest
51
- target #{klass}
52
- # library "pathname", "set", "securerandom" # Declare library signatures to load
53
- using hook.refinement
54
-
55
- # def test_method_name
56
- # # Call the method
57
- # method_name(arg)
58
- # method_name(arg, arg2)
59
- # end
47
+ require "erb"
48
+ require "ruby/signature"
49
+
50
+ class TestTemplateBuilder
51
+ attr_reader :klass, :env
52
+
53
+ def initialize(klass)
54
+ @klass = klass
55
+
56
+ @env = Ruby::Signature::Environment.new
57
+ Ruby::Signature::EnvironmentLoader.new.load(env: @env)
58
+ end
59
+
60
+ def call
61
+ ERB.new(<<~ERB, trim_mode: "-").result(binding)
62
+ require_relative "test_helper"
63
+
64
+ class <%= klass %>Test < StdlibTest
65
+ target <%= klass %>
66
+ # library "pathname", "set", "securerandom" # Declare library signatures to load
67
+ using hook.refinement
68
+ <%- class_methods.each do |method_name, definition| %>
69
+ def test_class_method_<%= test_name_for(method_name) %>
70
+ <%- definition.method_types.each do |method_type| -%>
71
+ # <%= method_type %>
72
+ <%= klass %>.<%= method_name %>
73
+ <%- end -%>
74
+ end
75
+ <%- end -%>
76
+ <%- instance_methods.each do |method_name, definition| %>
77
+ def test_<%= test_name_for(method_name) %>
78
+ <%- definition.method_types.each do |method_type| -%>
79
+ # <%= method_type %>
80
+ <%= klass %>.new.<%= method_name %>
81
+ <%- end -%>
82
+ end
83
+ <%- end -%>
84
+ end
85
+ ERB
86
+ end
87
+
88
+ private
89
+
90
+ def test_name_for(method_name)
91
+ {
92
+ :== => 'double_equal',
93
+ :!= => 'not_equal',
94
+ :=== => 'triple_equal',
95
+ :[] => 'square_bracket',
96
+ :[]= => 'square_bracket_assign',
97
+ :> => 'greater_than',
98
+ :< => 'less_than',
99
+ :>= => 'greater_than_equal_to',
100
+ :<= => 'less_than_equal_to',
101
+ :<=> => 'spaceship',
102
+ :+ => 'plus',
103
+ :- => 'minus',
104
+ :* => 'multiply',
105
+ :/ => 'divide',
106
+ :** => 'power',
107
+ :% => 'modulus',
108
+ :& => 'and',
109
+ :| => 'or',
110
+ :^ => 'xor',
111
+ :>> => 'right_shift',
112
+ :<< => 'left_shift',
113
+ :=~ => 'pattern_match',
114
+ :!~ => 'does_not_match',
115
+ :~ => 'tilde'
116
+ }.fetch(method_name, method_name)
60
117
  end
61
- RUBY
118
+
119
+ def type_name
120
+ @type_name ||= Ruby::Signature::TypeName.new(name: klass.to_sym, namespace: Ruby::Signature::Namespace.new(path: [], absolute: true))
121
+ end
122
+
123
+ def class_methods
124
+ @class_methods ||= Ruby::Signature::DefinitionBuilder.new(env: env).build_singleton(type_name).methods.select {|_, definition|
125
+ definition.implemented_in.name.absolute! == type_name
126
+ }
127
+ end
128
+
129
+ def instance_methods
130
+ @instance_methods ||= Ruby::Signature::DefinitionBuilder.new(env: env).build_instance(type_name).methods.select {|_, definition|
131
+ definition.implemented_in.name.absolute! == type_name
132
+ }
133
+ end
134
+ end
135
+
136
+ path.write TestTemplateBuilder.new(klass).call
62
137
 
63
138
  puts "Created: #{path}"
64
139
  end
@@ -42,4 +42,5 @@ Gem::Specification.new do |spec|
42
42
  spec.add_development_dependency "rubocop"
43
43
  spec.add_development_dependency "rubocop-rubycw"
44
44
  spec.add_development_dependency "minitest-reporters", "~> 1.3.6"
45
+ spec.add_development_dependency "json", "~> 2.3.0"
45
46
  end
@@ -42,3 +42,4 @@ type int = Integer | _ToInt
42
42
  type real = Integer | Float | Rational
43
43
 
44
44
  type string = String | _ToStr
45
+ type encoding = Encoding | string
@@ -133,7 +133,7 @@ module Enumerable[unchecked out Elem, out Return]: _Each[Elem, Return]
133
133
 
134
134
  def inject: (untyped init, Symbol method) -> untyped
135
135
  | (Symbol method) -> untyped
136
- | [A] (A initial) { (Elem, A) -> A } -> Elem
136
+ | [A] (A initial) { (A, Elem) -> A } -> A
137
137
  | () { (Elem, Elem) -> Elem } -> Elem
138
138
 
139
139
  # Returns the object in *enum* with the maximum value. The first form
@@ -1034,7 +1034,7 @@ class Module < Object
1034
1034
  # Removes the method identified by *symbol* from the current class. For an
1035
1035
  # example, see Module#undef_method. String arguments are converted to symbols.
1036
1036
  #
1037
- def remove_method: (Symbol | String arg0) -> self
1037
+ def remove_method: (*Symbol | String arg0) -> self
1038
1038
 
1039
1039
  # Returns `true` if *mod* is a singleton class or `false` if it is an ordinary
1040
1040
  # class or module.
@@ -1087,7 +1087,7 @@ class Module < Object
1087
1087
  # In parent
1088
1088
  # prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
1089
1089
  #
1090
- def undef_method: (Symbol | String arg0) -> self
1090
+ def undef_method: (*Symbol | String arg0) -> self
1091
1091
 
1092
1092
  # Import class refinements from *module* into the current class or module
1093
1093
  # definition.