steep 1.4.0.dev.3 → 1.4.0.dev.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1911,10 +1911,12 @@ module Steep
1911
1911
  when_clause_constr = condition_constr
1912
1912
  body_envs = [] #: Array[TypeInference::TypeEnv]
1913
1913
 
1914
+ # @type var tests: Array[Parser::AST::Node]
1915
+ # @type var body: Parser::AST::Node?
1914
1916
  *tests, body = when_clause.children
1915
1917
 
1916
1918
  tests.each do |test|
1917
- test_type, condition_constr = condition_constr.synthesize(test, condition: true).to_ary
1919
+ test_type, condition_constr = condition_constr.synthesize(test, condition: true)
1918
1920
  truthy_env, falsy_env = interpreter.eval(env: condition_constr.context.type_env, node: test)
1919
1921
 
1920
1922
  condition_constr = condition_constr.update_type_env { falsy_env }
@@ -3181,46 +3183,65 @@ module Steep
3181
3183
  receiver_type = checker.factory.deep_expand_alias(recv_type)
3182
3184
  private = receiver.nil? || receiver.type == :self
3183
3185
 
3184
- type, constr = case receiver_type
3185
- when nil
3186
- raise
3187
-
3188
- when AST::Types::Any
3189
- constr = constr.synthesize_children(node, skips: [receiver])
3190
- constr.add_call(
3191
- TypeInference::MethodCall::Untyped.new(
3192
- node: node,
3193
- context: context.call_context,
3194
- method_name: method_name
3195
- )
3196
- )
3186
+ type, constr =
3187
+ case receiver_type
3188
+ when nil
3189
+ raise
3197
3190
 
3198
- else
3199
- if interface = calculate_interface(receiver_type, private: private)
3200
- constr.type_send_interface(
3201
- node,
3202
- interface: interface,
3203
- receiver: receiver,
3204
- receiver_type: receiver_type,
3205
- method_name: method_name,
3206
- arguments: arguments,
3207
- block_params: block_params,
3208
- block_body: block_body,
3209
- tapp: tapp
3210
- )
3211
- else
3212
- constr = constr.synthesize_children(node, skips: [receiver])
3213
- constr.add_call(
3214
- TypeInference::MethodCall::NoMethodError.new(
3215
- node: node,
3216
- context: context.call_context,
3217
- method_name: method_name,
3218
- receiver_type: receiver_type,
3219
- error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: receiver_type)
3220
- )
3221
- )
3222
- end
3223
- end
3191
+ when AST::Types::Any
3192
+ case node.type
3193
+ when :block, :numblock
3194
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
3195
+ block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
3196
+ block_params or raise
3197
+
3198
+ constr = constr.synthesize_children(node.children[0])
3199
+
3200
+ constr.type_block_without_hint(
3201
+ node: node,
3202
+ block_params: TypeInference::BlockParams.from_node(block_params, annotations: block_annotations),
3203
+ block_annotations: block_annotations,
3204
+ block_body: block_body
3205
+ ) do |error|
3206
+ constr.typing.errors << error
3207
+ end
3208
+ else
3209
+ constr = constr.synthesize_children(node, skips: [receiver])
3210
+ end
3211
+
3212
+ constr.add_call(
3213
+ TypeInference::MethodCall::Untyped.new(
3214
+ node: node,
3215
+ context: context.call_context,
3216
+ method_name: method_name
3217
+ )
3218
+ )
3219
+ else
3220
+ if interface = calculate_interface(receiver_type, private: private)
3221
+ constr.type_send_interface(
3222
+ node,
3223
+ interface: interface,
3224
+ receiver: receiver,
3225
+ receiver_type: receiver_type,
3226
+ method_name: method_name,
3227
+ arguments: arguments,
3228
+ block_params: block_params,
3229
+ block_body: block_body,
3230
+ tapp: tapp
3231
+ )
3232
+ else
3233
+ constr = constr.synthesize_children(node, skips: [receiver])
3234
+ constr.add_call(
3235
+ TypeInference::MethodCall::NoMethodError.new(
3236
+ node: node,
3237
+ context: context.call_context,
3238
+ method_name: method_name,
3239
+ receiver_type: receiver_type,
3240
+ error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: receiver_type)
3241
+ )
3242
+ )
3243
+ end
3244
+ end
3224
3245
 
