steep 0.52.2 → 1.0.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-windows.yml +34 -0
  3. data/.github/workflows/ruby.yml +2 -2
  4. data/CHANGELOG.md +47 -0
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +8 -8
  7. data/lib/steep/ast/builtin.rb +2 -2
  8. data/lib/steep/ast/types/factory.rb +108 -5
  9. data/lib/steep/ast/types/proc.rb +2 -0
  10. data/lib/steep/cli.rb +3 -1
  11. data/lib/steep/diagnostic/ruby.rb +1 -1
  12. data/lib/steep/drivers/check.rb +3 -3
  13. data/lib/steep/path_helper.rb +22 -0
  14. data/lib/steep/project.rb +3 -15
  15. data/lib/steep/server/base_worker.rb +1 -0
  16. data/lib/steep/server/change_buffer.rb +1 -1
  17. data/lib/steep/server/interaction_worker.rb +3 -5
  18. data/lib/steep/server/lsp_formatter.rb +12 -0
  19. data/lib/steep/server/master.rb +61 -45
  20. data/lib/steep/server/type_check_worker.rb +10 -25
  21. data/lib/steep/services/completion_provider.rb +3 -3
  22. data/lib/steep/services/goto_service.rb +2 -4
  23. data/lib/steep/services/hover_provider/rbs.rb +1 -1
  24. data/lib/steep/services/stats_calculator.rb +0 -1
  25. data/lib/steep/services/type_check_service.rb +3 -0
  26. data/lib/steep/signature/validator.rb +6 -1
  27. data/lib/steep/source.rb +3 -3
  28. data/lib/steep/subtyping/check.rb +0 -3
  29. data/lib/steep/type_construction.rb +140 -29
  30. data/lib/steep/type_inference/logic_type_interpreter.rb +6 -4
  31. data/lib/steep/type_inference/method_call.rb +4 -1
  32. data/lib/steep/type_inference/method_params.rb +1 -0
  33. data/lib/steep/type_inference/send_args.rb +1 -2
  34. data/lib/steep/type_inference/type_env.rb +6 -0
  35. data/lib/steep/version.rb +1 -1
  36. data/lib/steep.rb +3 -2
  37. data/smoke/compact/Steepfile +6 -0
  38. data/smoke/compact/a.rb +2 -0
  39. data/smoke/compact/a.rbs +5 -0
  40. data/smoke/compact/b.rb +2 -0
  41. data/smoke/compact/test_expectations.yml +18 -0
  42. data/smoke/regression/lambda.rb +3 -0
  43. data/smoke/regression/test_expectations.yml +12 -0
  44. data/steep.gemspec +1 -1
  45. metadata +12 -5
  46. data/lib/steep/subtyping/variable_occurrence.rb +0 -51
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c9d5eb873780b31a2431d2e6c4efdc558fbb3a4a42c08cbe2580bb191db5bc8
4
- data.tar.gz: dee794e9cb098309b9875396ed1dc9904a4c6882aeadb27c83c26604ebcbc87d
3
+ metadata.gz: 8317c379e5b7e85cca4a22c9133248a77a112e7687c3cf553ddb90f96ab31236
4
+ data.tar.gz: cd9c06372e29c009b4af99a5f0c252dcdbdcc9d2905cbd601cffb7210f809c93
5
5
  SHA512:
6
- metadata.gz: ba05f88c28a78414ffcd41744558bdea978b72621f422571cb1450b7b0d56fb77c2b65329064226863db2517d4769a6f54e7c47ce92eef59d97f0403bb9e9425
7
- data.tar.gz: 6e260b48940214b7c0910bf2678c587b469e163e70265f197ef8fd17a1703a68fd9488c77c3d1f8254939c074281717593e49812875fb705615189cd3ec4cdf0
6
+ metadata.gz: 7b0cfaee1dac3cdc8a69d9ef50714615647c1049783d6406d6ee3246c11a5cb2b5e4287f42a896d13e9ed6411e092acf15406199a0f6f0e3bad412f0ae12e250
7
+ data.tar.gz: a8b8192a8e6217eff958d30ac12c9aa1cbf9608626c892c9ae9585e33c9241d5a75e760060271e15f60f9869ceab41e9ff2fab38920db9692aa4f1ec296d1257
@@ -0,0 +1,34 @@
1
+ name: Run test on Windows
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request: {}
8
+
9
+ jobs:
10
+ test:
11
+ strategy:
12
+ matrix:
13
+ ruby_version:
14
+ - "2.7"
15
+ - "3.0"
16
+ - "3.1"
17
+ task:
18
+ - test
19
+ # - test:output Ignored because the order of diagnostics changes somehow
20
+ - build
21
+ runs-on: windows-latest
22
+ steps:
23
+ - uses: actions/checkout@v3
24
+ - uses: ruby/setup-ruby@v1
25
+ with:
26
+ ruby-version: ${{ matrix.ruby_version }}
27
+ - name: Run test
28
+ run: |
29
+ git config --global --add safe.directory /__w/steep/steep
30
+ ruby -v
31
+ gem install bundler
32
+ bundle install --jobs 4 --retry 3
33
+ bin/setup
34
+ bundle exec rake ${{matrix.task}}
@@ -1,4 +1,4 @@
1
- name: Ruby
1
+ name: Run test on container
2
2
 
