steep 0.13.0 → 0.16.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +0 -3
  3. data/CHANGELOG.md +28 -0
  4. data/Rakefile +0 -13
  5. data/bin/setup +0 -2
  6. data/bin/smoke_runner.rb +0 -1
  7. data/exe/steep +0 -1
  8. data/lib/steep.rb +33 -1
  9. data/lib/steep/annotation_parser.rb +4 -4
  10. data/lib/steep/ast/buffer.rb +11 -7
  11. data/lib/steep/ast/builtin.rb +8 -0
  12. data/lib/steep/ast/types/factory.rb +124 -89
  13. data/lib/steep/cli.rb +16 -1
  14. data/lib/steep/drivers/annotations.rb +1 -1
  15. data/lib/steep/drivers/check.rb +20 -4
  16. data/lib/steep/drivers/init.rb +5 -5
  17. data/lib/steep/drivers/langserver.rb +13 -287
  18. data/lib/steep/drivers/utils/driver_helper.rb +1 -1
  19. data/lib/steep/drivers/vendor.rb +2 -2
  20. data/lib/steep/drivers/watch.rb +97 -85
  21. data/lib/steep/drivers/worker.rb +51 -0
  22. data/lib/steep/project.rb +9 -5
  23. data/lib/steep/project/completion_provider.rb +298 -0
  24. data/lib/steep/project/dsl.rb +14 -0
  25. data/lib/steep/project/file.rb +54 -47
  26. data/lib/steep/project/hover_content.rb +17 -8
  27. data/lib/steep/project/options.rb +25 -3
  28. data/lib/steep/project/target.rb +40 -24
  29. data/lib/steep/server/base_worker.rb +56 -0
  30. data/lib/steep/server/code_worker.rb +151 -0
  31. data/lib/steep/server/interaction_worker.rb +281 -0
  32. data/lib/steep/server/master.rb +196 -0
  33. data/lib/steep/server/signature_worker.rb +148 -0
  34. data/lib/steep/server/utils.rb +36 -0
  35. data/lib/steep/server/worker_process.rb +62 -0
  36. data/lib/steep/signature/errors.rb +1 -1
  37. data/lib/steep/signature/validator.rb +13 -13
  38. data/lib/steep/source.rb +1 -1
  39. data/lib/steep/type_construction.rb +1004 -727
  40. data/lib/steep/type_inference/constant_env.rb +3 -11
  41. data/lib/steep/type_inference/context.rb +8 -3
  42. data/lib/steep/type_inference/context_array.rb +111 -0
  43. data/lib/steep/type_inference/local_variable_type_env.rb +226 -0
  44. data/lib/steep/type_inference/logic.rb +130 -0
  45. data/lib/steep/type_inference/type_env.rb +5 -69
  46. data/lib/steep/typing.rb +91 -23
  47. data/lib/steep/version.rb +1 -1
  48. data/smoke/alias/Steepfile +1 -0
  49. data/smoke/alias/a.rb +1 -1
  50. data/smoke/and/Steepfile +1 -0
  51. data/smoke/array/Steepfile +1 -0
  52. data/smoke/array/b.rb +0 -2
  53. data/smoke/block/Steepfile +1 -0
  54. data/smoke/case/Steepfile +1 -0
  55. data/smoke/class/Steepfile +1 -0
  56. data/smoke/const/Steepfile +1 -0
  57. data/smoke/dstr/Steepfile +1 -0
  58. data/smoke/ensure/Steepfile +1 -0
  59. data/smoke/enumerator/Steepfile +1 -0
  60. data/smoke/extension/Steepfile +1 -0
  61. data/smoke/extension/c.rb +1 -0
  62. data/smoke/hash/Steepfile +1 -0
  63. data/smoke/hello/Steepfile +1 -0
  64. data/smoke/if/Steepfile +1 -0
  65. data/smoke/if/a.rb +1 -1
  66. data/smoke/implements/Steepfile +1 -0
  67. data/smoke/initialize/Steepfile +1 -0
  68. data/smoke/integer/Steepfile +1 -0
  69. data/smoke/interface/Steepfile +1 -0
  70. data/smoke/kwbegin/Steepfile +1 -0
  71. data/smoke/lambda/Steepfile +1 -0
  72. data/smoke/literal/Steepfile +1 -0
  73. data/smoke/map/Steepfile +1 -0
  74. data/smoke/method/Steepfile +1 -0
  75. data/smoke/module/Steepfile +1 -0
  76. data/smoke/regexp/Steepfile +1 -0
  77. data/smoke/regexp/b.rb +4 -4
  78. data/smoke/regression/Steepfile +1 -0
  79. data/smoke/rescue/Steepfile +1 -0
  80. data/smoke/rescue/a.rb +1 -1
  81. data/smoke/self/Steepfile +1 -0
  82. data/smoke/skip/Steepfile +1 -0
  83. data/smoke/stdout/Steepfile +1 -0
  84. data/smoke/super/Steepfile +1 -0
  85. data/smoke/type_case/Steepfile +1 -0
  86. data/smoke/yield/Steepfile +1 -0
  87. data/steep.gemspec +8 -8
  88. metadata +38 -138
  89. data/exe/rbs +0 -3
  90. data/exe/ruby-signature +0 -3
  91. data/vendor/ruby-signature/.github/workflows/ruby.yml +0 -27
  92. data/vendor/ruby-signature/.gitignore +0 -12
  93. data/vendor/ruby-signature/.rubocop.yml +0 -15
  94. data/vendor/ruby-signature/BSDL +0 -22
  95. data/vendor/ruby-signature/COPYING +0 -56
  96. data/vendor/ruby-signature/Gemfile +0 -6
  97. data/vendor/ruby-signature/README.md +0 -93
  98. data/vendor/ruby-signature/Rakefile +0 -66
  99. data/vendor/ruby-signature/bin/annotate-with-rdoc +0 -156
  100. data/vendor/ruby-signature/bin/console +0 -14
  101. data/vendor/ruby-signature/bin/query-rdoc +0 -103
  102. data/vendor/ruby-signature/bin/setup +0 -10
  103. data/vendor/ruby-signature/bin/sort +0 -88
  104. data/vendor/ruby-signature/bin/test_runner.rb +0 -17
  105. data/vendor/ruby-signature/docs/CONTRIBUTING.md +0 -97
  106. data/vendor/ruby-signature/docs/sigs.md +0 -148
  107. data/vendor/ruby-signature/docs/stdlib.md +0 -152
  108. data/vendor/ruby-signature/docs/syntax.md +0 -528
  109. data/vendor/ruby-signature/exe/rbs +0 -3
  110. data/vendor/ruby-signature/exe/ruby-signature +0 -7
  111. data/vendor/ruby-signature/lib/ruby/signature.rb +0 -64
  112. data/vendor/ruby-signature/lib/ruby/signature/ast/annotation.rb +0 -29
  113. data/vendor/ruby-signature/lib/ruby/signature/ast/comment.rb +0 -29
  114. data/vendor/ruby-signature/lib/ruby/signature/ast/declarations.rb +0 -391
  115. data/vendor/ruby-signature/lib/ruby/signature/ast/members.rb +0 -364
  116. data/vendor/ruby-signature/lib/ruby/signature/buffer.rb +0 -52
  117. data/vendor/ruby-signature/lib/ruby/signature/builtin_names.rb +0 -54
  118. data/vendor/ruby-signature/lib/ruby/signature/cli.rb +0 -534
  119. data/vendor/ruby-signature/lib/ruby/signature/constant.rb +0 -28
  120. data/vendor/ruby-signature/lib/ruby/signature/constant_table.rb +0 -152
  121. data/vendor/ruby-signature/lib/ruby/signature/definition.rb +0 -172
  122. data/vendor/ruby-signature/lib/ruby/signature/definition_builder.rb +0 -921
  123. data/vendor/ruby-signature/lib/ruby/signature/environment.rb +0 -283
  124. data/vendor/ruby-signature/lib/ruby/signature/environment_loader.rb +0 -138
  125. data/vendor/ruby-signature/lib/ruby/signature/environment_walker.rb +0 -126
  126. data/vendor/ruby-signature/lib/ruby/signature/errors.rb +0 -189
  127. data/vendor/ruby-signature/lib/ruby/signature/location.rb +0 -104
  128. data/vendor/ruby-signature/lib/ruby/signature/method_type.rb +0 -125
  129. data/vendor/ruby-signature/lib/ruby/signature/namespace.rb +0 -93
  130. data/vendor/ruby-signature/lib/ruby/signature/parser.y +0 -1343
  131. data/vendor/ruby-signature/lib/ruby/signature/prototype/rb.rb +0 -441
  132. data/vendor/ruby-signature/lib/ruby/signature/prototype/rbi.rb +0 -579
  133. data/vendor/ruby-signature/lib/ruby/signature/prototype/runtime.rb +0 -383
  134. data/vendor/ruby-signature/lib/ruby/signature/substitution.rb +0 -48
  135. data/vendor/ruby-signature/lib/ruby/signature/test.rb +0 -28
  136. data/vendor/ruby-signature/lib/ruby/signature/test/errors.rb +0 -63
  137. data/vendor/ruby-signature/lib/ruby/signature/test/hook.rb +0 -290
  138. data/vendor/ruby-signature/lib/ruby/signature/test/setup.rb +0 -58
  139. data/vendor/ruby-signature/lib/ruby/signature/test/spy.rb +0 -324
  140. data/vendor/ruby-signature/lib/ruby/signature/test/test_helper.rb +0 -185
  141. data/vendor/ruby-signature/lib/ruby/signature/test/type_check.rb +0 -256
  142. data/vendor/ruby-signature/lib/ruby/signature/type_name.rb +0 -72
  143. data/vendor/ruby-signature/lib/ruby/signature/types.rb +0 -932
  144. data/vendor/ruby-signature/lib/ruby/signature/variance_calculator.rb +0 -140
  145. data/vendor/ruby-signature/lib/ruby/signature/vendorer.rb +0 -49
  146. data/vendor/ruby-signature/lib/ruby/signature/version.rb +0 -5
  147. data/vendor/ruby-signature/lib/ruby/signature/writer.rb +0 -271
  148. data/vendor/ruby-signature/ruby-signature.gemspec +0 -45
  149. data/vendor/ruby-signature/stdlib/abbrev/abbrev.rbs +0 -3
  150. data/vendor/ruby-signature/stdlib/base64/base64.rbs +0 -15
  151. data/vendor/ruby-signature/stdlib/builtin/array.rbs +0 -1997
  152. data/vendor/ruby-signature/stdlib/builtin/basic_object.rbs +0 -280
  153. data/vendor/ruby-signature/stdlib/builtin/binding.rbs +0 -177
  154. data/vendor/ruby-signature/stdlib/builtin/builtin.rbs +0 -35
  155. data/vendor/ruby-signature/stdlib/builtin/class.rbs +0 -145
  156. data/vendor/ruby-signature/stdlib/builtin/comparable.rbs +0 -116
  157. data/vendor/ruby-signature/stdlib/builtin/complex.rbs +0 -400
  158. data/vendor/ruby-signature/stdlib/builtin/constants.rbs +0 -37
  159. data/vendor/ruby-signature/stdlib/builtin/data.rbs +0 -5
  160. data/vendor/ruby-signature/stdlib/builtin/deprecated.rbs +0 -2
  161. data/vendor/ruby-signature/stdlib/builtin/dir.rbs +0 -419
  162. data/vendor/ruby-signature/stdlib/builtin/encoding.rbs +0 -606
  163. data/vendor/ruby-signature/stdlib/builtin/enumerable.rbs +0 -404
  164. data/vendor/ruby-signature/stdlib/builtin/enumerator.rbs +0 -260
  165. data/vendor/ruby-signature/stdlib/builtin/errno.rbs +0 -781
  166. data/vendor/ruby-signature/stdlib/builtin/errors.rbs +0 -582
  167. data/vendor/ruby-signature/stdlib/builtin/exception.rbs +0 -193
  168. data/vendor/ruby-signature/stdlib/builtin/false_class.rbs +0 -40
  169. data/vendor/ruby-signature/stdlib/builtin/fiber.rbs +0 -68
  170. data/vendor/ruby-signature/stdlib/builtin/fiber_error.rbs +0 -12
  171. data/vendor/ruby-signature/stdlib/builtin/file.rbs +0 -476
  172. data/vendor/ruby-signature/stdlib/builtin/file_test.rbs +0 -59
  173. data/vendor/ruby-signature/stdlib/builtin/float.rbs +0 -696
  174. data/vendor/ruby-signature/stdlib/builtin/gc.rbs +0 -121
  175. data/vendor/ruby-signature/stdlib/builtin/hash.rbs +0 -1029
  176. data/vendor/ruby-signature/stdlib/builtin/integer.rbs +0 -710
  177. data/vendor/ruby-signature/stdlib/builtin/io.rbs +0 -683
  178. data/vendor/ruby-signature/stdlib/builtin/kernel.rbs +0 -574
  179. data/vendor/ruby-signature/stdlib/builtin/marshal.rbs +0 -135
  180. data/vendor/ruby-signature/stdlib/builtin/match_data.rbs +0 -141
  181. data/vendor/ruby-signature/stdlib/builtin/math.rbs +0 -66
  182. data/vendor/ruby-signature/stdlib/builtin/method.rbs +0 -182
  183. data/vendor/ruby-signature/stdlib/builtin/module.rbs +0 -248
  184. data/vendor/ruby-signature/stdlib/builtin/nil_class.rbs +0 -82
  185. data/vendor/ruby-signature/stdlib/builtin/numeric.rbs +0 -409
  186. data/vendor/ruby-signature/stdlib/builtin/object.rbs +0 -824
  187. data/vendor/ruby-signature/stdlib/builtin/proc.rbs +0 -426
  188. data/vendor/ruby-signature/stdlib/builtin/process.rbs +0 -354
  189. data/vendor/ruby-signature/stdlib/builtin/random.rbs +0 -93
  190. data/vendor/ruby-signature/stdlib/builtin/range.rbs +0 -226
  191. data/vendor/ruby-signature/stdlib/builtin/rational.rbs +0 -424
  192. data/vendor/ruby-signature/stdlib/builtin/rb_config.rbs +0 -10
  193. data/vendor/ruby-signature/stdlib/builtin/regexp.rbs +0 -131
  194. data/vendor/ruby-signature/stdlib/builtin/ruby_vm.rbs +0 -14
  195. data/vendor/ruby-signature/stdlib/builtin/signal.rbs +0 -55
  196. data/vendor/ruby-signature/stdlib/builtin/string.rbs +0 -770
  197. data/vendor/ruby-signature/stdlib/builtin/string_io.rbs +0 -13
  198. data/vendor/ruby-signature/stdlib/builtin/struct.rbs +0 -40
  199. data/vendor/ruby-signature/stdlib/builtin/symbol.rbs +0 -230
  200. data/vendor/ruby-signature/stdlib/builtin/thread.rbs +0 -1112
  201. data/vendor/ruby-signature/stdlib/builtin/thread_group.rbs +0 -23
  202. data/vendor/ruby-signature/stdlib/builtin/time.rbs +0 -739
  203. data/vendor/ruby-signature/stdlib/builtin/trace_point.rbs +0 -91
  204. data/vendor/ruby-signature/stdlib/builtin/true_class.rbs +0 -46
  205. data/vendor/ruby-signature/stdlib/builtin/unbound_method.rbs +0 -159
  206. data/vendor/ruby-signature/stdlib/builtin/warning.rbs +0 -17
  207. data/vendor/ruby-signature/stdlib/erb/erb.rbs +0 -18
  208. data/vendor/ruby-signature/stdlib/find/find.rbs +0 -44
  209. data/vendor/ruby-signature/stdlib/pathname/pathname.rbs +0 -21
  210. data/vendor/ruby-signature/stdlib/prime/integer-extension.rbs +0 -23
  211. data/vendor/ruby-signature/stdlib/prime/prime.rbs +0 -188
  212. data/vendor/ruby-signature/stdlib/securerandom/securerandom.rbs +0 -9
  213. data/vendor/ruby-signature/stdlib/set/set.rbs +0 -77
  214. data/vendor/ruby-signature/stdlib/tmpdir/tmpdir.rbs +0 -53
