steep 1.2.1 → 1.3.0.pre.2

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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/Gemfile.lock +4 -4
  4. data/Gemfile.steep +1 -1
  5. data/Gemfile.steep.lock +13 -3
  6. data/Steepfile +0 -1
  7. data/bin/steep-prof +1 -1
  8. data/lib/steep/annotation_parser.rb +34 -28
  9. data/lib/steep/ast/annotation.rb +16 -5
  10. data/lib/steep/ast/node/type_application.rb +74 -0
  11. data/lib/steep/ast/node/type_assertion.rb +56 -0
  12. data/lib/steep/ast/types/factory.rb +5 -1
  13. data/lib/steep/ast/types/helper.rb +4 -3
  14. data/lib/steep/ast/types/logic.rb +4 -0
  15. data/lib/steep/diagnostic/helper.rb +2 -1
  16. data/lib/steep/diagnostic/lsp_formatter.rb +3 -1
  17. data/lib/steep/diagnostic/ruby.rb +70 -5
  18. data/lib/steep/diagnostic/signature.rb +21 -8
  19. data/lib/steep/drivers/check.rb +2 -2
  20. data/lib/steep/drivers/checkfile.rb +2 -2
  21. data/lib/steep/drivers/langserver.rb +2 -2
  22. data/lib/steep/drivers/stats.rb +2 -2
  23. data/lib/steep/drivers/utils/jobs_option.rb +0 -4
  24. data/lib/steep/drivers/watch.rb +1 -1
  25. data/lib/steep/drivers/worker.rb +0 -1
  26. data/lib/steep/server/lsp_formatter.rb +13 -3
  27. data/lib/steep/server/master.rb +4 -1
  28. data/lib/steep/server/worker_process.rb +91 -14
  29. data/lib/steep/services/completion_provider.rb +2 -1
  30. data/lib/steep/services/goto_service.rb +2 -1
  31. data/lib/steep/services/hover_provider/rbs.rb +7 -7
  32. data/lib/steep/services/hover_provider/ruby.rb +21 -5
  33. data/lib/steep/services/signature_service.rb +23 -4
  34. data/lib/steep/services/type_check_service.rb +4 -4
  35. data/lib/steep/signature/validator.rb +36 -13
  36. data/lib/steep/source.rb +189 -71
  37. data/lib/steep/type_construction.rb +246 -135
  38. data/lib/steep/type_inference/logic_type_interpreter.rb +3 -1
  39. data/lib/steep/version.rb +1 -1
  40. data/lib/steep.rb +2 -0
  41. data/rbs_collection.steep.lock.yaml +27 -10
  42. data/rbs_collection.steep.yaml +0 -1
  43. data/sig/shims/exception.rbs +4 -0
  44. data/sig/shims/parser/comment.rbs +33 -0
  45. data/sig/shims/parser.rbs +30 -2
  46. data/sig/steep/annotation_parser.rbs +59 -0
  47. data/sig/steep/ast/annotation.rbs +21 -26
  48. data/sig/steep/ast/node/type_application.rbs +31 -0
  49. data/sig/steep/ast/node/type_assertion.rbs +26 -0
  50. data/sig/steep/ast/types/any.rbs +1 -1
  51. data/sig/steep/ast/types/boolean.rbs +1 -1
  52. data/sig/steep/ast/types/bot.rbs +1 -1
  53. data/sig/steep/ast/types/class.rbs +1 -1
  54. data/sig/steep/ast/types/factory.rbs +0 -2
  55. data/sig/steep/ast/types/helper.rbs +6 -3
  56. data/sig/steep/ast/types/instance.rbs +1 -1
  57. data/sig/steep/ast/types/intersection.rbs +1 -1
  58. data/sig/steep/ast/types/logic.rbs +2 -0
  59. data/sig/steep/ast/types/name.rbs +2 -2
  60. data/sig/steep/ast/types/nil.rbs +1 -1
  61. data/sig/steep/ast/types/record.rbs +1 -1
  62. data/sig/steep/ast/types/self.rbs +1 -1
  63. data/sig/steep/ast/types/top.rbs +2 -2
  64. data/sig/steep/ast/types/tuple.rbs +1 -1
  65. data/sig/steep/ast/types/union.rbs +1 -1
  66. data/sig/steep/ast/types/var.rbs +2 -2
  67. data/sig/steep/ast/types/void.rbs +1 -1
  68. data/sig/steep/diagnostic/helper.rbs +9 -3
  69. data/sig/steep/diagnostic/lsp_formatter.rbs +12 -8
  70. data/sig/steep/diagnostic/ruby.rbs +62 -8
  71. data/sig/steep/diagnostic/signature.rbs +118 -85
  72. data/sig/steep/drivers/utils/jobs_option.rbs +0 -2
  73. data/sig/steep/drivers/worker.rbs +11 -13
  74. data/sig/steep/range_extension.rbs +7 -0
  75. data/sig/steep/server/lsp_formatter.rbs +14 -7
  76. data/sig/steep/server/worker_process.rbs +74 -12
  77. data/sig/steep/services/hover_provider/rbs.rbs +27 -7
  78. data/sig/steep/services/hover_provider/ruby.rbs +18 -4
  79. data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
  80. data/sig/steep/services/signature_service.rbs +14 -0
  81. data/sig/steep/services/type_check_service.rbs +2 -2
  82. data/sig/steep/signature/validator.rbs +76 -0
  83. data/sig/steep/source.rbs +54 -30
  84. data/sig/steep/type_construction.rbs +85 -27
  85. data/sig/steep/type_inference/method_call.rbs +1 -1
  86. data/sig/steep.rbs +2 -0
  87. data/smoke/diagnostics-rbs/inherit-module.rbs +2 -0
  88. data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
  89. data/steep.gemspec +1 -1
  90. metadata +16 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 350eb85d965ebe0f830b76a4866e2380fbc03d19bdafb5c683e5cf426fff35f4
