steep 1.5.0.pre.5 → 1.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/steep/ast/node/type_application.rb +5 -3
- data/lib/steep/ast/node/type_assertion.rb +7 -3
- data/lib/steep/ast/types/factory.rb +7 -0
- data/lib/steep/diagnostic/ruby.rb +161 -33
- data/lib/steep/drivers/init.rb +3 -2
- data/lib/steep/node_helper.rb +23 -0
- data/lib/steep/project/dsl.rb +0 -21
- data/lib/steep/server/interaction_worker.rb +13 -0
- data/lib/steep/server/lsp_formatter.rb +13 -0
- data/lib/steep/services/completion_provider.rb +85 -3
- data/lib/steep/services/hover_provider/ruby.rb +1 -1
- data/lib/steep/services/signature_help_provider.rb +100 -5
- data/lib/steep/source.rb +8 -13
- data/lib/steep/type_construction.rb +58 -28
- data/lib/steep/type_inference/logic_type_interpreter.rb +8 -6
- data/lib/steep/type_inference/send_args.rb +9 -1
- data/lib/steep/version.rb +1 -1
- data/sig/steep/ast/node/type_application.rbs +1 -1
- data/sig/steep/ast/node/type_assertion.rbs +1 -1
- data/sig/steep/ast/types/factory.rbs +1 -2
- data/sig/steep/diagnostic/ruby.rbs +28 -6
- data/sig/steep/node_helper.rbs +9 -0
- data/sig/steep/project/dsl.rbs +7 -2
- data/sig/steep/services/completion_provider.rbs +15 -1
- data/sig/steep/services/signature_help_provider.rbs +12 -2
- data/sig/steep/signature/validator.rbs +2 -2
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77aea7baf36285cf4a5b0941e63cc8f5f95d52132d3a5d4933a396a79b949721
|
4
|
+
data.tar.gz: 2506370595dde6633abbab74b1e370d435579415a154b4a82b4da3bb1b065627
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f3190f0ca65a931f9c88d99cbd67836478d754439b5630b1b68f89e9fa6d84a84cc8bde32335d4bdb38b3f13aefaeaf93a75b53722a0b6841eab27e9b689ed8
|
7
|
+
data.tar.gz: 94576f1eedcb8c46ca8228e84e4100e860c0e3ed2a28dc209afa80abdeeed188118f1589dcb15d0a8edb0cd8c751f611035a15b613d284113c8cbebcce42dc6e
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,42 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 1.5.0 (2023-07-13)
|
6
|
+
|
7
|
+
### Type checker core
|
8
|
+
|
9
|
+
* Fix for the case `untyped` is the proc type hint ([#868](https://github.com/soutaro/steep/pull/868))
|
10
|
+
* Type case with type variable ([#869](https://github.com/soutaro/steep/pull/869))
|
11
|
+
* Filx `nil?` unreachability detection ([#867](https://github.com/soutaro/steep/pull/867))
|
12
|
+
|
13
|
+
### Commandline tool
|
14
|
+
|
15
|
+
* Update `#configure_code_diagnostics` type ([#873](https://github.com/soutaro/steep/pull/873))
|
16
|
+
* Update diagnostics templates ([#871](https://github.com/soutaro/steep/pull/871))
|
17
|
+
* Removed "set" from "libray" in init.rb and README ([#870](https://github.com/soutaro/steep/pull/870))
|
18
|
+
|
19
|
+
### Language server
|
20
|
+
|
21
|
+
* Use RBS::Buffer method to calculate position ([#872](https://github.com/soutaro/steep/pull/872))
|
22
|
+
|
23
|
+
## 1.5.0.pre.6 (2023-07-11)
|
24
|
+
|
25
|
+
### Type checker core
|
26
|
+
|
27
|
+
* Report RBS validation errors in Ruby code ([#859](https://github.com/soutaro/steep/pull/859))
|
28
|
+
* Fix proc type assignment ([#858](https://github.com/soutaro/steep/pull/858))
|
29
|
+
* Report `UnexpectedKeywordArgument` even if no keyword param is accepted ([#856](https://github.com/soutaro/steep/pull/856))
|
30
|
+
* Unfold type alias on unwrap optional ([#855](https://github.com/soutaro/steep/pull/855))
|
31
|
+
|
32
|
+
### Language server
|
33
|
+
|
34
|
+
* Keyword completion in block call ([#865](https://github.com/soutaro/steep/pull/865))
|
35
|
+
* Indicate the current or next argument on signature help ([#850](https://github.com/soutaro/steep/pull/850))
|
36
|
+
* Support completion for keyword arguments ([#851](https://github.com/soutaro/steep/pull/851))
|
37
|
+
* Let hover show the type of method call node ([#864](https://github.com/soutaro/steep/pull/864))
|
38
|
+
* Fix UnknownNodeError in SignatureHelp ([#863](https://github.com/soutaro/steep/pull/863))
|
39
|
+
* hover: Fix NoMethodError on generating hover for not supported files ([#853](https://github.com/soutaro/steep/pull/853))
|
40
|
+
|
5
41
|
## 1.5.0.pre.5 (2023-07-07)
|
6
42
|
|
7
43
|
### Type checker core
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -37,10 +37,12 @@ module Steep
|
|
37
37
|
ty = ty.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
|
38
38
|
|
39
39
|
validator = Signature::Validator.new(checker: subtyping)
|
40
|
-
validator.
|
40
|
+
validator.rescue_validation_errors do
|
41
|
+
validator.validate_type(ty)
|
42
|
+
end
|
41
43
|
|
42
44
|
if validator.has_error?
|
43
|
-
return
|
45
|
+
return validator.each_error
|
44
46
|
end
|
45
47
|
|
46
48
|
ty = subtyping.factory.type(ty)
|
@@ -58,7 +60,7 @@ module Steep
|
|
58
60
|
|
59
61
|
def types?(context, subtyping, type_vars)
|
60
62
|
case types = types(context, subtyping, type_vars)
|
61
|
-
when RBS::ParsingError
|
63
|
+
when RBS::ParsingError, Enumerator
|
62
64
|
nil
|
63
65
|
else
|
64
66
|
types
|
@@ -22,10 +22,14 @@ module Steep
|
|
22
22
|
ty = ty.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
|
23
23
|
|
24
24
|
validator = Signature::Validator.new(checker: subtyping)
|
25
|
-
validator.
|
25
|
+
validator.rescue_validation_errors do
|
26
|
+
validator.validate_type(ty)
|
27
|
+
end
|
26
28
|
|
27
29
|
unless validator.has_error?
|
28
30
|
subtyping.factory.type(ty)
|
31
|
+
else
|
32
|
+
validator.each_error.to_a
|
29
33
|
end
|
30
34
|
else
|
31
35
|
nil
|
@@ -37,7 +41,7 @@ module Steep
|
|
37
41
|
def type_syntax?
|
38
42
|
RBS::Parser.parse_type(type_location.buffer, range: type_location.range, variables: [], require_eof: true)
|
39
43
|
true
|
40
|
-
rescue::RBS::ParsingError
|
44
|
+
rescue ::RBS::ParsingError
|
41
45
|
false
|
42
46
|
end
|
43
47
|
|
@@ -45,7 +49,7 @@ module Steep
|
|
45
49
|
type = type(context, subtyping, type_vars)
|
46
50
|
|
47
51
|
case type
|
48
|
-
when RBS::ParsingError, nil
|
52
|
+
when RBS::ParsingError, nil, Array
|
49
53
|
nil
|
50
54
|
else
|
51
55
|
type
|
@@ -964,6 +964,19 @@ module Steep
|
|
964
964
|
end
|
965
965
|
end
|
966
966
|
|
967
|
+
class RBSError < Base
|
968
|
+
attr_reader :error
|
969
|
+
|
970
|
+
def initialize(error:, node:, location:)
|
971
|
+
@error = error
|
972
|
+
super(node: node, location: location)
|
973
|
+
end
|
974
|
+
|
975
|
+
def header_line
|
976
|
+
error.header_line
|
977
|
+
end
|
978
|
+
end
|
979
|
+
|
967
980
|
ALL = ObjectSpace.each_object(Class).with_object([]) do |klass, array|
|
968
981
|
if klass < Base
|
969
982
|
array << klass
|
@@ -979,20 +992,57 @@ module Steep
|
|
979
992
|
def self.default
|
980
993
|
@default ||= _ = all_error.merge(
|
981
994
|
{
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
995
|
+
ArgumentTypeMismatch => :error,
|
996
|
+
BlockBodyTypeMismatch => :hint,
|
997
|
+
BlockTypeMismatch => :hint,
|
998
|
+
BreakTypeMismatch => :hint,
|
999
|
+
DifferentMethodParameterKind => :hint,
|
1000
|
+
FallbackAny => :hint,
|
1001
|
+
FalseAssertion => :hint,
|
1002
|
+
ImplicitBreakValueMismatch => :hint,
|
1003
|
+
IncompatibleAnnotation => :hint,
|
1004
|
+
IncompatibleArgumentForwarding => :warning,
|
1005
|
+
IncompatibleAssignment => :hint,
|
1006
|
+
IncompatibleMethodTypeAnnotation => :hint,
|
1007
|
+
IncompatibleTypeCase => :hint,
|
1008
|
+
InsufficientKeywordArguments => :error,
|
1009
|
+
InsufficientPositionalArguments => :error,
|
1010
|
+
InsufficientTypeArgument => :hint,
|
1011
|
+
MethodArityMismatch => :error,
|
1012
|
+
MethodBodyTypeMismatch => :error,
|
1013
|
+
MethodDefinitionMissing => nil,
|
1014
|
+
MethodParameterMismatch => :error,
|
1015
|
+
MethodReturnTypeAnnotationMismatch => :hint,
|
1016
|
+
MultipleAssignmentConversionError => :hint,
|
1017
|
+
NoMethod => :error,
|
1018
|
+
ProcHintIgnored => :hint,
|
1019
|
+
ProcTypeExpected => :hint,
|
1020
|
+
RBSError => :information,
|
1021
|
+
RequiredBlockMissing => :error,
|
1022
|
+
ReturnTypeMismatch => :error,
|
1023
|
+
SetterBodyTypeMismatch => :information,
|
1024
|
+
SetterReturnTypeMismatch => :information,
|
1025
|
+
SyntaxError => :hint,
|
1026
|
+
TypeArgumentMismatchError => :hint,
|
1027
|
+
UnexpectedBlockGiven => :warning,
|
1028
|
+
UnexpectedDynamicMethod => :hint,
|
1029
|
+
UnexpectedError => :hint,
|
1030
|
+
UnexpectedJump => :hint,
|
1031
|
+
UnexpectedJumpValue => :hint,
|
1032
|
+
UnexpectedKeywordArgument => :error,
|
1033
|
+
UnexpectedPositionalArgument => :error,
|
1034
|
+
UnexpectedSplat => :hint,
|
1035
|
+
UnexpectedSuper => :information,
|
1036
|
+
UnexpectedTypeArgument => :hint,
|
1037
|
+
UnexpectedYield => :warning,
|
986
1038
|
UnknownConstant => :warning,
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
SetterBodyTypeMismatch => nil,
|
995
|
-
SetterReturnTypeMismatch => nil
|
1039
|
+
UnknownGlobalVariable => :warning,
|
1040
|
+
UnknownInstanceVariable => :information,
|
1041
|
+
UnreachableBranch => :hint,
|
1042
|
+
UnreachableValueBranch => :hint,
|
1043
|
+
UnresolvedOverloading => :error,
|
1044
|
+
UnsatisfiableConstraint => :hint,
|
1045
|
+
UnsupportedSyntax => :hint,
|
996
1046
|
}
|
997
1047
|
).freeze
|
998
1048
|
end
|
@@ -1000,17 +1050,57 @@ module Steep
|
|
1000
1050
|
def self.strict
|
1001
1051
|
@strict ||= _ = all_error.merge(
|
1002
1052
|
{
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1053
|
+
ArgumentTypeMismatch => :error,
|
1054
|
+
BlockBodyTypeMismatch => :error,
|
1055
|
+
BlockTypeMismatch => :error,
|
1056
|
+
BreakTypeMismatch => :error,
|
1057
|
+
DifferentMethodParameterKind => :error,
|
1058
|
+
FallbackAny => :warning,
|
1059
|
+
FalseAssertion => :error,
|
1060
|
+
ImplicitBreakValueMismatch => :information,
|
1061
|
+
IncompatibleAnnotation => :error,
|
1062
|
+
IncompatibleArgumentForwarding => :error,
|
1063
|
+
IncompatibleAssignment => :error,
|
1064
|
+
IncompatibleMethodTypeAnnotation => :error,
|
1065
|
+
IncompatibleTypeCase => :error,
|
1066
|
+
InsufficientKeywordArguments => :error,
|
1067
|
+
InsufficientPositionalArguments => :error,
|
1068
|
+
InsufficientTypeArgument => :error,
|
1069
|
+
MethodArityMismatch => :error,
|
1070
|
+
MethodBodyTypeMismatch => :error,
|
1071
|
+
MethodDefinitionMissing => :hint,
|
1072
|
+
MethodParameterMismatch => :error,
|
1073
|
+
MethodReturnTypeAnnotationMismatch => :error,
|
1074
|
+
MultipleAssignmentConversionError => :error,
|
1075
|
+
NoMethod => :error,
|
1076
|
+
ProcHintIgnored => :information,
|
1077
|
+
ProcTypeExpected => :error,
|
1078
|
+
RBSError => :error,
|
1079
|
+
RequiredBlockMissing => :error,
|
1080
|
+
ReturnTypeMismatch => :error,
|
1012
1081
|
SetterBodyTypeMismatch => :error,
|
1013
|
-
SetterReturnTypeMismatch => :error
|
1082
|
+
SetterReturnTypeMismatch => :error,
|
1083
|
+
SyntaxError => :hint,
|
1084
|
+
TypeArgumentMismatchError => :error,
|
1085
|
+
UnexpectedBlockGiven => :error,
|
1086
|
+
UnexpectedDynamicMethod => :information,
|
1087
|
+
UnexpectedError => :information,
|
1088
|
+
UnexpectedJump => :error,
|
1089
|
+
UnexpectedJumpValue => :error,
|
1090
|
+
UnexpectedKeywordArgument => :error,
|
1091
|
+
UnexpectedPositionalArgument => :error,
|
1092
|
+
UnexpectedSplat => :warning,
|
1093
|
+
UnexpectedSuper => :error,
|
1094
|
+
UnexpectedTypeArgument => :error,
|
1095
|
+
UnexpectedYield => :error,
|
1096
|
+
UnknownConstant => :error,
|
1097
|
+
UnknownGlobalVariable => :error,
|
1098
|
+
UnknownInstanceVariable => :error,
|
1099
|
+
UnreachableBranch => :information,
|
1100
|
+
UnreachableValueBranch => :warning,
|
1101
|
+
UnresolvedOverloading => :error,
|
1102
|
+
UnsatisfiableConstraint => :error,
|
1103
|
+
UnsupportedSyntax => :information,
|
1014
1104
|
}
|
1015
1105
|
).freeze
|
1016
1106
|
end
|
@@ -1018,19 +1108,57 @@ module Steep
|
|
1018
1108
|
def self.lenient
|
1019
1109
|
@lenient ||= _ = all_error.merge(
|
1020
1110
|
{
|
1021
|
-
|
1022
|
-
|
1111
|
+
ArgumentTypeMismatch => :information,
|
1112
|
+
BlockBodyTypeMismatch => :hint,
|
1113
|
+
BlockTypeMismatch => :hint,
|
1114
|
+
BreakTypeMismatch => :hint,
|
1115
|
+
DifferentMethodParameterKind => nil,
|
1023
1116
|
FallbackAny => nil,
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1117
|
+
FalseAssertion => nil,
|
1118
|
+
ImplicitBreakValueMismatch => nil,
|
1119
|
+
IncompatibleAnnotation => nil,
|
1120
|
+
IncompatibleArgumentForwarding => :information,
|
1121
|
+
IncompatibleAssignment => :hint,
|
1122
|
+
IncompatibleMethodTypeAnnotation => nil,
|
1123
|
+
IncompatibleTypeCase => nil,
|
1124
|
+
InsufficientKeywordArguments => :information,
|
1125
|
+
InsufficientPositionalArguments => :information,
|
1126
|
+
InsufficientTypeArgument => nil,
|
1127
|
+
MethodArityMismatch => :information,
|
1128
|
+
MethodBodyTypeMismatch => :warning,
|
1027
1129
|
MethodDefinitionMissing => nil,
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1130
|
+
MethodParameterMismatch => :warning,
|
1131
|
+
MethodReturnTypeAnnotationMismatch => nil,
|
1132
|
+
MultipleAssignmentConversionError => nil,
|
1133
|
+
NoMethod => :information,
|
1134
|
+
ProcHintIgnored => nil,
|
1135
|
+
ProcTypeExpected => nil,
|
1136
|
+
RBSError => :information,
|
1137
|
+
RequiredBlockMissing => :hint,
|
1138
|
+
ReturnTypeMismatch => :warning,
|
1032
1139
|
SetterBodyTypeMismatch => nil,
|
1033
|
-
SetterReturnTypeMismatch => nil
|
1140
|
+
SetterReturnTypeMismatch => nil,
|
1141
|
+
SyntaxError => :hint,
|
1142
|
+
TypeArgumentMismatchError => nil,
|
1143
|
+
UnexpectedBlockGiven => :hint,
|
1144
|
+
UnexpectedDynamicMethod => nil,
|
1145
|
+
UnexpectedError => :hint,
|
1146
|
+
UnexpectedJump => nil,
|
1147
|
+
UnexpectedJumpValue => nil,
|
1148
|
+
UnexpectedKeywordArgument => :information,
|
1149
|
+
UnexpectedPositionalArgument => :information,
|
1150
|
+
UnexpectedSplat => nil,
|
1151
|
+
UnexpectedSuper => nil,
|
1152
|
+
UnexpectedTypeArgument => nil,
|
1153
|
+
UnexpectedYield => :information,
|
1154
|
+
UnknownConstant => :hint,
|
1155
|
+
UnknownGlobalVariable => :hint,
|
1156
|
+
UnknownInstanceVariable => :hint,
|
1157
|
+
UnreachableBranch => :hint,
|
1158
|
+
UnreachableValueBranch => :hint,
|
1159
|
+
UnresolvedOverloading => :information,
|
1160
|
+
UnsatisfiableConstraint => :hint,
|
1161
|
+
UnsupportedSyntax => :hint,
|
1034
1162
|
}
|
1035
1163
|
).freeze
|
1036
1164
|
end
|
data/lib/steep/drivers/init.rb
CHANGED
@@ -18,9 +18,10 @@ module Steep
|
|
18
18
|
# check "app/models/**/*.rb" # Glob
|
19
19
|
# # ignore "lib/templates/*.rb"
|
20
20
|
#
|
21
|
-
# # library "pathname"
|
21
|
+
# # library "pathname" # Standard libraries
|
22
22
|
# # library "strong_json" # Gems
|
23
23
|
#
|
24
|
+
# # configure_code_diagnostics(D::Ruby.default) # `default` diagnostics setting (applies by default)
|
24
25
|
# # configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
|
25
26
|
# # configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
|
26
27
|
# # configure_code_diagnostics(D::Ruby.silent) # `silent` diagnostics setting
|
@@ -34,7 +35,7 @@ module Steep
|
|
34
35
|
#
|
35
36
|
# check "test"
|
36
37
|
#
|
37
|
-
# # library "pathname"
|
38
|
+
# # library "pathname" # Standard libraries
|
38
39
|
# end
|
39
40
|
EOF
|
40
41
|
|
data/lib/steep/node_helper.rb
CHANGED
@@ -217,5 +217,28 @@ module Steep
|
|
217
217
|
false
|
218
218
|
end
|
219
219
|
end
|
220
|
+
|
221
|
+
def deconstruct_sendish_and_block_nodes(*nodes)
|
222
|
+
send_node, block_node = nodes.take(2)
|
223
|
+
|
224
|
+
if send_node
|
225
|
+
case send_node.type
|
226
|
+
when :send, :csend, :super
|
227
|
+
if block_node
|
228
|
+
case block_node.type
|
229
|
+
when :block, :numblock
|
230
|
+
if send_node.equal?(block_node.children[0])
|
231
|
+
return [send_node, block_node]
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
[send_node, nil]
|
237
|
+
when :zsuper
|
238
|
+
# zsuper doesn't receive block
|
239
|
+
[send_node, nil]
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
220
243
|
end
|
221
244
|
end
|
data/lib/steep/project/dsl.rb
CHANGED
@@ -143,27 +143,6 @@ module Steep
|
|
143
143
|
@repo_paths.push(*paths.map {|s| Pathname(s) })
|
144
144
|
end
|
145
145
|
|
146
|
-
# Configure the code diagnostics printing setup.
|
147
|
-
#
|
148
|
-
# Yields a hash, and the update the hash in the block.
|
149
|
-
#
|
150
|
-
# ```rb
|
151
|
-
# D = Steep::Diagnostic
|
152
|
-
#
|
153
|
-
# configure_code_diagnostics do |hash|
|
154
|
-
# # Assign one of :error, :warning, :information, :hint or :nil to error classes.
|
155
|
-
# hash[D::Ruby::UnexpectedPositionalArgument] = :error
|
156
|
-
# end
|
157
|
-
# ```
|
158
|
-
#
|
159
|
-
# Passing a hash is also allowed.
|
160
|
-
#
|
161
|
-
# ```rb
|
162
|
-
# D = Steep::Diagnostic
|
163
|
-
#
|
164
|
-
# configure_code_diagnostics(D::Ruby.lenient)
|
165
|
-
# ```
|
166
|
-
#
|
167
146
|
def configure_code_diagnostics(hash = nil)
|
168
147
|
if hash
|
169
148
|
code_diagnostics_config.merge!(hash)
|
@@ -361,6 +361,17 @@ module Steep
|
|
361
361
|
new_text: item.identifier.to_s
|
362
362
|
)
|
363
363
|
)
|
364
|
+
when Services::CompletionProvider::KeywordArgumentItem
|
365
|
+
LSP::Interface::CompletionItem.new(
|
366
|
+
label: item.identifier.to_s,
|
367
|
+
kind: LSP::Constant::CompletionItemKind::FIELD,
|
368
|
+
label_details: LSP::Interface::CompletionItemLabelDetails.new(description: 'Keyword argument'),
|
369
|
+
documentation: LSPFormatter.markup_content { LSPFormatter.format_completion_docs(item) },
|
370
|
+
text_edit: LSP::Interface::TextEdit.new(
|
371
|
+
range: range,
|
372
|
+
new_text: item.identifier.to_s
|
373
|
+
)
|
374
|
+
)
|
364
375
|
when Services::CompletionProvider::TypeNameItem
|
365
376
|
kind =
|
366
377
|
case
|
@@ -397,6 +408,8 @@ module Steep
|
|
397
408
|
signatures = items.map do |item|
|
398
409
|
LSP::Interface::SignatureInformation.new(
|
399
410
|
label: "(#{item.method_type.type.param_to_s})",
|
411
|
+
parameters: item.parameters.map { |param| LSP::Interface::ParameterInformation.new(label: param)},
|
412
|
+
active_parameter: item.active_parameter,
|
400
413
|
documentation: item.comment&.yield_self do |comment|
|
401
414
|
LSP::Interface::MarkupContent.new(
|
402
415
|
kind: LSP::Constant::MarkupKind::MARKDOWN,
|
@@ -28,7 +28,16 @@ module Steep
|
|
28
28
|
|
29
29
|
case call
|
30
30
|
when TypeInference::MethodCall::Typed
|
31
|
+
io.puts <<~MD
|
32
|
+
```rbs
|
33
|
+
#{call.actual_method_type.type.return_type}
|
34
|
+
```
|
35
|
+
|
36
|
+
----
|
37
|
+
MD
|
38
|
+
|
31
39
|
method_types = call.method_decls.map(&:method_type)
|
40
|
+
|
32
41
|
if call.is_a?(TypeInference::MethodCall::Special)
|
33
42
|
method_types = [
|
34
43
|
call.actual_method_type.with(
|
@@ -250,6 +259,10 @@ module Steep
|
|
250
259
|
end
|
251
260
|
|
252
261
|
io.string
|
262
|
+
when Services::CompletionProvider::KeywordArgumentItem
|
263
|
+
<<~MD
|
264
|
+
**Keyword argument**: `#{item.identifier}`
|
265
|
+
MD
|
253
266
|
end
|
254
267
|
end
|
255
268
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Steep
|
2
2
|
module Services
|
3
3
|
class CompletionProvider
|
4
|
+
include NodeHelper
|
5
|
+
|
4
6
|
Position = _ = Struct.new(:line, :column, keyword_init: true) do
|
5
7
|
# @implements Position
|
6
8
|
def -(size)
|
@@ -11,6 +13,7 @@ module Steep
|
|
11
13
|
Range = _ = Struct.new(:start, :end, keyword_init: true)
|
12
14
|
|
13
15
|
InstanceVariableItem = _ = Struct.new(:identifier, :range, :type, keyword_init: true)
|
16
|
+
KeywordArgumentItem = _ = Struct.new(:identifier, :range, keyword_init: true)
|
14
17
|
LocalVariableItem = _ = Struct.new(:identifier, :range, :type, keyword_init: true)
|
15
18
|
ConstantItem = _ = Struct.new(:env, :identifier, :range, :type, :full_name, keyword_init: true) do
|
16
19
|
# @implements ConstantItem
|
@@ -267,7 +270,9 @@ module Steep
|
|
267
270
|
[]
|
268
271
|
end
|
269
272
|
else
|
270
|
-
[]
|
273
|
+
items = [] #: Array[item]
|
274
|
+
items_for_following_keyword_arguments(source_text, index: index, line: line, column: column, items: items)
|
275
|
+
items
|
271
276
|
end
|
272
277
|
end
|
273
278
|
end
|
@@ -302,10 +307,10 @@ module Steep
|
|
302
307
|
end
|
303
308
|
|
304
309
|
def items_for_trigger(position:)
|
305
|
-
node, *
|
310
|
+
node, *parents = source.find_nodes(line: position.line, column: position.column)
|
306
311
|
node ||= source.node
|
307
312
|
|
308
|
-
return [] unless node
|
313
|
+
return [] unless node && parents
|
309
314
|
|
310
315
|
items = [] #: Array[item]
|
311
316
|
|
@@ -319,6 +324,16 @@ module Steep
|
|
319
324
|
method_items_for_receiver_type(context.self_type, include_private: true, prefix: prefix, position: position, items: items)
|
320
325
|
local_variable_items_for_context(context, position: position, prefix: prefix, items: items)
|
321
326
|
|
327
|
+
if (send_node, block_node = deconstruct_sendish_and_block_nodes(*parents))
|
328
|
+
keyword_argument_items_for_method(
|
329
|
+
call_node: block_node || send_node,
|
330
|
+
send_node: send_node,
|
331
|
+
position: position,
|
332
|
+
prefix: prefix,
|
333
|
+
items: items
|
334
|
+
)
|
335
|
+
end
|
336
|
+
|
322
337
|
when node.type == :lvar && at_end?(position, of: node.loc)
|
323
338
|
# foo ← (lvar)
|
324
339
|
local_variable_items_for_context(context, position: position, prefix: node.children[0].to_s, items: items)
|
@@ -527,6 +542,37 @@ module Steep
|
|
527
542
|
items
|
528
543
|
end
|
529
544
|
|
545
|
+
def items_for_following_keyword_arguments(text, index:, line:, column:, items:)
|
546
|
+
return if text[index - 1] !~ /[a-zA-Z0-9]/
|
547
|
+
|
548
|
+
text = text.dup
|
549
|
+
argname = [] #: Array[String]
|
550
|
+
while text[index - 1] =~ /[a-zA-Z0-9]/
|
551
|
+
argname.unshift(text[index - 1] || '')
|
552
|
+
source_text[index - 1] = " "
|
553
|
+
index -= 1
|
554
|
+
end
|
555
|
+
|
556
|
+
begin
|
557
|
+
type_check!(source_text, line: line, column: column)
|
558
|
+
rescue Parser::SyntaxError
|
559
|
+
return
|
560
|
+
end
|
561
|
+
|
562
|
+
if nodes = source.find_nodes(line: line, column: column)
|
563
|
+
if (send_node, block_node = deconstruct_sendish_and_block_nodes(*nodes))
|
564
|
+
position = Position.new(line: line, column: column)
|
565
|
+
keyword_argument_items_for_method(
|
566
|
+
call_node: block_node || send_node,
|
567
|
+
send_node: send_node,
|
568
|
+
position: position,
|
569
|
+
prefix: argname.join,
|
570
|
+
items: items
|
571
|
+
)
|
572
|
+
end
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
530
576
|
def method_items_for_receiver_type(type, include_private:, prefix:, position:, items:)
|
531
577
|
range = range_for(position, prefix: prefix)
|
532
578
|
context = typing.context_at(line: position.line, column: position.column)
|
@@ -641,6 +687,42 @@ module Steep
|
|
641
687
|
end
|
642
688
|
end
|
643
689
|
|
690
|
+
def keyword_argument_items_for_method(call_node:, send_node:, position:, prefix:, items:)
|
691
|
+
receiver_node, method_name, argument_nodes = deconstruct_send_node!(send_node)
|
692
|
+
|
693
|
+
call = typing.call_of(node: call_node)
|
694
|
+
|
695
|
+
case call
|
696
|
+
when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
|
697
|
+
type = call.receiver_type
|
698
|
+
shape = subtyping.builder.shape(
|
699
|
+
type,
|
700
|
+
public_only: !!receiver_node,
|
701
|
+
config: Interface::Builder::Config.new(self_type: type, class_type: nil, instance_type: nil, variable_bounds: {})
|
702
|
+
)
|
703
|
+
if shape
|
704
|
+
if method = shape.methods[call.method_name]
|
705
|
+
method.method_types.each.with_index do |method_type, i|
|
706
|
+
defn = method_type.method_decls.to_a[0]&.method_def
|
707
|
+
if defn
|
708
|
+
range = range_for(position, prefix: prefix)
|
709
|
+
kwargs = argument_nodes.find { |arg| arg.type == :kwargs }&.children || []
|
710
|
+
used_kwargs = kwargs.filter_map { |arg| arg.type == :pair && arg.children.first.children.first }
|
711
|
+
|
712
|
+
kwargs = defn.type.type.required_keywords.keys + defn.type.type.optional_keywords.keys
|
713
|
+
kwargs.each do |name|
|
714
|
+
if name.to_s.start_with?(prefix) && !used_kwargs.include?(name)
|
715
|
+
items << KeywordArgumentItem.new(identifier: "#{name}:", range: range)
|
716
|
+
end
|
717
|
+
end
|
718
|
+
end
|
719
|
+
end
|
720
|
+
end
|
721
|
+
end
|
722
|
+
end
|
723
|
+
end
|
724
|
+
|
725
|
+
|
644
726
|
def index_for(string, line:, column:)
|
645
727
|
index = 0
|
646
728
|
|
@@ -110,7 +110,7 @@ module Steep
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def content_for(target:, path:, line:, column:)
|
113
|
-
file = service.source_files[path]
|
113
|
+
file = service.source_files[path] or return
|
114
114
|
typing = typecheck(target, path: path, content: file.content, line: line, column: column) or return
|
115
115
|
node, *parents = typing.source.find_nodes(line: line, column: column)
|
116
116
|
|