@@ -9,6 +9,7 @@ module Steep
9
9
  attr_reader :ignored_sources
10
10
  attr_reader :no_builtin
11
11
  attr_reader :vendor_dir
12
+ attr_reader :strictness_level
12
13
 
13
14
  def initialize(name, sources: [], libraries: [], signatures: [], ignored_sources: [])
14
15
  @name = name
@@ -17,6 +18,7 @@ module Steep
17
18
  @signatures = signatures
18
19
  @ignored_sources = ignored_sources
19
20
  @vendor_dir = nil
21
+ @strictness_level = :default
20
22
  end
21
23
 
22
24
  def initialize_copy(other)
@@ -26,6 +28,7 @@ module Steep
26
28
  @signatures = other.signatures.dup
27
29
  @ignored_sources = other.ignored_sources.dup
28
30
  @vendor_dir = other.vendor_dir
31
+ @strictness_level = other.strictness_level
29
32
  end
30
33
 
31
34
  def check(*args)
@@ -40,6 +43,10 @@ module Steep
40
43
  libraries.push(*args)
41
44
  end
42
45
 
46
+ def typing_options(level)
47
+ @strictness_level = level
48
+ end
49
+
43
50
  def signature(*args)
44
51
  signatures.push(*args)
45
52
  end
@@ -114,6 +121,13 @@ module Steep
114
121
  options: Options.new.tap do |options|