3225
3246
  Pair.new(type: type, constr: constr)
3226
3247
  end
@@ -1,6 +1,6 @@
1
1
  module Steep
2
2
  module TypeInference
3
- class MethodCall
3
+ module MethodCall
4
4
  class MethodDecl
5
5
  attr_reader :method_name
6
6
  attr_reader :method_def
@@ -569,7 +569,7 @@ module Steep
569
569
 
570
570
  def each
571
571
  if block_given?
572
- errors = []
572
+ errors = [] #: Array[PositionalArgs::error_arg | KeywordArgs::error_arg]
573
573
 
574
574
  last_positional_args = positional_arg
575
575
 
@@ -619,12 +619,12 @@ module Steep
619
619
  end
620
620
 
621
621
  if fag = forwarded_args_node
622
- params = Interface::Function::Params.new(
622
+ forward_params = Interface::Function::Params.new(
623
623
  positional_params: last_positional_args.positional_params,
624
624
  keyword_params: keyword_params
625
625
  )
626
626
 
627
- forwarded_args = ForwardedArgs.new(node: fag, params: params)
627
+ forwarded_args = ForwardedArgs.new(node: fag, params: forward_params)
628
628
  else
629
629
  keyword_args.tap do |args|
630
630
  while (a, args = args.next)
@@ -242,12 +242,14 @@ module Steep
242
242
 
243
243
  common_pure_nodes = envs
244
244
  .map {|env| Set.new(env.pure_method_calls.each_key) }
245
- .inject(Set.new(pure_method_calls.each_key)) {|s1, s2| s1.intersection(s2) }
245
+ .inject {|s1, s2| s1.intersection(s2) } || Set[]
246
246
 
247
247
  pure_call_updates = common_pure_nodes.each_with_object({}) do |node, hash|
248
248
  pairs = envs.map {|env| env.pure_method_calls[node] }
249
- refined_type = AST::Types::Union.build(types: pairs.map {|pair| pair[1] || pair[0].return_type })
250
- call, _ = (pure_method_calls[node] or raise)
249
+ refined_type = AST::Types::Union.build(types: pairs.map {|call, type| type || call.return_type })
250
+
251
+ # Any *pure_method_call* can be used because it's *pure*
252
+ (call, _ = envs[0].pure_method_calls[node]) or raise
251
253
 
252
254
  hash[node] = [call, refined_type]
253
255
  end
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "1.4.0.dev.3"
2
+ VERSION = "1.4.0.dev.4"
3
3
  end
data/lib/steep.rb CHANGED
@@ -107,6 +107,7 @@ require "steep/services/hover_provider/ruby"
107
107
  require "steep/services/hover_provider/rbs"
108
108
  require "steep/services/type_name_completion"
109
109
  require "steep/services/completion_provider"
110
+ require "steep/services/signature_help_provider"
110
111
  require "steep/services/stats_calculator"
111
112
  require "steep/services/file_loader"
112
113
  require "steep/services/goto_service"
data/sample/Steepfile CHANGED
@@ -5,6 +5,8 @@ target :lib do
5
5
 
6
6
  check "lib" # Directory name
7
7
 
8
+ library "rbs"
9
+
8
10
  # configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
9
11
  # configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
10
12
  # configure_code_diagnostics do |hash| # You can setup everything yourself
@@ -27,6 +27,271 @@ module LanguageServer
27
27
 
28
28
  HINT: String
29
29
  end
30
+
31
+ module CompletionItemKind
32
+ type t = Integer
33
+
34
+ TEXT: Integer
35
+ METHOD: Integer
36
+ FUNCTION: Integer
37
+ CONSTRUCTOR: Integer
38
+ FIELD: Integer
39
+ VARIABLE: Integer
40
+ CLASS: Integer
41
+ INTERFACE: Integer
42
+ MODULE: Integer
43
+ PROPERTY: Integer
44
+ UNIT: Integer
45
+ VALUE: Integer
46
+ ENUM: Integer
47
+ KEYWORD: Integer
48
+ SNIPPET: Integer
49
+ COLOR: Integer
50
+ FILE: Integer
51
+ REFERENCE: Integer
52
+ FOLDER: Integer
53
+ ENUMMEMBER: Integer
54
+ CONSTANT: Integer
55
+ STRUCT: Integer
56
+ EVENT: Integer
57
+ OPERATOR: Integer
58
+ TYPEPARAMETER: Integer
59
+ end
60
+
61
+ module CompletionItemTag
62
+ type t = Integer
63
+
64
+ Deprecated: Integer
65
+ end
66
+
67
+ module InsertTextFormat
68
+ type t = Integer
69
+
70
+ PLAIN_TEXT: Integer
71
+
72
+ SNIPPET: Integer
73
+ end
74
+
75
+ module InsertTextMode
76
+ type t = Integer
77
+
78
+ AS_IS: Integer
79
+
80
+ ADJUST_INDENTATION: Integer
81
+ end
82
+
83
+ module MarkupKind
84
+ type t = "plaintext" | "markdown"
85
+
86
+ PLAINTEXT: "plaintext"
87
+
88
+ MARKDOWN: "markdown"
89
+ end
90
+ end
91
+
92
+ module Interface
93
+ interface _Base
94
+ def attributes: () -> Hash[Symbol, untyped]
95
+
96
+ alias to_hash attributes
97
+
98
+ def to_json: () -> String
99
+ end
100
+
101
+ class Position
102
+ include _Base
103
+
104
+ # 0-origin line number
105
+ attr_reader line: Integer
106
+
107
+ # 0-origin character position (== cursor position)
108
+ attr_reader character: Integer
109
+
110
+ def initialize: (line: Integer, character: Integer) -> void
111
+ | (Hash[Symbol, untyped]) -> void
112
+ end
113
+
114
+ class Range
115
+ include _Base
116
+
117
+ attr_reader start: Position
118
+
119
+ attr_reader end: Position
120
+
121
+ def initialize: (start: Position, end: Position) -> void
122
+ | (Hash[Symbol, untyped]) -> void
123
+ end
124
+
125
+ class MarkupContent
126
+ include _Base
127
+
128
+ attr_reader kind: Constant::MarkupKind::t
129
+
130
+ attr_reader value: String
131
+
132
+ def initialize: (kind: Constant::MarkupKind::t, value: String) -> void
133
+ end
134
+
135
+ class TextEdit
136
+ include _Base
137
+
138
+ attr_reader range: Range
139
+
140
+ attr_reader new_text: String
141
+
142
+ def initialize: (range: Range, new_text: String) -> void
143
+ end
144
+
145
+ class InsertReplaceEdit
146
+ include _Base
147
+
148
+ attr_reader new_text: String
149
+
150
+ attr_reader insert: Range
151
+
152
+ attr_reader replace: Range
153
+
154
+ def initialize: (new_text: String, insert: Range, replace: Range) -> void
155
+ end
156
+
157
+ class Command
158
+ include _Base
159
+
160
+ attr_reader title: String
161
+
162
+ attr_reader command: String
163
+
164
+ attr_reader arguments: Array[untyped]?
165
+
166
+ def initialize: (title: String, command: String, ?arguments: Array[untyped]?) -> void
167
+ end
168
+
169
+ class Hover
170
+ include _Base
171
+
172
+ attr_reader contents: MarkupContent
173
+
174
+ attr_reader range: Range
175
+
176
+ def initialize: (contents: MarkupContent, range: Range) -> void
177
+ end
178
+
179
+ class CompletionList
180
+ include _Base
181
+
182
+ attr_reader is_incomplete: bool
183
+
184
+ attr_reader items: Array[CompletionItem]
185
+
186
+ def initialize: (items: Array[CompletionItem], is_incomplete: bool) -> void
187
+ end
188
+
189
+ class CompletionItem
190
+ include _Base
191
+
192
+ attr_reader label: String
193
+
194
+ attr_reader label_details: CompletionItemLabelDetails?
195
+
196
+ attr_reader kind: Constant::CompletionItemKind::t?
197
+
198
+ attr_reader tags: Array[Constant::CompletionItemTag::t]?
199
+
200
+ attr_reader detail: String?
201
+
202
+ attr_reader documentation: MarkupContent?
203
+
204
+ attr_reader preselect: bool?
205
+
206
+ attr_reader sort_text: String?
207
+
208
+ attr_reader filter_text: String?
209
+
210
+ attr_reader insert_text: String?
211
+
212
+ attr_reader insert_text_format: Constant::InsertTextFormat::t?
213
+
214
+ attr_reader insert_text_mode: Constant::InsertTextMode::t?
215
+
216
+ attr_reader text_edit: TextEdit | InsertReplaceEdit | nil
217
+
218
+ attr_reader text_edit_text: String?
219
+
220
+ attr_reader additional_text_edits: Array[TextEdit]?
221
+
222
+ attr_reader commit_characters: Array[String]?
223
+
224
+ attr_reader command: Command?
225
+
226
+ attr_reader data: untyped?
227
+
228
+ def initialize:(
229
+ label: String,
230
+ ?label_details: CompletionItemLabelDetails?,
231
+ ?kind: Constant::CompletionItemKind::t?,
232
+ ?tags: Array[Constant::CompletionItemTag::t]?,
233
+ ?detail: String?,
234
+ ?documentation: MarkupContent?,
235
+ ?preselect: bool?,
236
+ ?sort_text: String?,
237
+ ?filter_text: String?,
238
+ ?insert_text: String?,
239
+ ?insert_text_format: Constant::InsertTextFormat::t?,
240
+ ?insert_text_mode: Constant::InsertTextMode::t?,
241
+ ?text_edit: TextEdit | InsertReplaceEdit | nil,
242
+ ?text_edit_text: String?,
243
+ ?additional_text_edits: Array[TextEdit]?,
244
+ ?commit_characters: Array[String]?,
245
+ ?command: Command?,
246
+ ?data: untyped?
247
+ ) -> void
248
+ end
249
+
250
+ class CompletionItemLabelDetails
251
+ include _Base
252
+
253
+ attr_reader detail: String?
254
+
255
+ attr_reader description: String?
256
+
257
+ def initialize: (?detail: String?, ?description: String?) -> void
258
+ end
259
+
260
+ class SignatureInformation
261
+ include _Base
262
+
263
+ attr_reader label: String
264
+
265
+ attr_reader documentation: MarkupContent?
266
+
267
+ attr_reader parameters: Array[ParameterInformation]?
268
+
269
+ attr_reader active_parameter: Integer?
270
+
271
+ def initialize: (label: String, ?documentation: MarkupContent?, ?parameters: Array[ParameterInformation]?, ?active_parameter: Integer?) -> void
272
+ end
273
+
274
+ class ParameterInformation
275
+ include _Base
276
+
277
+ attr_reader label: String | [Integer, Integer]
278
+
279
+ attr_reader documentation: MarkupContent?
280
+
281
+ def initialize: (label: String | [Integer, Integer], ?documentation: MarkupContent) -> void
282
+ end
283
+
284
+ class SignatureHelp
285
+ include _Base
286
+
287
+ attr_reader signatures: Array[SignatureInformation]
288
+
289
+ attr_reader active_signature: Integer?
290
+
291
+ attr_reader active_parameter: Integer?
292
+
293
+ def initialize: (signatures: Array[SignatureInformation], ?active_signature: Integer?, ?active_parameter: Integer?) -> void
294
+ end
30
295
  end
31
296
  end
32
297
  end
data/sig/shims/parser.rbs CHANGED
@@ -43,4 +43,7 @@ module Parser
43
43
  def value: (untyped) -> untyped
44
44
  end
45
45
  end
46
+
47
+ class SyntaxError < StandardError
48
+ end
46
49
  end
@@ -6,6 +6,8 @@ module Steep
6
6
  attr_reader method_name: Symbol
7
7
 
8
8
  def initialize: (type_name: RBS::TypeName, method_name: Symbol) -> void
9
+
10
+ def relative: () -> InstanceMethodName
9
11
  end
10
12
 
11
13
  class SingletonMethodName
@@ -13,6 +15,8 @@ module Steep
13
15
  attr_reader method_name: Symbol
14
16
 
15
17
  def initialize: (type_name: RBS::TypeName, method_name: Symbol) -> void
18
+
19
+ def relative: () -> SingletonMethodName
16
20
  end
17
21
 
18
22
  class ::Object
@@ -20,7 +24,7 @@ module Steep
20
24
  #
21
25
  # * `ClassName#method_name` syntax returns an `InstanceMethodName` object
22
26
  # * `ClassName.method_name` syntax returns a `SingletonMethodName` object
23
- #
27
+ #
24
28
  def MethodName: (String string) -> (InstanceMethodName | SingletonMethodName)
25
29
  end
26
30
  end
@@ -36,7 +36,19 @@ module Steep
36
36
  def initialize: (id: String, path: Pathname, line: Integer, column: Integer, trigger: String) -> void
37
37
  end
38
38
 
39
- type job = ApplyChangeJob | HoverJob | CompletionJob
39
+ class SignatureHelpJob
40
+ attr_reader id: String
41
+
42
+ attr_reader path: Pathname
43
+
44
+ attr_reader line: Integer
45
+
46
+ attr_reader column: Integer
47
+
48
+ def initialize: (id: String, path: Pathname, line: Integer, column: Integer) -> void
49
+ end
50
+
51
+ type job = ApplyChangeJob | HoverJob | CompletionJob | SignatureHelpJob
40
52
 
41
53
  module LSP = LanguageServer::Protocol
42
54
 
@@ -50,21 +62,15 @@ module Steep
50
62
 
51
63
  def handle_request: (lsp_request) -> void
52
64
 
53
- def process_hover: (HoverJob job) -> untyped
54
-
55
- def process_completion: (CompletionJob job) -> untyped
56
-
57
- def format_completion_item_for_rbs: (Services::SignatureService, RBS::TypeName, CompletionJob job, String complete_text, Integer prefix_size) -> untyped
58
-
59
- def format_comment: (Comment? comment) -> untyped?
65
+ def process_hover: (HoverJob job) -> LanguageServer::Protocol::Interface::Hover?
60
66
 
61
- def format_comments: (Array[RBS::AST::Comment] comments) -> untyped?
67
+ def process_completion: (CompletionJob job) -> LanguageServer::Protocol::Interface::CompletionList?
62
68
 
63
- def format_completion_item: (CompletionProvider::item item) -> untyped
69
+ def process_signature_help: (SignatureHelpJob) -> LanguageServer::Protocol::Interface::SignatureHelp?
64
70
 
65
- def method_type_to_snippet: (RBS::MethodType method_type) -> ::String
71
+ def format_completion_item_for_rbs: (Services::SignatureService, RBS::TypeName, CompletionJob job, String complete_text, Integer prefix_size) -> LanguageServer::Protocol::Interface::CompletionItem
66
72
 
67
- def params_to_snippet: (RBS::Types::Function fun) -> String
73
+ def format_completion_item: (CompletionProvider::item item) -> LanguageServer::Protocol::Interface::CompletionItem
68
74
  end
69
75
  end
70
76
  end
@@ -1,38 +1,63 @@
1
+ use RBS::TypeName
2
+
1
3
  module Steep
2
4
  module Server
5
+ # LSPFormatter translates hover content and completion item to markdown string
6
+ #
7
+ # The class has four main methods:
8
+ #
9
+ # * `markup_content` translates a string to `MarkupContent` object
10
+ # * `format_hover_content` translates a hover content to Markdown string
11
+ # * `format_completion_docs` translates a completion item to a documentation
12
+ # * `format_rbs_competion_docs` generates docs for completion item of RBS
13
+ #
3
14
  module LSPFormatter
4
15
  include Services
5
16
 
6
- class CommentBuilder
7
- @array: Array[String]
17
+ module LSP = LanguageServer::Protocol
18
+
19
+ # Translate given String to MarkupContent
20
+ #
21
+ def self?.markup_content: (String?) -> LanguageServer::Protocol::Interface::MarkupContent?
22
+ | () { () -> String? } -> LanguageServer::Protocol::Interface::MarkupContent?
8
23
 
9
- def initialize: () -> void
24
+ # Translates a hover content to String
25
+ #
26
+ def self?.format_hover_content: (Services::HoverProvider::Ruby::content | Services::HoverProvider::RBS::content) -> String
10
27
 
11
- def self.build: () { (CommentBuilder) -> void } -> String
28
+ # Translates a completion item to String
29
+ def self?.format_completion_docs: (Services::CompletionProvider::item) -> String
12
30
 
13
- def to_s: () -> String
31
+ # Translates a completion item for RBS to String
32
+ def self?.format_rbs_completion_docs: (TypeName, summarizable_decl, Array[RBS::AST::Comment]) -> String
14
33
 
15
- def <<: (String? string) -> void
34
+ def self?.format_comment: (RBS::AST::Comment?, ?header: String?) -> String?
35
+ | (RBS::AST::Comment?, ?header: String?) { (String) -> void } -> void
16
36
 
17
- def push: () { (String) -> void } -> void
18
- end
37
+ def self?.format_comments: (Array[[String, RBS::AST::Comment?]]) -> String
19
38
 
20
- def self?.format_hover_content: (Services::HoverProvider::Ruby::content | Services::HoverProvider::RBS::content) -> untyped
39
+ def self?.local_variable: (Symbol, AST::Types::t) -> String
21
40
 
22
- def self?.to_list: [A < Object] (Enumerable[A] collection) ?{ (A) -> String } -> String
41
+ def self?.instance_variable: (Symbol, AST::Types::t) -> String
23
42
 
24
- def self?.name_and_args: (untyped name, untyped args) -> ::String
43
+ # Renders type application
44
+ def self?.name_and_args: (TypeName name, Array[RBS::Types::t] args) -> String
25
45
 
26
- def self?.name_and_params: (untyped name, untyped params) -> ::String
46
+ # Renders generic type definition
47
+ def self?.name_and_params: (TypeName name, Array[RBS::AST::TypeParam] params) -> String
27
48
 
28
- type summarizable_decl = ::RBS::AST::Declarations::Class
29
- | ::RBS::AST::Declarations::Module
30
- | ::RBS::AST::Declarations::Interface
31
- | ::RBS::AST::Declarations::TypeAlias
32
- | ::RBS::AST::Declarations::ClassAlias
33
- | ::RBS::AST::Declarations::ModuleAlias
49
+ type summarizable_decl = RBS::AST::Declarations::Class
50
+ | RBS::AST::Declarations::Module
51
+ | RBS::AST::Declarations::Interface
52
+ | RBS::AST::Declarations::TypeAlias
53
+ | RBS::AST::Declarations::ClassAlias
54
+ | RBS::AST::Declarations::ModuleAlias
55
+ | RBS::AST::Declarations::Global
56
+ | RBS::AST::Declarations::Constant
34
57
 
35
58
  def self?.declaration_summary: (summarizable_decl) -> String
59
+
60
+ def self?.format_method_item_doc: (Array[_ToS], Array[method_name], Hash[method_name, RBS::AST::Comment?], ?String footer) -> String
36
61
  end
37
62
  end
38
63
  end