steep 1.2.1 → 1.3.0.pre.2

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