115
122
  options.libraries.push(*target.libraries)
116
123
 
124
+ case target.strictness_level
125
+ when :strict
126
+ options.apply_strict_typing_options!
127
+ when :lenient
128
+ options.apply_lenient_typing_options!
129
+ end
130
+
117
131
  case target.vendor_dir
118
132
  when Array
119
133
  options.vendored_stdlib_path = target.vendor_dir[0]
@@ -31,65 +31,72 @@ module Steep
31
31
  case status
32
32
  when TypeCheckStatus
33
33
  status.typing.errors
34
- # errors.reject do |error|
35
- # case
36
- # when error.is_a?(Errors::FallbackAny)
37
- # !options.fallback_any_is_error
38
- # when error.is_a?(Errors::MethodDefinitionMissing)
39
- # options.allow_missing_definitions
40
- # end
41
- # end
42
34
  else
43
35
  []
44
36
  end
45
37
  end
46
38
 
39
+ def self.parse(source_code, path:, factory:)
40
+ Source.parse(source_code, path: path.to_s, factory: factory, labeling: ASTUtils::Labeling.new)
41
+ end
42
+
43
+ def self.type_check(source, subtyping:)
44
+ annotations = source.annotations(block: source.node, factory: subtyping.factory, current_module: AST::Namespace.root)
45
+ const_env = TypeInference::ConstantEnv.new(factory: subtyping.factory, context: [AST::Namespace.root])
46
+ type_env = TypeInference::TypeEnv.build(annotations: annotations,
47
+ subtyping: subtyping,
48
+ const_env: const_env,
49
+ signatures: subtyping.factory.env)
50
+ lvar_env = TypeInference::LocalVariableTypeEnv.empty(
51
+ subtyping: subtyping,
52
+ self_type: AST::Builtin::Object.instance_type
53
+ ).annotate(annotations)
54
+
55
+ context = TypeInference::Context.new(
56
+ block_context: nil,
57
+ module_context: TypeInference::Context::ModuleContext.new(
58
+ instance_type: nil,
59
+ module_type: nil,
60
+ implement_name: nil,
61
+ current_namespace: AST::Namespace.root,
62
+ const_env: const_env,
63
+ class_name: nil
64
+ ),
65
+ method_context: nil,
66
+ break_context: nil,
67
+ self_type: AST::Builtin::Object.instance_type,
68
+ type_env: type_env,
69
+ lvar_env: lvar_env
70
+ )
71
+
72
+ typing = Typing.new(source: source, root_context: context)
73
+
74
+ construction = TypeConstruction.new(
75
+ checker: subtyping,
76
+ annotations: annotations,
77
+ source: source,
78
+ context: context,
79
+ typing: typing
80
+ )
81
+
82
+ construction.synthesize(source.node) if source.node
83
+
84
+ typing
85
+ end
86
+
47
87
  def type_check(subtyping, env_updated_at)