3
3
  on:
4
4
  push:
@@ -8,7 +8,6 @@ on:
8
8
 
9
9
  jobs:
10
10
  test:
11
- runs-on: "ubuntu-latest"
12
11
  strategy:
13
12
  matrix:
14
13
  container_tag:
@@ -20,6 +19,7 @@ jobs:
20
19
  - test
21
20
  - test:output
22
21
  - build
22
+ runs-on: ubuntu-latest
23
23
  container:
24
24
  image: rubylang/ruby:${{ matrix.container_tag }}
25
25
  steps:
data/CHANGELOG.md CHANGED
@@ -2,6 +2,53 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.0.2 (2022-07-19)
6
+
7
+ This is another patch release for Steep 1.0.
8
+
9
+ ### Type checker
10
+
11
+ * Fix type application validation ([#607](https://github.com/soutaro/steep/pull/607))
12
+
13
+ ## 1.0.1 (2022-06-16)
14
+
15
+ This is the first patch release for Steep 1.0.
16
+ However, this release includes one non-trivial type system update, [\#570](https://github.com/soutaro/steep/pull/570), which adds a special typing rule for `Hash#compact` like `Array#compact`.
17
+ The change will make type checking more permissive and precise, so no new error won't be reported with the fix.
18
+
19
+ ### Type checker
20
+
21
+ * Support shorthand hash for Ruby 3.1 ([\#567](https://github.com/soutaro/steep/pull/567))
22
+ * Fix super and zsuper with block ([\#568](https://github.com/soutaro/steep/pull/568))
23
+ * Apply logic-type evaluation only if the node is `:send` ([\#569](https://github.com/soutaro/steep/pull/569))
24
+ * Add support for `Hash#compact` ([\#570](https://github.com/soutaro/steep/pull/570))
25
+ * Use given `const_env` when making a new `ModuleContext` ([\#575](https://github.com/soutaro/steep/pull/575))
26
+ * Graceful, hopefully, error handling with undefined outer module ([\#576](https://github.com/soutaro/steep/pull/576))
27
+ * Type check anonymous block forwarding ([\#577](https://github.com/soutaro/steep/pull/577))
28
+ * Incompatible default value is a type error ([\#578](https://github.com/soutaro/steep/pull/578))
29
+ * Load `ChildrenLevel` helper in `AST::Types::Proc` ([\#584](https://github.com/soutaro/steep/pull/584))
30
+ * Type check `gvar` and `gvasgn` in methods([\#579](https://github.com/soutaro/steep/pull/579))
31
+ * Avoid `UnexpectedError` when assigning untyped singleton class ([\#586](https://github.com/soutaro/steep/pull/586))
32
+
33
+ ### Tool
34
+
35
+ * Improve Windows support ([\#561](https://github.com/soutaro/steep/pull/561), [\#573](https://github.com/soutaro/steep/pull/573))
36
+ * Test if `.ruby-version` exists before `rvm do` in binstub ([\#558](https://github.com/soutaro/steep/pull/558))
37
+ * Fix typo ([\#564](https://github.com/soutaro/steep/pull/564))
38
+ * Ignore `untitled:` URIs in LSP ([\#580](https://github.com/soutaro/steep/pull/580))
39
+
40
+ ### Miscellaneous
41
+
42
+ * Fix test name ([\#565](https://github.com/soutaro/steep/pull/565), [\#566](https://github.com/soutaro/steep/pull/566), [\#585](https://github.com/soutaro/steep/pull/585))
43
+ * Remove some unused code except tests ([\#587](https://github.com/soutaro/steep/pull/587))
44
+
45
+ ## 1.0.0 (2022-05-20)
46
+
47
+ * Add special typing rule for `Array#compact` ([\#555](https://github.com/soutaro/steep/pull/555))
48
+ * Add custom method type of `#fetch` on tuples and records ([\#554](https://github.com/soutaro/steep/pull/554))
49
+ * Better `masgn` ([\#553](https://github.com/soutaro/steep/pull/553))
50
+ * Fix method parameter type checking ([\#552](https://github.com/soutaro/steep/pull/552))
51
+
5
52
  ## 0.52.2 (2022-05-02)
6
53
 
7
54
  * Handle class declaration with non-const super class ([\#546](https://github.com/soutaro/steep/pull/546))
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ gem "with_steep_types", path: "test/gems/with_steep_types"
7
7
  gem "without_steep_types", path: "test/gems/without_steep_types"
8
8
 
9
9
  gem "rake"
10
- gem "minitest", "~> 5.15"
10
+ gem "minitest", "~> 5.16"
11
11
  gem "minitest-hooks"
12
12
  group :stackprof, optional: true do
13
13
  gem "stackprof"
data/Gemfile.lock CHANGED
@@ -1,12 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- steep (0.52.2)
4
+ steep (1.0.2)
5
5
  activesupport (>= 5.1)
6
6
  language_server-protocol (>= 3.15, < 4.0)
7
7
  listen (~> 3.0)
8
8
  parallel (>= 1.0.0)
9
- parser (>= 3.0)
9
+ parser (>= 3.1)
10
10
  rainbow (>= 2.2.2, < 4.0)
11
11
  rbs (>= 2.3.2)
12
12
  terminal-table (>= 2, < 4)
@@ -24,7 +24,7 @@ PATH
24
24
  GEM
25
25
  remote: https://rubygems.org/
26
26
  specs:
27
- activesupport (7.0.2.4)
27
+ activesupport (7.0.3.1)
28
28
  concurrent-ruby (~> 1.0, >= 1.0.2)
29
29
  i18n (>= 1.6, < 2)
30
30
  minitest (>= 5.1)
@@ -32,13 +32,13 @@ GEM
32
32
  ast (2.4.2)
33
33
  concurrent-ruby (1.1.10)
34
34
  ffi (1.15.5)
35
- i18n (1.10.0)
35
+ i18n (1.12.0)
36
36
  concurrent-ruby (~> 1.0)
37
37
  language_server-protocol (3.16.0.3)
38
38
  listen (3.7.1)
39
39
  rb-fsevent (~> 0.10, >= 0.10.3)
40
40
  rb-inotify (~> 0.9, >= 0.9.10)
41
- minitest (5.15.0)
41
+ minitest (5.16.1)
42
42
  minitest-hooks (1.5.0)
43
43
  minitest (> 5.3)
44
44
  minitest-slow_test (0.2.0)
@@ -51,19 +51,19 @@ GEM
51
51
  rb-fsevent (0.11.1)
52
52
  rb-inotify (0.10.1)
53
53
  ffi (~> 1.0)
54
- rbs (2.3.2)
54
+ rbs (2.6.0)
55
55
  stackprof (0.2.19)
56
56
  terminal-table (3.0.2)
57
57
  unicode-display_width (>= 1.1.1, < 3)
58
58
  tzinfo (2.0.4)
59
59
  concurrent-ruby (~> 1.0)
60
- unicode-display_width (2.1.0)
60
+ unicode-display_width (2.2.0)
61
61
 
62
62
  PLATFORMS
63
63
  ruby
64
64
 
65
65
  DEPENDENCIES
66
- minitest (~> 5.15)
66
+ minitest (~> 5.16)
67
67
  minitest-hooks
68
68
  minitest-slow_test
69
69
  rake
@@ -16,7 +16,7 @@ module Steep
16
16
  args << Builtin.any_type
17
17
  end
18
18
  end
19
- arity == args.size or raise "Mulformed instance type: name=#{module_name}, args=#{args}"
19
+ arity == args.size or raise "Malformed instance type: name=#{module_name}, args=#{args}"
20
20
 
21
21
  Types::Name::Instance.new(name: module_name, args: args)
22
22
  end
@@ -28,7 +28,7 @@ module Steep
28
28
  def instance_type?(type, args: nil)
29
29
  if type.is_a?(Types::Name::Instance)
30
30
  if args
31
- arity == args.size or raise "Mulformed instance type: name=#{module_name}, args=#{args}"
31
+ arity == args.size or raise "Malformed instance type: name=#{module_name}, args=#{args}"
32
32
  type.name == module_name && type.args == args
33
33
  else
34
34
  type.name == module_name && type.args.size == arity
@@ -9,6 +9,12 @@ module Steep
9
9
 
10
10
  attr_reader :type_interface_cache
11
11
 
12
+ def inspect
13
+ s = "#<%s:%#018x " % [self.class, object_id]
14
+ s << "@definition_builder=#<%s:%#018x>" % [definition_builder.class, definition_builder.object_id]
15
+ s + ">"
16
+ end
17
+
12
18
  def initialize(builder:)
13
19
  @definition_builder = builder
14
20
 
@@ -282,8 +288,6 @@ module Steep
282
288
  fvs = self_type.free_variables()
283
289
 
284
290
  type_params = []
285
- alpha_vars = []
286
- alpha_types = []
287
291
 
288
292
  conflicting_names = method_type.type_params.each.with_object([]) do |param, names|
289
293
  names << params.name if fvs.include?(param.name)
@@ -674,6 +678,57 @@ module Steep
674
678
  )
675
679
  end
676
680
 
681
+ array_interface.methods[:fetch] = array_interface.methods[:fetch].yield_self do |fetch|
682
+ Interface::Interface::Entry.new(
683
+ method_types: type.types.flat_map.with_index {|elem_type, index|
684
+ [
685
+ Interface::MethodType.new(
686
+ type_params: [],
687
+ type: Interface::Function.new(
688
+ params: Interface::Function::Params.build(required: [AST::Types::Literal.new(value: index)]),
689
+ return_type: elem_type,
690
+ location: nil
691
+ ),
692
+ block: nil,
693
+ method_decls: Set[]
694
+ ),
695
+ Interface::MethodType.new(
696
+ type_params: [Interface::TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
697
+ type: Interface::Function.new(
698
+ params: Interface::Function::Params.build(
699
+ required: [
700
+ AST::Types::Literal.new(value: index),
701
+ AST::Types::Var.new(name: :T)
702
+ ]
703
+ ),
704
+ return_type: AST::Types::Union.build(types: [elem_type, AST::Types::Var.new(name: :T)]),
705
+ location: nil
706
+ ),
707
+ block: nil,
708
+ method_decls: Set[]
709
+ ),
710
+ Interface::MethodType.new(
711
+ type_params: [Interface::TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
712
+ type: Interface::Function.new(
713
+ params: Interface::Function::Params.build(required: [AST::Types::Literal.new(value: index)]),
714
+ return_type: AST::Types::Union.build(types: [elem_type, AST::Types::Var.new(name: :T)]),
715
+ location: nil
716
+ ),
717
+ block: Interface::Block.new(
718
+ type: Interface::Function.new(
719
+ params: Interface::Function::Params.build(required: [AST::Builtin::Integer.instance_type]),
720
+ return_type: AST::Types::Var.new(name: :T),
721
+ location: nil
722
+ ),
723
+ optional: false
724
+ ),
725
+ method_decls: Set[]
726
+ )
727
+ ]
728
+ } + fetch.method_types
729
+ )
730
+ end
731
+
677
732
  array_interface.methods[:first] = array_interface.methods[:first].yield_self do |first|
678
733
  Interface::Interface::Entry.new(
679
734
  method_types: [
@@ -712,11 +767,11 @@ module Steep
712
767
 
713
768
  when Record
714
769
  yield_self do
715
- key_type = type.elements.keys.map {|value| Literal.new(value: value, location: nil) }.yield_self do |types|
770
+ all_key_type = type.elements.keys.map {|value| Literal.new(value: value, location: nil) }.yield_self do |types|
716
771
  Union.build(types: types, location: nil)
717
772
  end
718
- value_type = Union.build(types: type.elements.values, location: nil)
719
- hash_type = Builtin::Hash.instance_type(key_type, value_type)
773
+ all_value_type = Union.build(types: type.elements.values, location: nil)
774
+ hash_type = Builtin::Hash.instance_type(all_key_type, all_value_type)
720
775
 
721
776
  interface(hash_type, private: private, self_type: self_type).tap do |hash_interface|
722
777
  hash_interface.methods[:[]] = hash_interface.methods[:[]].yield_self do |ref|
@@ -768,6 +823,54 @@ module Steep
768
823
  } + update.method_types
769
824
  )
770
825
  end
826
+
827
+ hash_interface.methods[:fetch] = hash_interface.methods[:fetch].yield_self do |update|
828
+ Interface::Interface::Entry.new(
829
+ method_types: type.elements.flat_map {|key_value, value_type|
830
+ key_type = Literal.new(value: key_value, location: nil)
831
+
832
+ [
833
+ Interface::MethodType.new(
834
+ type_params: [],
835
+ type: Interface::Function.new(
836
+ params: Interface::Function::Params.build(required: [key_type]),
837
+ return_type: value_type,
838
+ location: nil
839
+ ),
840
+ block: nil,
841
+ method_decls: Set[]
842
+ ),
843
+ Interface::MethodType.new(
844
+ type_params: [Interface::TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
845
+ type: Interface::Function.new(
846
+ params: Interface::Function::Params.build(required: [key_type, AST::Types::Var.new(name: :T)]),
847
+ return_type: AST::Types::Union.build(types: [value_type, AST::Types::Var.new(name: :T)]),
848
+ location: nil
849
+ ),
850
+ block: nil,
851
+ method_decls: Set[]
852
+ ),
853
+ Interface::MethodType.new(
854
+ type_params: [Interface::TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
855
+ type: Interface::Function.new(
856
+ params: Interface::Function::Params.build(required: [key_type]),
857
+ return_type: AST::Types::Union.build(types: [value_type, AST::Types::Var.new(name: :T)]),
858
+ location: nil
859
+ ),
860
+ block: Interface::Block.new(
861
+ type: Interface::Function.new(
862
+ params: Interface::Function::Params.build(required: [all_key_type]),
863
+ return_type: AST::Types::Var.new(name: :T),
864
+ location: nil
865
+ ),
866
+ optional: false
867
+ ),
868
+ method_decls: Set[]
869
+ )
870
+ ]
871
+ } + update.method_types
872
+ )
873
+ end
771
874
  end
772
875
  end
773
876
 
@@ -45,6 +45,8 @@ module Steep
45
45
  end
46
46
  end
47
47
 
48
+ include Helper::ChildrenLevel
49
+
48
50
  def level
49
51
  children = type.params.each_type.to_a + [type.return_type]
50
52
  if block
data/lib/steep/cli.rb CHANGED
@@ -271,7 +271,9 @@ if type "rbenv" > /dev/null 2>&1; then
271
271
  STEEP="rbenv exec ${STEEP}"
272
272
  else
273
273
  if type "rvm" > /dev/null 2>&1; then
274
- STEEP="rvm ${ROOT_DIR} do ${STEEP}"
274
+ if [ -e ${ROOT_DIR}/.ruby-version ]; then
275
+ STEEP="rvm ${ROOT_DIR} do ${STEEP}"
276
+ fi
275
277
  fi
276
278
  fi
277
279
 
@@ -296,7 +296,7 @@ module Steep
296
296
  attr_reader :method_type
297
297
 
298
298
  def initialize(node:, method_type:)
299
- super(node: node, location: node.loc.selector)
299
+ super(node: node, location: (node.type == :super || node.type == :zsuper) ? node.loc.keyword : node.loc.selector)
300
300
  @method_type = method_type
301
301
  end
302
302
 
@@ -139,7 +139,7 @@ module Steep
139
139
  missing_count = 0
140
140
 
141
141
  ns = notifications.each.with_object({}) do |notification, hash|
142
- path = project.relative_path(Pathname(URI.parse(notification[:uri]).path))
142
+ path = project.relative_path(Steep::PathHelper.to_pathname(notification[:uri]))
143
143
  hash[path] = notification[:diagnostics]
144
144
  end
145
145
 
@@ -186,7 +186,7 @@ module Steep
186
186
  end
187
187
 
188
188
  ns = notifications.each.with_object({}) do |notification, hash|
189
- path = project.relative_path(Pathname(URI.parse(notification[:uri]).path))
189
+ path = project.relative_path(Steep::PathHelper.to_pathname(notification[:uri]))
190
190
  hash[path] = notification[:diagnostics]
191
191
  end
192
192
 
@@ -215,7 +215,7 @@ module Steep
215
215
  total = errors.sum {|notification| notification[:diagnostics].size }
216
216
 
217
217
  errors.each do |notification|
218
- path = Pathname(URI.parse(notification[:uri]).path)
218
+ path = Steep::PathHelper.to_pathname(notification[:uri])
219
219
  buffer = RBS::Buffer.new(name: project.relative_path(path), content: path.read)
220
220
  printer = DiagnosticPrinter.new(buffer: buffer, stdout: stdout)
221
221
 
@@ -0,0 +1,22 @@
1
+ module Steep
2
+ module PathHelper
3
+ module_function
4
+
5
+ def to_pathname(uri, dosish: Gem.win_platform?)
6
+ uri = URI.parse(uri)
7
+ if uri.scheme == "file"
8
+ path = uri.path
9
+ path.sub!(%r{^/([a-zA-Z])(:|%3A)//?}i, '\1:/') if dosish
10
+ Pathname(path)
11
+ end
12
+ end
13
+
14
+ def to_uri(path, dosish: Gem.win_platform?)
15
+ str_path = path.to_s
16
+ if dosish
17
+ str_path.insert(0, "/") if str_path[0] != "/"
18
+ end
19
+ URI::File.build(path: str_path)
20
+ end
21
+ end
22
+ end
data/lib/steep/project.rb CHANGED
@@ -16,22 +16,10 @@ module Steep
16
16
  steepfile_path.parent
17
17
  end
18
18
 
19
- def relative_path(orig_path)
20
- path = if Gem.win_platform?
21
- path_str = URI.decode_www_form_component(
22
- orig_path.to_s.delete_prefix("/")
23
- )
24
- unless path_str.start_with?(%r{[a-z]:/}i)
25
- # FIXME: Sometimes drive letter is missing, taking from base_dir
26
- path_str = base_dir.to_s.split("/")[0] + "/" + path_str
27
- end
28
- Pathname.new(
29
- path_str
30
- )
31
- else
32
- orig_path
33
- end
19
+ def relative_path(path)
34
20
  path.relative_path_from(base_dir)
21
+ rescue ArgumentError
22
+ path
35
23
  end
36
24
 
37
25
  def absolute_path(path)
@@ -69,6 +69,7 @@ module Steep
69
69
  end
70
70
  end
71
71
  end
72
+ thread.abort_on_exception = true
72
73
 
73
74
  Steep.logger.tagged "frontend" do
74
75
  begin
@@ -40,7 +40,7 @@ module Steep
40
40
 
41
41
  def collect_changes(request)
42
42
  push_buffer do |changes|
43
- path = project.relative_path(Pathname(URI.parse(request[:params][:textDocument][:uri]).path))
43
+ path = project.relative_path(Steep::PathHelper.to_pathname(request[:params][:textDocument][:uri]))
44
44
  version = request[:params][:textDocument][:version]
45
45
  Steep.logger.info { "Updating source: path=#{path}, version=#{version}..." }
46
46
 
@@ -53,8 +53,7 @@ module Steep
53
53
  when "textDocument/hover"
54
54
  id = request[:id]
55
55
 
56
- uri = URI.parse(request[:params][:textDocument][:uri])
57
- path = project.relative_path(Pathname(uri.path))
56
+ path = project.relative_path(Steep::PathHelper.to_pathname(request[:params][:textDocument][:uri]))
58
57
  line = request[:params][:position][:line]+1
59
58
  column = request[:params][:position][:character]
60
59
 
@@ -64,8 +63,7 @@ module Steep
64
63
  id = request[:id]
65
64
 
66
65
  params = request[:params]
67
- uri = URI.parse(params[:textDocument][:uri])
68
- path = project.relative_path(Pathname(uri.path))
66
+ path = project.relative_path(Steep::PathHelper.to_pathname(params[:textDocument][:uri]))
69
67
  line, column = params[:position].yield_self {|hash| [hash[:line]+1, hash[:character]] }
70
68
  trigger = params.dig(:context, :triggerCharacter)
71
69
 
@@ -144,7 +142,7 @@ module Steep
144
142
  decls = sig_service.files[relative_path].decls
145
143
  locator = RBS::Locator.new(decls: decls)
146
144
 
147
- hd, tail = locator.find2(line: job.line, column: job.column)
145
+ _hd, tail = locator.find2(line: job.line, column: job.column)
148
146
 
149
147
  namespace = []
150
148
  tail.each do |t|
@@ -48,6 +48,18 @@ module Steep
48
48
  call = content.method_call
49
49
  builder.push do |s|
50
50
  case call
51
+ when TypeInference::MethodCall::Special
52
+ mt = call.actual_method_type.with(
53
+ type: call.actual_method_type.type.with(return_type: call.return_type)
54
+ )
55
+ s << <<-EOM
56
+ **💡 Custom typing rule applies**
57
+
58
+ ```rbs
59
+ #{mt.to_s}
60
+ ```
61
+
62
+ EOM
51
63
  when TypeInference::MethodCall::Typed
52
64
  mt = call.actual_method_type.with(
53
65
  type: call.actual_method_type.type.with(return_type: call.return_type)