4
- data.tar.gz: 6be02c8f8628ea4a4c3f701fb4066d678a0237c3079245e2738380a41975dff0
3
+ metadata.gz: 639a97319d661c777702365209eaf5a6ea2632723a509331a03f6f1ef3926148
4
+ data.tar.gz: fb6061b52a09fb97c907abff4f69d6c9267eef1c9a3af52fa87fffda9de5d1f0
5
5
  SHA512:
6
- metadata.gz: 8d18a11bf1ee0e927651727dde99a9db70e99669c91b37e361b0c4cf1dff6d0b4aab914a63480a4db8477fe49694ab4ba74e99aad4b27f6df64e664ec3d53ca2
7
- data.tar.gz: 0cf526b1068660ffc759b41f1f197bf85b4f1590619bd2198b6f5fb5e770d26a2c617d53d00aa475cdacfd154eab1fcc1de5ff394da4ef804873b29f5fd9794a
6
+ metadata.gz: 232ec5b779c018aa9824318e003cd60e3ec3691297903337bb414fff87e757daaacfda2d94fb0c751538dcad194763ad6cb5b072156686bd450d5292d490a2e6
7
+ data.tar.gz: b322f5568a1fe5cbc0693a01a7be50d9860e056a9f69325e6c55a9322f2d32f7d1d0889d19e45576ca6f3f9afde9649747d9d02a0e251702f94cd27bf5fae27c
data/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.3.0.pre.2 (2022-11-23)
6
+
7
+ ### Type checker core
8
+
9
+ * Add missing `#level` method ([\#671](https://github.com/soutaro/steep/pull/671))
10
+ * Cache `constant_resolver` among files in a target([\#673](https://github.com/soutaro/steep/pull/673))
11
+ * Early return from type checking overloads ([\#674](https://github.com/soutaro/steep/pull/674))
12
+
13
+ ### Commandline tool
14
+
15
+ * Spawn worker processes if `--steep-command` is specified ([\#672](https://github.com/soutaro/steep/pull/672))
16
+
17
+ ## 1.3.0.pre.1 (2022-11-22)
18
+
19
+ ### Type checker core
20
+
21
+ * Add type assertion syntax ([#665](https://github.com/soutaro/steep/pull/665))
22
+ * Add type application syntax ([#670](https://github.com/soutaro/steep/pull/670))
23
+
24
+ ### Commandline tool
25
+
26
+ * Fork when available for quicker startup ([#664](https://github.com/soutaro/steep/pull/664))
27
+
28
+ ### Miscellaneous
29
+
30
+ * Fixes for some RBS errors within steep gem ([#668](https://github.com/soutaro/steep/pull/668))
31
+ * Upgrade to RBS 2.8 (pre) ([#669](https://github.com/soutaro/steep/pull/669))
32
+
5
33
  ## 1.2.1 (2022-10-22)
6
34
 
7
35
  ### Type checker core
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- steep (1.2.1)
4
+ steep (1.3.0.pre.2)
5
5
  activesupport (>= 5.1)
6
6
  csv (>= 3.0.9)
7
7
  fileutils (>= 1.1.0)
@@ -12,7 +12,7 @@ PATH
12
12
  parallel (>= 1.0.0)
13
13
  parser (>= 3.1)
14
14
  rainbow (>= 2.2.2, < 4.0)
15
- rbs (>= 2.7.0)
15
+ rbs (>= 2.8.0.pre)
16
16
  securerandom (>= 0.1)
17
17
  strscan (>= 1.0.0)
18
18
  terminal-table (>= 2, < 4)
@@ -54,11 +54,11 @@ GEM
54
54
  rb-fsevent (0.11.2)
55
55
  rb-inotify (0.10.1)
56
56
  ffi (~> 1.0)
57
- rbs (2.7.0)
57
+ rbs (2.8.0.pre.1)
58
58
  ruby-debug-ide (0.7.3)
59
59
  rake (>= 0.8.1)
60
60
  securerandom (0.2.0)
61
- stackprof (0.2.21)
61
+ stackprof (0.2.22)
62
62
  strscan (3.0.4)
63
63
  terminal-table (3.0.2)
64
64
  unicode-display_width (>= 1.1.1, < 3)
data/Gemfile.steep CHANGED
@@ -1,4 +1,4 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem 'steep', '~> 1.2.0'
4
- gem "rbs"
4
+ gem "rbs", '~> 2.8.0.pre'
data/Gemfile.steep.lock CHANGED
@@ -8,13 +8,17 @@ GEM
8
8
  tzinfo (~> 2.0)
9
9
  ast (2.4.2)
10
10
  concurrent-ruby (1.1.10)
11
+ csv (3.2.5)
11
12
  ffi (1.15.5)
13
+ fileutils (1.6.0)
12
14
  i18n (1.12.0)
13
15
  concurrent-ruby (~> 1.0)
16
+ json (2.6.2)
14
17
  language_server-protocol (3.17.0.1)
15
18
  listen (3.7.1)
16
19
  rb-fsevent (~> 0.10, >= 0.10.3)
17
20
  rb-inotify (~> 0.9, >= 0.9.10)
21
+ logger (1.5.1)
18
22
  minitest (5.16.3)
19
23
  parallel (1.22.1)
20
24
  parser (3.1.2.1)
@@ -23,18 +27,24 @@ GEM
23
27
  rb-fsevent (0.11.2)
24
28
  rb-inotify (0.10.1)
25
29
  ffi (~> 1.0)
26
- rbs (2.7.0)
30
+ rbs (2.8.0.pre.1)
27
31
  securerandom (0.2.0)
28
- steep (1.2.0)
32
+ steep (1.2.1)
29
33
  activesupport (>= 5.1)
34
+ csv (>= 3.0.9)
35
+ fileutils (>= 1.1.0)
36
+ json (>= 2.1.0)
30
37
  language_server-protocol (>= 3.15, < 4.0)
31
38
  listen (~> 3.0)
39
+ logger (>= 1.3.0)
32
40
  parallel (>= 1.0.0)
33
41
  parser (>= 3.1)
34
42
  rainbow (>= 2.2.2, < 4.0)
35
43
  rbs (>= 2.7.0)
36
44
  securerandom (>= 0.1)
45
+ strscan (>= 1.0.0)
37
46
  terminal-table (>= 2, < 4)
47
+ strscan (3.0.4)
38
48
  terminal-table (3.0.2)
39
49
  unicode-display_width (>= 1.1.1, < 3)
40
50
  tzinfo (2.0.5)
@@ -45,7 +55,7 @@ PLATFORMS
45
55
  arm64-darwin-21
46
56
 
47
57
  DEPENDENCIES
48
- rbs
58
+ rbs (~> 2.8.0.pre)
49
59
  steep (~> 1.2.0)
50
60
 
51
61
  BUNDLED WITH
data/Steepfile CHANGED
@@ -10,7 +10,6 @@ target :app do
10
10
  hash[D::Ruby::MethodDefinitionMissing] = :hint
11
11
  end
12
12
 
13
- signature "../rbs/sig", "../rbs/stdlib/rdoc/0"
14
13
  library(
15
14
  "set",
16
15
  "pathname",
data/bin/steep-prof CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "stackprof"
4
4
 
5
- mode = (ENV["STEEP_STACKPROF_MODE"] || :wall).to_sym
5
+ mode = (ENV["STEEP_STACKPROF_MODE"] || :cpu).to_sym
6
6
  out = ENV["STEEP_STACKPROF_OUT"] || "tmp/stackprof-#{mode}-steep.dump"
7
7
  interval = ENV["STEEP_STACKPROF_INTERVAL"]&.to_i || 1000
8
8
 
@@ -27,7 +27,7 @@ module Steep
27
27
  message = case exn
28
28
  when RBS::ParsingError
29
29
  Diagnostic::Signature::SyntaxError.parser_syntax_error_message(exn)
30
- else
30
+ when Exception
31
31
  exn.message
32
32
  end
33
33
 
@@ -45,16 +45,10 @@ module Steep
45
45
  factory.type(RBS::Parser.parse_type(string))
46
46
  end
47
47
 
48
- # @type ${keyword} ${name}: ${type}
49
- # Example: @type const Foo::Bar: String
50
- # @type var xyzzy: Array[String]
51
48
  def keyword_subject_type(keyword, name)
52
49
  /@type\s+#{keyword}\s+(?<name>#{name})#{COLON}#{TYPE}/
53
50
  end
54
51
 
55
- # @type ${keyword}: ${type}
56
- # Example: @type break: String
57
- # @type self: Foo
58
52
  def keyword_and_type(keyword)
59
53
  /@type\s+#{keyword}#{COLON}#{TYPE}/
60
54
  end
@@ -63,8 +57,9 @@ module Steep
63
57
  case src
64
58
  when keyword_subject_type("var", VAR_NAME)
65
59
  Regexp.last_match.yield_self do |match|
66
- name = match[:name]
67
- type = match[:type]
60
+ match or raise
61
+ name = match[:name] or raise
62
+ type = match[:type] or raise
68
63
 
69
64
  AST::Annotation::VarType.new(name: name.to_sym,
70
65
  type: parse_type(type),
@@ -73,8 +68,9 @@ module Steep
73
68
 
74
69
  when keyword_subject_type("method", METHOD_NAME)
75
70
  Regexp.last_match.yield_self do |match|
76
- name = match[:name]
77
- type = match[:type]
71
+ match or raise
72
+ name = match[:name] or raise
73
+ type = match[:type] or raise
78
74
 
79
75
  method_type = factory.method_type(RBS::Parser.parse_method_type(type), method_decls: Set[])
80
76
 
@@ -85,16 +81,18 @@ module Steep
85
81
 
86
82
  when keyword_subject_type("const", CONST_NAME)
87
83
  Regexp.last_match.yield_self do |match|
88
- name = match[:name]
89
- type = parse_type(match[:type])
84
+ match or raise
85
+ name = match[:name] or raise
86
+ type = parse_type(match[:type] || raise)
90
87
 
91
88
  AST::Annotation::ConstType.new(name: TypeName(name), type: type, location: location)
92
89
  end
93
90
 
94
91
  when keyword_subject_type("ivar", IVAR_NAME)
95
92
  Regexp.last_match.yield_self do |match|
96
- name = match[:name]
97
- type = parse_type(match[:type])
93
+ match or raise
94
+ name = match[:name] or raise
95
+ type = parse_type(match[:type] || raise)
98
96
 
99
97
  AST::Annotation::IvarType.new(name: name.to_sym,
100
98
  type: type,
@@ -103,51 +101,58 @@ module Steep
103
101
 
104
102
  when keyword_and_type("return")
105
103
  Regexp.last_match.yield_self do |match|
106
- type = parse_type(match[:type])
104
+ match or raise
105
+ type = parse_type(match[:type] || raise)
107
106
  AST::Annotation::ReturnType.new(type: type, location: location)
108
107
  end
109
108
 
110
109
  when keyword_and_type("block")
111
110
  Regexp.last_match.yield_self do |match|
112
- type = parse_type(match[:type])
111
+ match or raise
112
+ type = parse_type(match[:type] || raise)
113
113
  AST::Annotation::BlockType.new(type: type, location: location)
114
114
  end
115
115
 
116
116
  when keyword_and_type("self")
117
117
  Regexp.last_match.yield_self do |match|
118
- type = parse_type(match[:type])
118
+ match or raise
119
+ type = parse_type(match[:type] || raise)
119
120
  AST::Annotation::SelfType.new(type: type, location: location)
120
121
  end
121
122
 
122
123
  when keyword_and_type("instance")
123
124
  Regexp.last_match.yield_self do |match|
124
- type = parse_type(match[:type])
125
+ match or raise
126
+ type = parse_type(match[:type] || raise)
125
127
  AST::Annotation::InstanceType.new(type: type, location: location)
126
128
  end
127
129
 
128
130
  when keyword_and_type("module")
129
131
  Regexp.last_match.yield_self do |match|
130
- type = parse_type(match[:type])
132
+ match or raise
133
+ type = parse_type(match[:type] || raise)
131
134
  AST::Annotation::ModuleType.new(type: type, location: location)
132
135
  end
133
136
 
134
137
  when keyword_and_type("break")
135
138
  Regexp.last_match.yield_self do |match|
136
- type = parse_type(match[:type])
139
+ match or raise
140
+ type = parse_type(match[:type] || raise)
137
141
  AST::Annotation::BreakType.new(type: type, location: location)
138
142
  end
139
143
 
140
144
  when /@dynamic\s+(?<names>(#{DYNAMIC_NAME}\s*,\s*)*#{DYNAMIC_NAME})/
141
145
  Regexp.last_match.yield_self do |match|
142
- names = match[:names].split(/\s*,\s*/)
146
+ match or raise
147
+ names = (match[:names] || raise).split(/\s*,\s*/)
143
148
 
144
149
  AST::Annotation::Dynamic.new(
145
150
  names: names.map {|name|
146
- case name
147
- when /^self\./
148
- AST::Annotation::Dynamic::Name.new(name: name[5..].to_sym, kind: :module)
149
- when /^self\?\./
150
- AST::Annotation::Dynamic::Name.new(name: name[6..].to_sym, kind: :module_instance)
151
+ case
152
+ when name.delete_prefix!("self.")
153
+ AST::Annotation::Dynamic::Name.new(name: name.to_sym, kind: :module)
154
+ when name.delete_prefix!("self?.")
155
+ AST::Annotation::Dynamic::Name.new(name: name.to_sym, kind: :module_instance)
151
156
  else
152
157
  AST::Annotation::Dynamic::Name.new(name: name.to_sym, kind: :instance)
153
158
  end
@@ -158,7 +163,8 @@ module Steep
158
163
 
159
164
  when /@implements\s+(?<name>#{CONST_NAME})#{TYPE_PARAMS}$/
160
165
  Regexp.last_match.yield_self do |match|
161
- type_name = TypeName(match[:name])
166
+ match or raise
167
+ type_name = TypeName(match[:name] || raise)
162
168
  params = match[:params]&.yield_self {|params| params.split(/,/).map {|param| param.strip.to_sym } } || []
163
169
 
164
170
  name = AST::Annotation::Implements::Module.new(name: type_name, args: params)
@@ -1,10 +1,19 @@
1
1
  module Steep
2
2
  module AST
3
3
  module Annotation
4
+ module Located
5
+ attr_reader :location
6
+
7
+ def line
8
+ location&.start_line
9
+ end
10
+ end
11
+
4
12
  class Named
13
+ include Located
14
+
5
15
  attr_reader :name
6
16
  attr_reader :type
7
- attr_reader :location
8
17
 
9
18
  def initialize(name:, type:, location: nil)
10
19
  @name = name
@@ -20,9 +29,9 @@ module Steep
20
29
  end
21
30
 
22
31
  class Typed
32
+ include Located
33
+
23
34
  attr_reader :type
24
- attr_reader :annotation
25
- attr_reader :location
26
35
 
27
36
  def initialize(type:, location: nil)
28
37
  @type = type
@@ -68,7 +77,8 @@ module Steep
68
77
  end
69
78
  end
70
79
 
71
- attr_reader :location
80
+ include Located
81
+
72
82
  attr_reader :name
73
83
 
74
84
  def initialize(name:, location: nil)
@@ -108,7 +118,8 @@ module Steep
108
118
  end
109
119
  end
110
120
 
111
- attr_reader :location
121
+ include Located
122
+
112
123
  attr_reader :names
113
124
 
114
125
  def initialize(names:, location: nil)
@@ -0,0 +1,74 @@
1
+ module Steep
2
+ module AST
3
+ module Node
4
+ class TypeApplication
5
+ attr_reader :location
6
+
7
+ def initialize(location)
8
+ @location = location
9
+ end
10
+
11
+ def node
12
+ @node || raise
13
+ end
14
+
15
+ def set_node(node)
16
+ @node = node
17
+ end
18
+
19
+ def line
20
+ location.start_line
21
+ end
22
+
23
+ def source
24
+ location.source
25
+ end
26
+
27
+ def types(context, factory, type_vars)
28
+ # @type var types: Array[Types::t]
29
+ types = []
30
+
31
+ loc = type_location
32
+
33
+ while true
34
+ ty = RBS::Parser.parse_type(loc.buffer, range: loc.range, variables: type_vars) or break
35
+ ty = factory.type(ty)
36
+ types << factory.absolute_type(ty, context: context)
37
+
38
+ match = RBS::Location.new(loc.buffer, ty.location.end_pos, type_location.end_pos).source.match(/\A\s*,\s*/) or break
39
+ offset = match.length
40
+ loc = RBS::Location.new(loc.buffer, ty.location.end_pos + offset, type_location.end_pos)
41
+ end
42
+
43
+ types
44
+ rescue ::RBS::ParsingError => exn
45
+ exn
46
+ end
47
+
48
+ def types?(context, factory, type_vars)
49
+ case types = types(context, factory, type_vars)
50
+ when RBS::ParsingError
51
+ nil
52
+ else
53
+ types
54
+ end
55
+ end
56
+
57
+ def type_str
58
+ @type_str ||= source.delete_prefix("$").lstrip
59
+ end
60
+
61
+ def type_location
62
+ offset = source.size - type_str.size
63
+ RBS::Location.new(location.buffer, location.start_pos + offset, location.end_pos)
64
+ end
65
+
66
+ def self.parse(location)
67
+ if location.source =~/\A\$\s*(.+)/
68
+ TypeApplication.new(location)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,56 @@
1
+ module Steep
2
+ module AST
3
+ module Node
4
+ class TypeAssertion
5
+ attr_reader :location
6
+
7
+ def initialize(location)
8
+ @location = location
9
+ end
10
+
11
+ def source
12
+ location.source
13
+ end
14
+
15
+ def line
16
+ location.start_line
17
+ end
18
+
19
+ def type(context, factory, type_vars)
20
+ if ty = RBS::Parser.parse_type(type_location.buffer, range: type_location.range, variables: type_vars)
21
+ ty = factory.type(ty)
22
+ factory.absolute_type(ty, context: context)
23
+ else
24
+ nil
25
+ end
26
+ rescue ::RBS::ParsingError => exn
27
+ exn
28
+ end
29
+
30
+ def type?(context, factory, type_vars)
31
+ case type = type(context, factory, type_vars)
32
+ when RBS::ParsingError
33
+ nil
34
+ else
35
+ type
36
+ end
37
+ end
38
+
39
+ def type_str
40
+ @type_str ||= source.delete_prefix(":").lstrip
41
+ end
42
+
43
+ def type_location
44
+ offset = source.size - type_str.size
45
+ RBS::Location.new(location.buffer, location.start_pos + offset, location.end_pos)
46
+ end
47
+
48
+ def self.parse(location)
49
+ if location.source =~/\A:\s*(.+)/
50
+ TypeAssertion.new(location)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -37,7 +37,11 @@ module Steep
37
37
  end
38
38
 
39
39
  def type(type)
40
- ty = type_cache[type] and return ty
40
+ unless type.location
41
+ if ty = type_cache[type]
42
+ return ty
43
+ end
44
+ end
41
45
 
42
46
  type_cache[type] =
43
47
  case type
@@ -4,12 +4,13 @@ module Steep
4
4
  module Helper
5
5
  module ChildrenLevel
6
6
  def level_of_children(children)
7
- children.map(&:level).sort {|a, b| b.size <=> a.size }.inject() do |a, b|
8
- a.zip(b).map do |(x, y)|
7
+ levels = children.map(&:level)
8
+ children.map(&:level).sort {|a, b| (b.size <=> a.size) || 0 }.inject() do |a, b|
9
+ a.zip(b).map do |x, y|
9
10
  if x && y
10
11
  x + y
11
12
  else
12
- x || y
13
+ x || y || raise
13
14
  end
14
15
  end
15
16
  end || []
@@ -28,6 +28,10 @@ module Steep
28
28
  def to_s
29
29
  "<% #{self.class} %>"
30
30
  end
31
+
32
+ def level
33
+ [0]
34
+ end
31
35
  end
32
36
 
33
37
  class Not < Base
@@ -2,7 +2,8 @@ module Steep
2
2
  module Diagnostic
3
3
  module Helper
4
4
  def error_name
5
- self.class.name.split(/::/).last
5
+ name = self.class.name or raise
6
+ name.split(/::/).last or raise
6
7
  end
7
8
 
8
9
  def full_message
@@ -41,11 +41,13 @@ module Steep
41
41
  severity = severity_for(diagnostic)
42
42
 
43
43
  if severity
44
+ range = diagnostic.location&.as_lsp_range or raise
45
+
44
46
  LSP::Interface::Diagnostic.new(
45
47
  message: diagnostic.full_message,
46
48
  code: diagnostic.diagnostic_code,
47
49
  severity: severity,
48
- range: diagnostic.location.as_lsp_range
50
+ range: range
49
51
  ).to_hash
50
52
  end
51
53
  end
@@ -773,6 +773,65 @@ module Steep
773
773
  end
774
774
  end
775
775
 
776
+ class FalseAssertion < Base
777
+ attr_reader :node, :assertion_type, :node_type
778
+
779
+ def initialize(node:, assertion_type:, node_type:)
780
+ super(node: node)
781
+ @assertion_type = assertion_type
782
+ @node_type = node_type
783
+ end
784
+
785
+ def header_line
786
+ "Assertion cannot hold: no relationship between infered type (`#{node_type.to_s}`) and asserted type (`#{assertion_type.to_s}`)"
787
+ end
788
+ end
789
+
790
+ class UnexpectedTypeArgument < Base
791
+ attr_reader :type_arg, :method_type
792
+
793
+ def initialize(type_arg:, method_type:)
794
+ super(node: nil, location: type_arg.location)
795
+ @type_arg = type_arg
796
+ @method_type = method_type
797
+ end
798
+
799
+ def header_line
800
+ "Unexpected type arg is given to method type `#{method_type.to_s}`"
801
+ end
802
+ end
803
+
804
+ class InsufficientTypeArgument < Base
805
+ attr_reader :type_args, :method_type
806
+
807
+ def initialize(node:, type_args:, method_type:)
808
+ super(node: node)
809
+ @type_args = type_args
810
+ @method_type = method_type
811
+ end
812
+
813
+ def header_line
814
+ "Requires #{method_type.type_params.size} types, but #{type_args.size} given: `#{method_type.to_s}`"
815
+ end
816
+ end
817
+
818
+ class TypeArgumentMismatchError < Base
819
+ attr_reader :type_argument, :type_parameter, :result
820
+
821
+ def initialize(type_arg:, type_param:, result:)
822
+ super(node: nil, location: type_arg.location)
823
+ @type_argument = type_arg
824
+ @type_parameter = type_param
825
+ @result = result
826
+ end
827
+
828
+ include ResultPrinter
829
+
830
+ def header_line
831
+ "Cannot pass a type `#{type_argument}` as a type parameter `#{type_parameter.to_s}`"
832
+ end
833
+ end
834
+
776
835
  ALL = ObjectSpace.each_object(Class).with_object([]) do |klass, array|
777
836
  if klass < Base
778
837
  array << klass
@@ -781,24 +840,29 @@ module Steep
781
840
 
782
841
  def self.all_error
783
842
  @all_error ||= ALL.each.with_object({}) do |klass, hash|
843
+ # @type var hash: Hash[singleton(Base), LSPFormatter::severity]
784
844
  hash[klass] = LSPFormatter::ERROR
785
845
  end.freeze
786
846
  end
787
847
 
788
848
  def self.default
789
- @default ||= all_error.merge(
849
+ @default ||= _ = all_error.merge(
790
850
  {
791
851
  ImplicitBreakValueMismatch => :warning,
792
852
  FallbackAny => :information,
793
853
  ElseOnExhaustiveCase => :warning,
794
854
  UnknownConstant => :warning,
795
- MethodDefinitionMissing => :information
855
+ MethodDefinitionMissing => :information,
856
+ FalseAssertion => :information,
857
+ UnexpectedTypeArgument => :information,
858
+ InsufficientTypeArgument => :information,
859
+ UnexpectedTypeArgument => :information
796
860
  }
797
861
  ).freeze
798
862
  end
799
863
 
800
864
  def self.strict
801
- @strict ||= all_error.merge(
865
+ @strict ||= _ = all_error.merge(
802
866
  {
803
867
  NoMethod => nil,
804
868
  ImplicitBreakValueMismatch => nil,
@@ -811,7 +875,7 @@ module Steep
811
875
  end
812
876
 
813
877
  def self.lenient
814
- @lenient ||= all_error.merge(
878
+ @lenient ||= _ = all_error.merge(
815
879
  {
816
880
  NoMethod => nil,
817
881
  ImplicitBreakValueMismatch => nil,
@@ -819,7 +883,8 @@ module Steep
819
883
  ElseOnExhaustiveCase => nil,
820
884
  UnknownConstant => nil,
821
885
  MethodDefinitionMissing => nil,
822
- UnexpectedJump => nil
886
+ UnexpectedJump => nil,
887
+ FalseAssertion => :hint
823
888
  }
824
889
  ).freeze
825
890
  end