48
88
  # skip type check
49
89
  return false if status.is_a?(TypeCheckStatus) && env_updated_at <= status.timestamp
50
90
 
51
91
  parse(subtyping.factory) do |source|
52
- typing = Typing.new
53
-
54
- if source
55
- annotations = source.annotations(block: source.node, factory: subtyping.factory, current_module: AST::Namespace.root)
56
- const_env = TypeInference::ConstantEnv.new(factory: subtyping.factory, context: nil)
57
- type_env = TypeInference::TypeEnv.build(annotations: annotations,
58
- subtyping: subtyping,
59
- const_env: const_env,
60
- signatures: subtyping.factory.env)
61
-
62
- construction = TypeConstruction.new(
63
- checker: subtyping,
64
- annotations: annotations,
65
- source: source,
66
- context: TypeInference::Context.new(
67
- block_context: nil,
68
- module_context: TypeInference::Context::ModuleContext.new(
69
- instance_type: nil,
70
- module_type: nil,
71
- implement_name: nil,
72
- current_namespace: AST::Namespace.root,
73
- const_env: const_env,
74
- class_name: nil
75
- ),
76
- method_context: nil,
77
- break_context: nil,
78
- self_type: AST::Builtin::Object.instance_type,
79
- type_env: type_env
80
- ),
81
- typing: typing
82
- )
83
-
84
- construction.synthesize(source.node)
85
- end
86
-
92
+ typing = self.class.type_check(source, subtyping: subtyping)
87
93
  @status = TypeCheckStatus.new(
88
94
  typing: typing,
89
95
  source: source,
90
96
  timestamp: Time.now
91
97
  )
