steep 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.