92
98
  rescue => exn
99
+ Steep.log_error(exn)
93
100
  @status = TypeCheckErrorStatus.new(error: exn)
94
101
  end
95
102
 
@@ -100,7 +107,7 @@ module Steep
100
107
  if status.is_a?(TypeCheckStatus)
101
108
  yield status.source
102
109
  else
103
- yield Source.parse(content, path: path.to_s, factory: factory, labeling: ASTUtils::Labeling.new)
110
+ yield self.class.parse(content, path: path, factory: factory)
104
111
  end
105
112
  rescue AnnotationParser::SyntaxError => exn
106
113
  Steep.logger.warn { "Annotation syntax error on #{path}: #{exn.inspect}" }
@@ -133,10 +140,10 @@ module Steep
133
140
  end
134
141
 
135
142
  def load!
136
- buffer = Ruby::Signature::Buffer.new(name: path, content: content)
137
- decls = Ruby::Signature::Parser.parse_signature(buffer)
143
+ buffer = RBS::Buffer.new(name: path, content: content)
144
+ decls = RBS::Parser.parse_signature(buffer)
138
145
  @status = DeclarationsStatus.new(declarations: decls)
139
- rescue Ruby::Signature::Parser::SyntaxError, Ruby::Signature::Parser::SemanticsError => exn
146
+ rescue RBS::Parser::SyntaxError, RBS::Parser::SemanticsError => exn
140
147
  @status = ParseErrorStatus.new(error: exn)
141
148
  end
142
149
  end
@@ -33,21 +33,30 @@ module Steep
33
33
  end
34
34
 
35
35
  def content_for(path:, line:, column:)
36
- source_file = project.targets.map {|target| target.source_files[path] }.compact[0]
36
+ target = project.targets.find {|target| target.source_file?(path) }
37
+
38
+ if target
39
+ source_file = target.source_files[path]
40
+ target.type_check(target_sources: [source_file], validate_signatures: false)
37
41
 
38
- if source_file
39
42
  case (status = source_file.status)
40
43
  when SourceFile::TypeCheckStatus
41
44
  node, *parents = status.source.find_nodes(line: line, column: column)
42
45
 
43
46
  if node
44
47
  case node.type
45
- when :lvar, :lvasgn
48
+ when :lvar
46
49
  var_name = node.children[0]
47
- context = status.typing.context_of(node: node)
48
- var_type = context.type_env.get(lvar: var_name.name)
50
+ context = status.typing.context_at(line: line, column: column)
51
+ var_type = context.lvar_env[var_name.name] || AST::Types::Any.new(location: nil)
49
52
 
50
53
  VariableContent.new(node: node, name: var_name.name, type: var_type, location: node.location.name)
54
+ when :lvasgn
55
+ var_name, rhs = node.children
56
+ context = status.typing.context_at(line: line, column: column)
57
+ type = context.lvar_env[var_name.name] || status.typing.type_of(node: rhs)
58
+
59
+ VariableContent.new(node: node, name: var_name.name, type: type, location: node.location.name)
51
60
  when :send
52
61
  receiver, method_name, *_ = node.children
53
62
 
@@ -58,7 +67,7 @@ module Steep
58
67
  node
59
68
  end
60
69
 
61
- context = status.typing.context_of(node: result_node)
70
+ context = status.typing.context_at(line: line, column: column)
62
71
 
63
72
  receiver_type = if receiver
64
73
  status.typing.type_of(node: receiver)
@@ -98,10 +107,10 @@ module Steep
98
107
  location: result_node.location.expression
99
108
  )
100
109
  when :def, :defs
101
- context = status.typing.context_of(node: node)
110
+ context = status.typing.context_at(line: line, column: column)
102
111
  method_context = context.method_context
103
112
 
104
- if method_context
113
+ if method_context && method_context.method
105
114
  DefinitionContent.new(
106
115
  node: node,
107
116
  method_name: method_context.name,
@@ -1,20 +1,42 @@
1
1
  module Steep
2
2
  class Project
3
3
  class Options
4
- attr_accessor :fallback_any_is_error
4
+ attr_accessor :allow_fallback_any
5
5
  attr_accessor :allow_missing_definitions
6
+ attr_accessor :allow_unknown_constant_assignment
7
+ attr_accessor :allow_unknown_method_calls
6
8
  attr_accessor :vendored_stdlib_path
7
9
  attr_accessor :vendored_gems_path
8
10
  attr_reader :libraries
9
11
 
10
12
  def initialize
11
- self.fallback_any_is_error = false
12
- self.allow_missing_definitions = true
13
+ apply_default_typing_options!
13
14
  self.vendored_gems_path = nil
14
15
  self.vendored_stdlib_path = nil
15
16
 
16
17
  @libraries = []
17
18
  end
19
+
20
+ def apply_default_typing_options!
21
+ self.allow_fallback_any = true
22
+ self.allow_missing_definitions = true
23
+ self.allow_unknown_constant_assignment = false
24
+ self.allow_unknown_method_calls = false
25
+ end
26
+
27
+ def apply_strict_typing_options!
28
+ self.allow_fallback_any = false
29
+ self.allow_missing_definitions = false
30
+ self.allow_unknown_constant_assignment = false
31
+ self.allow_unknown_method_calls = false
32
+ end
33
+
34
+ def apply_lenient_typing_options!
35
+ self.allow_fallback_any = true
36
+ self.allow_missing_definitions = true
37
+ self.allow_unknown_constant_assignment = true
38
+ self.allow_unknown_method_calls = true
39
+ end
18
40
  end
19
41
  end
20
42
  end
@@ -67,32 +67,38 @@ module Steep
67
67
  end
68
68
 
69
69
  def possible_source_file?(path)
70
- self.class.test_pattern(source_patterns, path) &&
71
- !self.class.test_pattern(ignore_patterns, path)
70
+ self.class.test_pattern(source_patterns, path, ext: ".rb") &&
71
+ !self.class.test_pattern(ignore_patterns, path, ext: ".rb")
72
72
  end
73
73
 
74
74
  def possible_signature_file?(path)
75
- self.class.test_pattern(signature_patterns, path)
75
+ self.class.test_pattern(signature_patterns, path, ext: ".rbs")
76
76
  end
77
77
 
78
- def self.test_pattern(patterns, path)
78
+ def self.test_pattern(patterns, path, ext:)
79
79
  patterns.any? do |pattern|
80
80
  p = pattern.end_with?(File::Separator) ? pattern : pattern + File::Separator
81
- path.to_s.start_with?(p) || File.fnmatch(pattern, path.to_s)
81
+ (path.to_s.start_with?(p) && path.extname == ext) || File.fnmatch(pattern, path.to_s)
82
82
  end
83
83
  end
84
84
 
85
- def type_check
86
- load_signatures do |env, check, timestamp|
87
- run_type_check(env, check, timestamp)
85
+ def type_check(target_sources: source_files.values, validate_signatures: true)
86
+ Steep.logger.tagged "target#type_check(target_sources: [#{target_sources.map(&:path).join(", ")}], validate_signatures: #{validate_signatures})" do
87
+ Steep.measure "load signature and type check" do
88
+ load_signatures(validate: validate_signatures) do |env, check, timestamp|
89
+ Steep.measure "type checking #{target_sources.size} files" do
90
+ run_type_check(env, check, timestamp, target_sources: target_sources)
91
+ end
92
+ end
93
+ end
88
94
  end
89
95
  end
90
96
 
91
97
  def environment
92
- @environment ||= Ruby::Signature::Environment.new().tap do |env|
93
- stdlib_root = options.vendored_stdlib_path || Ruby::Signature::EnvironmentLoader::STDLIB_ROOT
98
+ @environment ||= RBS::Environment.new().tap do |env|
99
+ stdlib_root = options.vendored_stdlib_path || RBS::EnvironmentLoader::STDLIB_ROOT
94
100
  gem_vendor_path = options.vendored_gems_path
95
- loader = Ruby::Signature::EnvironmentLoader.new(stdlib_root: stdlib_root, gem_vendor_path: gem_vendor_path)
101
+ loader = RBS::EnvironmentLoader.new(stdlib_root: stdlib_root, gem_vendor_path: gem_vendor_path)
96
102
  options.libraries.each do |lib|
97
103
  loader.add(library: lib)
98
104
  end
@@ -100,7 +106,7 @@ module Steep
100
106
  end
101
107
  end
102
108
 
103
- def load_signatures
109
+ def load_signatures(validate:)
104
110
  timestamp = case status
105
111
  when TypeCheckStatus
106
112
  status.timestamp
@@ -129,20 +135,24 @@ module Steep
129
135
  end
130
136
  end
131
137
 
132
- definition_builder = Ruby::Signature::DefinitionBuilder.new(env: env)
138
+ definition_builder = RBS::DefinitionBuilder.new(env: env)
133
139
  factory = AST::Types::Factory.new(builder: definition_builder)
134
140
  check = Subtyping::Check.new(factory: factory)
135
141
 
136
- validator = Signature::Validator.new(checker: check)
137
- validator.validate()
138
-
139
- if validator.no_error?
140
- yield env, check, Time.now
142
+ if validate
143
+ validator = Signature::Validator.new(checker: check)
144
+ validator.validate()
145
+
146
+ if validator.no_error?
147
+ yield env, check, Time.now
148
+ else
149
+ @status = SignatureValidationErrorStatus.new(
150
+ errors: validator.each_error.to_a,
151
+ timestamp: Time.now
152
+ )
153
+ end
141
154
  else
142
- @status = SignatureValidationErrorStatus.new(
143
- errors: validator.each_error.to_a,
144
- timestamp: Time.now
145
- )
155
+ yield env, check, Time.now
146
156
  end
147
157
  end
148
158
 
@@ -160,10 +170,10 @@ module Steep
160
170
  end
161
171
  end
162
172
 
163
- def run_type_check(env, check, timestamp)
173
+ def run_type_check(env, check, timestamp, target_sources: source_files.values)
164
174
  type_check_sources = []
165
175
 
166
- source_files.each_value do |file|
176
+ target_sources.each do |file|
167
177
  if file.type_check(check, timestamp)
168
178
  type_check_sources << file
169
179
  end
@@ -177,6 +187,12 @@ module Steep
177
187
  )
178
188
  end
179
189
 
190
+ def no_error?
191
+ source_files.all? do |_, file|
192
+ file.status.is_a?(Project::SourceFile::TypeCheckStatus)
193
+ end
194
+ end
195
+
180
196
  def errors
181
197
  case status
182
198
  when TypeCheckStatus
@@ -0,0 +1,56 @@
1
+ module Steep
2
+ module Server
3
+ class BaseWorker
4
+ LSP = LanguageServer::Protocol
5
+
6
+ include Utils
7
+
8
+ attr_reader :project
9
+ attr_reader :reader, :writer
10
+
11
+ def initialize(project:, reader:, writer:)
12
+ @project = project
13
+ @reader = reader
14
+ @writer = writer
15
+ end
16
+
17
+ def handle_request(request)
18
+ # process request
19
+ end
20
+
21
+ def handle_job(job)
22
+ # process async job
23
+ end
24
+
25
+ def run
26
+ tags = Steep.logger.formatter.current_tags.dup
27
+ thread = Thread.new do
28
+ Steep.logger.formatter.push_tags(*tags)
29
+ Steep.logger.tagged "background" do
30
+ while job = queue.pop
31
+ handle_job(job)
32
+ end
33
+ end
34
+ end
35
+
36
+ Steep.logger.tagged "frontend" do
37
+ begin
38
+ reader.read do |request|
39
+ case request[:method]
40
+ when "shutdown"
41
+ # nop
42
+ when "exit"
43
+ break
44
+ else
45
+ handle_request(request)
46
+ end
47
+ end
48
+ ensure
49
+ queue << nil
50
+ thread.join
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end