steep 1.5.0.pre.6 → 1.5.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d00242c259b7c8d2a4a0f7022874ac5bb5f08491ab3edade6165ff1a9fbe89a7
4
- data.tar.gz: e02d896359c4eb88c730601320bb9137342c19b9ad1956d4ac417ffa5926d74a
3
+ metadata.gz: d7775c9db83acf70b19f27b4983923ee40e8d1a39043c981726573b0c06eb1c8
4
+ data.tar.gz: 1d9f2753a19a577cce778f6ec1ee924534523812764c0350c21280d82a0e1c69
5
5
  SHA512:
6
- metadata.gz: 5be83d84d984d215342c030e9ea590c419a1e12963361266f4bc57e2b2ceec110a3f08313754b2f46a274fc8b0d2acca497c71f2eff24c3fd4505cb1ff2ac5a7
7
- data.tar.gz: 7a30b064aa7ec6e27e3811e93b1ddf7ff4824cdeb5dfe70075f34311f7e22016bf4f3a2b107307a5247c54532451a25155fc2ba277842fec85f71aa23fdaced1
6
+ metadata.gz: 6bd6340dfecc114df47a959d25a4201a87ccccbc0b1e59238962de51c28218b01aa25499ae8a760e678481192131dfdd3c99b6c89412ce4b6e0b3fad2bf34ca5
7
+ data.tar.gz: 87437181a053c65f297192eb9e339c0b58ad074d4c6716eef2a1019116d3ed06d0525eebcc49855ae99a8393bffac82640d77f608479b98f67e158b42c54d327
data/CHANGELOG.md CHANGED
@@ -2,6 +2,36 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.5.1 (2023-07-20)
6
+
7
+ ### Type checker core
8
+
9
+ * Support unreachable branch detection with `elsif` ([#879](https://github.com/soutaro/steep/pull/879))
10
+ * Give an optional type hint to lhs of `||` ([#874](https://github.com/soutaro/steep/pull/874))
11
+
12
+ ### Miscellaneous
13
+
14
+ * Update steep ([#878](https://github.com/soutaro/steep/pull/878))
15
+ * Update inline type comments ([#875](https://github.com/soutaro/steep/pull/875))
16
+
17
+ ## 1.5.0 (2023-07-13)
18
+
19
+ ### Type checker core
20
+
21
+ * Fix for the case `untyped` is the proc type hint ([#868](https://github.com/soutaro/steep/pull/868))
22
+ * Type case with type variable ([#869](https://github.com/soutaro/steep/pull/869))
23
+ * Filx `nil?` unreachability detection ([#867](https://github.com/soutaro/steep/pull/867))
24
+
25
+ ### Commandline tool
26
+
27
+ * Update `#configure_code_diagnostics` type ([#873](https://github.com/soutaro/steep/pull/873))
28
+ * Update diagnostics templates ([#871](https://github.com/soutaro/steep/pull/871))
29
+ * Removed "set" from "libray" in init.rb and README ([#870](https://github.com/soutaro/steep/pull/870))
30
+
31
+ ### Language server
32
+
33
+ * Use RBS::Buffer method to calculate position ([#872](https://github.com/soutaro/steep/pull/872))
34
+
5
35
  ## 1.5.0.pre.6 (2023-07-11)
6
36
 
7
37
  ### Type checker core
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- steep (1.5.0.pre.6)
4
+ steep (1.5.1)
5
5
  activesupport (>= 5.1)
6
6
  concurrent-ruby (>= 1.1.10)
7
7
  csv (>= 3.0.9)
@@ -53,7 +53,7 @@ GEM
53
53
  rb-fsevent (0.11.2)
54
54
  rb-inotify (0.10.1)
55
55
  ffi (~> 1.0)
56
- rbs (3.1.0)
56
+ rbs (3.1.1)
57
57
  ruby-lsp (0.5.1)
58
58
  language_server-protocol (~> 3.17.0)
59
59
  sorbet-runtime
data/Gemfile.steep.lock CHANGED
@@ -1,17 +1,17 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
- activesupport (7.0.5)
4
+ activesupport (7.0.6)
5
5
  concurrent-ruby (~> 1.0, >= 1.0.2)
6
6
  i18n (>= 1.6, < 2)
7
7
  minitest (>= 5.1)
8
8
  tzinfo (~> 2.0)
9
9
  ast (2.4.2)
10
10
  concurrent-ruby (1.2.2)
11
- csv (3.2.6)
11
+ csv (3.2.7)
12
12
  ffi (1.15.5)
13
13
  fileutils (1.7.1)
14
- i18n (1.13.0)
14
+ i18n (1.14.1)
15
15
  concurrent-ruby (~> 1.0)
16
16
  json (2.6.3)
17
17
  language_server-protocol (3.17.0.3)
@@ -19,18 +19,20 @@ GEM
19
19
  rb-fsevent (~> 0.10, >= 0.10.3)
20
20
  rb-inotify (~> 0.9, >= 0.9.10)
21
21
  logger (1.5.3)
22
- minitest (5.18.0)
23
- parser (3.2.2.1)
22
+ minitest (5.18.1)
23
+ parser (3.2.2.3)
24
24
  ast (~> 2.4.1)
25
+ racc
26
+ racc (1.7.1)
25
27
  rainbow (3.1.1)
26
28
  rb-fsevent (0.11.2)
27
29
  rb-inotify (0.10.1)
28
30
  ffi (~> 1.0)
29
- rbs (3.1.0)
31
+ rbs (3.1.1)
30
32
  securerandom (0.2.2)
31
- steep (1.4.0)
33
+ steep (1.5.0)
32
34
  activesupport (>= 5.1)
33
- concurrent-ruby (>= 1.2.2)
35
+ concurrent-ruby (>= 1.1.10)
34
36
  csv (>= 3.0.9)
35
37
  fileutils (>= 1.1.0)
36
38
  json (>= 2.1.0)
@@ -39,7 +41,7 @@ GEM
39
41
  logger (>= 1.3.0)
40
42
  parser (>= 3.1)
41
43
  rainbow (>= 2.2.2, < 4.0)
42
- rbs (>= 2.8.0)
44
+ rbs (>= 3.1.0)
43
45
  securerandom (>= 0.1)
44
46
  strscan (>= 1.0.0)
45
47
  terminal-table (>= 2, < 4)
data/README.md CHANGED
@@ -30,7 +30,7 @@ target :app do
30
30
  check "lib"
31
31
  signature "sig"
32
32
 
33
- library "set", "pathname"
33
+ library "pathname"
34
34
  end
35
35
  ```
36
36
 
data/Steepfile CHANGED
@@ -3,13 +3,12 @@ D = Steep::Diagnostic
3
3
  target :app do
4
4
  check "lib"
5
5
  ignore "lib/steep/shims"
6
-
6
+
7
7
  signature "sig"
8
8
 
9
9
  collection_config "rbs_collection.steep.yaml"
10
10
 
11
- configure_code_diagnostics do |hash| # You can setup everything yourself
12
- hash[D::Ruby::MethodDefinitionMissing] = :hint
11
+ configure_code_diagnostics(D::Ruby.strict) do |hash|
13
12
  end
14
13
 
15
14
  FileUtils.mkpath("tmp")
@@ -110,20 +110,20 @@ module Steep
110
110
  end
111
111
 
112
112
  def lvar_types
113
- var_type_annotations.each_key.with_object({}) do |name, hash|
114
- hash[name] = var_type(lvar: name)
113
+ var_type_annotations.each_key.with_object({}) do |name, hash| #$ Hash[Symbol, Types::t]
114
+ hash[name] = var_type(lvar: name) || raise
115
115
  end
116
116
  end
117
117
 
118
118
  def ivar_types
119
- ivar_type_annotations.each_key.with_object({}) do |name, hash|
120
- hash[name] = var_type(ivar: name)
119
+ ivar_type_annotations.each_key.with_object({}) do |name, hash| #$ Hash[Symbol, Types::t]
120
+ hash[name] = var_type(ivar: name) || raise
121
121
  end
122
122
  end
123
123
 
124
124
  def const_types
125
- const_type_annotations.each_key.with_object({}) do |name, hash|
126
- hash[name] = var_type(const: name)
125
+ const_type_annotations.each_key.with_object({}) do |name, hash| #$ Hash[RBS::TypeName, Types::t]
126
+ hash[name] = var_type(const: name) || raise
127
127
  end
128
128
  end
129
129
 
@@ -841,7 +841,6 @@ module Steep
841
841
  end
842
842
 
843
843
  class UnexpectedError < Base
844
- attr_reader :message
845
844
  attr_reader :error
846
845
 
847
846
  def initialize(node:, error:)
@@ -850,7 +849,28 @@ module Steep
850
849
  end
851
850
 
852
851
  def header_line
853
- "UnexpectedError: #{error.message}"
852
+ "UnexpectedError: #{error.message}(#{error.class})"
853
+ end
854
+
855
+ def detail_lines
856
+ if trace = error.backtrace
857
+ io = StringIO.new
858
+
859
+ total = trace.size
860
+ if total > 30
861
+ trace = trace.take(15)
862
+ end
863
+
864
+ trace.each.with_index do |line, index|
865
+ io.puts "#{index+1}. #{line}"
866
+ end
867
+
868
+ if trace.size != total
869
+ io.puts " (#{total - trace.size} more backtrace)"
870
+ end
871
+
872
+ io.string
873
+ end
854
874
  end
855
875
  end
856
876
 
@@ -992,20 +1012,57 @@ module Steep
992
1012
  def self.default
993
1013
  @default ||= _ = all_error.merge(
994
1014
  {
995
- ImplicitBreakValueMismatch => :warning,
996
- FallbackAny => :information,
997
- UnreachableValueBranch => :warning,
998
- UnreachableBranch => :information,
1015
+ ArgumentTypeMismatch => :error,
1016
+ BlockBodyTypeMismatch => :hint,
1017
+ BlockTypeMismatch => :hint,
1018
+ BreakTypeMismatch => :hint,
1019
+ DifferentMethodParameterKind => :hint,
1020
+ FallbackAny => :hint,
1021
+ FalseAssertion => :hint,
1022
+ ImplicitBreakValueMismatch => :hint,
1023
+ IncompatibleAnnotation => :hint,
1024
+ IncompatibleArgumentForwarding => :warning,
1025
+ IncompatibleAssignment => :hint,
1026
+ IncompatibleMethodTypeAnnotation => :hint,
1027
+ IncompatibleTypeCase => :hint,
1028
+ InsufficientKeywordArguments => :error,
1029
+ InsufficientPositionalArguments => :error,
1030
+ InsufficientTypeArgument => :hint,
1031
+ MethodArityMismatch => :error,
1032
+ MethodBodyTypeMismatch => :error,
1033
+ MethodDefinitionMissing => nil,
1034
+ MethodParameterMismatch => :error,
1035
+ MethodReturnTypeAnnotationMismatch => :hint,
1036
+ MultipleAssignmentConversionError => :hint,
1037
+ NoMethod => :error,
1038
+ ProcHintIgnored => :hint,
1039
+ ProcTypeExpected => :hint,
1040
+ RBSError => :information,
1041
+ RequiredBlockMissing => :error,
1042
+ ReturnTypeMismatch => :error,
1043
+ SetterBodyTypeMismatch => :information,
1044
+ SetterReturnTypeMismatch => :information,
1045
+ SyntaxError => :hint,
1046
+ TypeArgumentMismatchError => :hint,
1047
+ UnexpectedBlockGiven => :warning,
1048
+ UnexpectedDynamicMethod => :hint,
1049
+ UnexpectedError => :hint,
1050
+ UnexpectedJump => :hint,
1051
+ UnexpectedJumpValue => :hint,
1052
+ UnexpectedKeywordArgument => :error,
1053
+ UnexpectedPositionalArgument => :error,
1054
+ UnexpectedSplat => :hint,
1055
+ UnexpectedSuper => :information,
1056
+ UnexpectedTypeArgument => :hint,
1057
+ UnexpectedYield => :warning,
999
1058
  UnknownConstant => :warning,
1000
- MethodDefinitionMissing => :information,
1001
- FalseAssertion => :information,
1002
- UnexpectedTypeArgument => :information,
1003
- InsufficientTypeArgument => :information,
1004
- UnexpectedTypeArgument => :information,
1005
- UnsupportedSyntax => nil,
1006
- ProcHintIgnored => :information,
1007
- SetterBodyTypeMismatch => nil,
1008
- SetterReturnTypeMismatch => nil
1059
+ UnknownGlobalVariable => :warning,
1060
+ UnknownInstanceVariable => :information,
1061
+ UnreachableBranch => :hint,
1062
+ UnreachableValueBranch => :hint,
1063
+ UnresolvedOverloading => :error,
1064
+ UnsatisfiableConstraint => :hint,
1065
+ UnsupportedSyntax => :hint,
1009
1066
  }
1010
1067
  ).freeze
1011
1068
  end
@@ -1013,17 +1070,57 @@ module Steep
1013
1070
  def self.strict
1014
1071
  @strict ||= _ = all_error.merge(
1015
1072
  {
1016
- NoMethod => nil,
1017
- ImplicitBreakValueMismatch => nil,
1018
- FallbackAny => nil,
1019
- UnreachableValueBranch => nil,
1020
- UnreachableBranch => nil,
1021
- UnknownConstant => nil,
1022
- MethodDefinitionMissing => nil,
1023
- UnsupportedSyntax => nil,
1024
- ProcHintIgnored => :warning,
1073
+ ArgumentTypeMismatch => :error,
1074
+ BlockBodyTypeMismatch => :error,
1075
+ BlockTypeMismatch => :error,
1076
+ BreakTypeMismatch => :error,
1077
+ DifferentMethodParameterKind => :error,
1078
+ FallbackAny => :warning,
1079
+ FalseAssertion => :error,
1080
+ ImplicitBreakValueMismatch => :information,
1081
+ IncompatibleAnnotation => :error,
1082
+ IncompatibleArgumentForwarding => :error,
1083
+ IncompatibleAssignment => :error,
1084
+ IncompatibleMethodTypeAnnotation => :error,
1085
+ IncompatibleTypeCase => :error,
1086
+ InsufficientKeywordArguments => :error,
1087
+ InsufficientPositionalArguments => :error,
1088
+ InsufficientTypeArgument => :error,
1089
+ MethodArityMismatch => :error,
1090
+ MethodBodyTypeMismatch => :error,
1091
+ MethodDefinitionMissing => :hint,
1092
+ MethodParameterMismatch => :error,
1093
+ MethodReturnTypeAnnotationMismatch => :error,
1094
+ MultipleAssignmentConversionError => :error,
1095
+ NoMethod => :error,
1096
+ ProcHintIgnored => :information,
1097
+ ProcTypeExpected => :error,
1098
+ RBSError => :error,
1099
+ RequiredBlockMissing => :error,
1100
+ ReturnTypeMismatch => :error,
1025
1101
  SetterBodyTypeMismatch => :error,
1026
- SetterReturnTypeMismatch => :error
1102
+ SetterReturnTypeMismatch => :error,
1103
+ SyntaxError => :hint,
1104
+ TypeArgumentMismatchError => :error,
1105
+ UnexpectedBlockGiven => :error,
1106
+ UnexpectedDynamicMethod => :information,
1107
+ UnexpectedError => :information,
1108
+ UnexpectedJump => :error,
1109
+ UnexpectedJumpValue => :error,
1110
+ UnexpectedKeywordArgument => :error,
1111
+ UnexpectedPositionalArgument => :error,
1112
+ UnexpectedSplat => :warning,
1113
+ UnexpectedSuper => :error,
1114
+ UnexpectedTypeArgument => :error,
1115
+ UnexpectedYield => :error,
1116
+ UnknownConstant => :error,
1117
+ UnknownGlobalVariable => :error,
1118
+ UnknownInstanceVariable => :error,
1119
+ UnreachableBranch => :information,
1120
+ UnreachableValueBranch => :warning,
1121
+ UnresolvedOverloading => :error,
1122
+ UnsatisfiableConstraint => :error,
1123
+ UnsupportedSyntax => :information,
1027
1124
  }
1028
1125
  ).freeze
1029
1126
  end
@@ -1031,19 +1128,57 @@ module Steep
1031
1128
  def self.lenient
1032
1129
  @lenient ||= _ = all_error.merge(
1033
1130
  {
1034
- NoMethod => nil,
1035
- ImplicitBreakValueMismatch => nil,
1131
+ ArgumentTypeMismatch => :information,
1132
+ BlockBodyTypeMismatch => :hint,
1133
+ BlockTypeMismatch => :hint,
1134
+ BreakTypeMismatch => :hint,
1135
+ DifferentMethodParameterKind => nil,
1036
1136
  FallbackAny => nil,
1037
- UnreachableValueBranch => nil,
1038
- UnreachableBranch => nil,
1039
- UnknownConstant => nil,
1137
+ FalseAssertion => nil,
1138
+ ImplicitBreakValueMismatch => nil,
1139
+ IncompatibleAnnotation => nil,
1140
+ IncompatibleArgumentForwarding => :information,
1141
+ IncompatibleAssignment => :hint,
1142
+ IncompatibleMethodTypeAnnotation => nil,
1143
+ IncompatibleTypeCase => nil,
1144
+ InsufficientKeywordArguments => :information,
1145
+ InsufficientPositionalArguments => :information,
1146
+ InsufficientTypeArgument => nil,
1147
+ MethodArityMismatch => :information,
1148
+ MethodBodyTypeMismatch => :warning,
1040
1149
  MethodDefinitionMissing => nil,
1041
- UnexpectedJump => nil,
1042
- FalseAssertion => :hint,
1043
- UnsupportedSyntax => nil,
1044
- ProcHintIgnored => :hint,
1150
+ MethodParameterMismatch => :warning,
1151
+ MethodReturnTypeAnnotationMismatch => nil,
1152
+ MultipleAssignmentConversionError => nil,
1153
+ NoMethod => :information,
1154
+ ProcHintIgnored => nil,
1155
+ ProcTypeExpected => nil,
1156
+ RBSError => :information,
1157
+ RequiredBlockMissing => :hint,
1158
+ ReturnTypeMismatch => :warning,
1045
1159
  SetterBodyTypeMismatch => nil,
1046
- SetterReturnTypeMismatch => nil
1160
+ SetterReturnTypeMismatch => nil,
1161
+ SyntaxError => :hint,
1162
+ TypeArgumentMismatchError => nil,
1163
+ UnexpectedBlockGiven => :hint,
1164
+ UnexpectedDynamicMethod => nil,
1165
+ UnexpectedError => :hint,
1166
+ UnexpectedJump => nil,
1167
+ UnexpectedJumpValue => nil,
1168
+ UnexpectedKeywordArgument => :information,
1169
+ UnexpectedPositionalArgument => :information,
1170
+ UnexpectedSplat => nil,
1171
+ UnexpectedSuper => nil,
1172
+ UnexpectedTypeArgument => nil,
1173
+ UnexpectedYield => :information,
1174
+ UnknownConstant => :hint,
1175
+ UnknownGlobalVariable => :hint,
1176
+ UnknownInstanceVariable => :hint,
1177
+ UnreachableBranch => :hint,
1178
+ UnreachableValueBranch => :hint,
1179
+ UnresolvedOverloading => :information,
1180
+ UnsatisfiableConstraint => :hint,
1181
+ UnsupportedSyntax => :hint,
1047
1182
  }
1048
1183
  ).freeze
1049
1184
  end
@@ -168,8 +168,7 @@ module Steep
168
168
 
169
169
  Steep.logger.info { "Starting type checking: #{request_guid}" }
170
170
 
171
- diagnostic_notifications = []
172
- error_messages = []
171
+ error_messages = [] #: Array[String]
173
172
  client_reader.read do |response|
174
173
  case
175
174
  when response[:method] == "textDocument/publishDiagnostics"
@@ -18,9 +18,10 @@ module Steep
18
18
  # check "app/models/**/*.rb" # Glob
19
19
  # # ignore "lib/templates/*.rb"
20
20
  #
21
- # # library "pathname", "set" # Standard libraries
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", "set" # Standard libraries
38
+ # # library "pathname" # Standard libraries
38
39
  # end
39
40
  EOF
40
41
 
@@ -54,7 +54,7 @@ module Steep
54
54
  end
55
55
 
56
56
  def print(stats_result)
57
- rows = []
57
+ rows = [] #: Array[Array[untyped]]
58
58
  stats_result.sort_by {|row| row[:path] }.each do |row|
59
59
  if row[:type] == "success"
60
60
  rows << [
@@ -471,8 +471,8 @@ module Steep
471
471
 
472
472
  # For overloading
473
473
  def +(other)
474
- requireds = {}
475
- optionals = {}
474
+ requireds = {} #: Hash[Symbol, AST::Types::t]
475
+ optionals = {} #: Hash[Symbol, AST::Types::t]
476
476
 
477
477
  all_keys = Set[] + self.requireds.keys + self.optionals.keys + other.requireds.keys + other.optionals.keys
478
478
  all_keys.each do |key|
@@ -535,8 +535,8 @@ module Steep
535
535
 
536
536
  # For union
537
537
  def |(other)
538
- requireds = {}
539
- optionals = {}
538
+ requireds = {} #: Hash[Symbol, AST::Types::t]
539
+ optionals = {} #: Hash[Symbol, AST::Types::t]
540
540
 
541
541
  all_keys = Set[] + self.requireds.keys + self.optionals.keys + other.requireds.keys + other.optionals.keys
542
542
  all_keys.each do |key|
@@ -600,8 +600,8 @@ module Steep
600
600
 
601
601
  # For intersection
602
602
  def &(other)
603
- requireds = {}
604
- optionals = {}
603
+ requireds = {} #: Hash[Symbol, AST::Types::t]
604
+ optionals = {} #: Hash[Symbol, AST::Types::t]
605
605
 
606
606
  all_keys = Set[] + self.requireds.keys + self.optionals.keys + other.requireds.keys + other.optionals.keys
607
607
  all_keys.each do |key|
@@ -665,7 +665,7 @@ module Steep
665
665
  end
666
666
 
667
667
  def required
668
- array = []
668
+ array = [] #: Array[AST::Types::t]
669
669
 
670
670
  positional_params&.each do |param|
671
671
  case param
@@ -680,7 +680,7 @@ module Steep
680
680
  end
681
681
 
682
682
  def optional
683
- array = []
683
+ array = [] #: Array[AST::Types::t]
684
684
 
685
685
  positional_params&.each do |param|
686
686
  case param
@@ -66,7 +66,7 @@ module Steep
66
66
  def typing_options(level = nil, **hash)
67
67
  Steep.logger.error "#typing_options is deprecated and has no effect as of version 0.46.0. Update your Steepfile as follows for (almost) equivalent setting:"
68
68
 
69
- messages = []
69
+ messages = [] #: Array[String]
70
70
 
71
71
  messages << "# D = Steep::Diagnostic # Define a constant to shorten namespace"
72
72
 
@@ -83,7 +83,7 @@ module Steep
83
83
  Steep.logger.error " #{msg}"
84
84
  end
85
85
 
86
- config = []
86
+ config = [] #: Array[String]
87
87
 
88
88
  if hash[:allow_missing_definitions]
89
89
  config << "hash[D::Ruby::MethodDefinitionMissing] = nil # allow_missing_definitions"
@@ -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)
@@ -122,7 +122,7 @@ module Steep
122
122
  items = begin
123
123
  provider.run(line: job.line, column: job.column)
124
124
  rescue Parser::SyntaxError
125
- []
125
+ [] #: Array[Services::CompletionProvider::item]
126
126
  end
127
127
 
128
128
  completion_items = items.map do |item|
@@ -157,7 +157,7 @@ module Steep
157
157
  locator = RBS::Locator.new(buffer: buffer, dirs: dirs, decls: decls)
158
158
 
159
159
  _hd, tail = locator.find2(line: job.line, column: job.column)
160
- tail ||= []
160
+ tail ||= [] #: Array[RBS::Locator::component]
161
161
 
162
162
  tail.reverse_each do |t|
163
163
  case t
data/lib/steep/source.rb CHANGED
@@ -330,13 +330,12 @@ module Steep
330
330
  def find_heredoc_nodes(line, column, position)
331
331
  each_heredoc_node() do |nodes, location|
332
332
  node = nodes[0]
333
+ loc = location.heredoc_body #: Parser::Source::Range
333
334
 
334
- range = location.heredoc_body&.yield_self do |r|
335
- r.begin_pos..r.end_pos
336
- end
337
-
338
- if range && (range === position)
339
- return nodes
335
+ if range = loc.to_range
336
+ if range.begin <= position && position <= range.end
337
+ return nodes
338
+ end
340
339
  end
341
340
  end
342
341
 
@@ -344,12 +343,10 @@ module Steep
344
343
  end
345
344
 
346
345
  def find_nodes_loc(node, position, parents)
347
- range = node.location.expression&.yield_self do |r|
348
- r.begin_pos..r.end_pos
349
- end
346
+ range = node.location.expression&.to_range
350
347
 
351
348
  if range
352
- if range === position
349
+ if range.begin <= position && position <= range.end
353
350
  parents.unshift node
354
351
 
355
352
  Source.each_child_node(node) do |child|
@@ -366,9 +363,7 @@ module Steep
366
363
  def find_nodes(line:, column:)
367
364
  return [] unless node
368
365
 
369
- position = (line-1).times.sum do |i|
370
- node.location.expression.source_buffer.source_line(i+1).size + 1
371
- end + column
366
+ position = buffer.loc_to_pos([line, column])
372
367
 
373
368
  if heredoc_nodes = find_heredoc_nodes(line, column, position)
374
369
  Source.each_child_node(heredoc_nodes[0]) do |child|
@@ -430,7 +430,7 @@ module Steep
430
430
  when AST::Types::Name::Singleton
431
431
  singleton_super_types(relation.sub_type.name)
432
432
  else
433
- []
433
+ [] #: Array[super_type]
434
434
  end
435
435
 
436
436
  unless possible_sub_types.empty?
@@ -743,7 +743,7 @@ module Steep
743
743
  args.each {|arg| constraints.unknown!(arg.name) }
744
744
 
745
745
  upper_bounds = {}
746
- relations = []
746
+ relations = [] #: Array[Relation]
747
747
 
748
748
  args.zip(sub_type.type_params, super_type.type_params).each do |arg, sub_param, sup_param|
749
749
  sub_ub = sub_param.upper_bound
@@ -249,8 +249,8 @@ module Steep
249
249
  class_type = context.class_type
250
250
  end
251
251
 
252
- vars = []
253
- types = []
252
+ vars = [] #: Array[Symbol]
253
+ types = [] #: Array[AST::Types::t]
254
254
 
255
255
  dictionary.each_key do |var|
256
256
  if variables.include?(var)
@@ -1778,7 +1778,10 @@ module Steep
1778
1778
  yield_self do
1779
1779
  left_node, right_node = node.children
1780
1780
 
1781
- left_type, constr, left_context = synthesize(left_node, hint: hint, condition: true).to_ary
1781
+ if hint
1782
+ left_hint = union_type_unify(hint, AST::Builtin.nil_type, AST::Builtin.false_type)
1783
+ end
1784
+ left_type, constr, left_context = synthesize(left_node, hint: left_hint, condition: true).to_ary
1782
1785
 
1783
1786
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing, config: builder_config)
1784
1787
  left_truthy, left_falsy = interpreter.eval(env: left_context.type_env, node: left_node)
@@ -1888,7 +1891,7 @@ module Steep
1888
1891
  if loc.respond_to?(:keyword)
1889
1892
  condition_loc = loc #: NodeHelper::condition_loc
1890
1893
  case condition_loc.keyword.source
1891
- when "if"
1894
+ when "if", "elsif"
1892
1895
  location = condition_loc.begin || condition_loc.keyword
1893
1896
  when "unless"
1894
1897
  # `else` token always exists
@@ -1913,8 +1916,9 @@ module Steep
1913
1916
 
1914
1917
  if loc.respond_to?(:keyword)
1915
1918
  condition_loc = loc #: NodeHelper::condition_loc
1919
+
1916
1920
  case condition_loc.keyword.source
1917
- when "if"
1921
+ when "if", "elsif"
1918
1922
  # `else` token always exists
1919
1923
  location = condition_loc.else || raise
1920
1924
  when "unless"
@@ -3103,27 +3107,29 @@ module Steep
3103
3107
 
3104
3108
  type_hint = deep_expand_alias(type_hint) || type_hint
3105
3109
 
3106
- procs = flatten_union(type_hint).select do |type|
3107
- check_relation(sub_type: type, super_type: AST::Builtin::Proc.instance_type).success? &&
3108
- !type.is_a?(AST::Types::Any)
3109
- end
3110
+ unless type_hint.is_a?(AST::Types::Any)
3111
+ procs = flatten_union(type_hint).select do |type|
3112
+ check_relation(sub_type: type, super_type: AST::Builtin::Proc.instance_type).success? &&
3113
+ !type.is_a?(AST::Types::Any)
3114
+ end
3110
3115
 
3111
- proc_instances, proc_types = procs.partition {|type| AST::Builtin::Proc.instance_type?(type) }
3116
+ proc_instances, proc_types = procs.partition {|type| AST::Builtin::Proc.instance_type?(type) }
3112
3117
 
3113
- case
3114
- when !proc_instances.empty? && proc_types.empty?
3115
- # `::Proc` is given as a hint
3116
- when proc_types.size == 1
3117
- # Proc type is given as a hint
3118
- hint_proc = proc_types[0] #: AST::Types::Proc
3119
- params_hint = hint_proc.type.params
3120
- return_hint = hint_proc.type.return_type
3121
- block_hint = hint_proc.block
3122
- self_hint = hint_proc.self_type
3123
- else
3124
- typing.add_error(
3125
- Diagnostic::Ruby::ProcHintIgnored.new(hint_type: original_hint, node: node)
3126
- )
3118
+ case
3119
+ when !proc_instances.empty? && proc_types.empty?
3120
+ # `::Proc` is given as a hint
3121
+ when proc_types.size == 1
3122
+ # Proc type is given as a hint
3123
+ hint_proc = proc_types[0] #: AST::Types::Proc
3124
+ params_hint = hint_proc.type.params
3125
+ return_hint = hint_proc.type.return_type
3126
+ block_hint = hint_proc.block
3127
+ self_hint = hint_proc.self_type
3128
+ else
3129
+ typing.add_error(
3130
+ Diagnostic::Ruby::ProcHintIgnored.new(hint_type: original_hint, node: node)
3131
+ )
3132
+ end
3127
3133
  end
3128
3134
  end
3129
3135
 
@@ -280,20 +280,22 @@ module Steep
280
280
  when AST::Types::Logic::ReceiverIsNil
281
281
  if receiver && arguments.size.zero?
282
282
  receiver_type = typing.type_of(node: receiver)
283
- truthy_receiver, falsy_receiver = factory.partition_union(receiver_type)
283
+ unwrap = factory.unwrap_optional(receiver_type)
284
+ truthy_receiver = AST::Builtin.nil_type
285
+ falsy_receiver = unwrap || receiver_type
284
286
 
285
287
  truthy_env, falsy_env = refine_node_type(
286
288
  env: env,
287
289
  node: receiver,
288
- truthy_type: falsy_receiver || BOT,
289
- falsy_type: truthy_receiver || BOT
290
+ truthy_type: truthy_receiver,
291
+ falsy_type: falsy_receiver
290
292
  )
291
293
 
292
294
  truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
293
- truthy_result.unreachable! unless truthy_receiver
295
+ truthy_result.unreachable! if unwrap == receiver_type
294
296
 
295
297
  falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
296
- falsy_result.unreachable! unless falsy_receiver
298
+ falsy_result.unreachable! unless unwrap
297
299
 
298
300
  [truthy_result, falsy_result]
299
301
  end
@@ -500,7 +502,7 @@ module Steep
500
502
  type_case_select0(ty, klass)
501
503
  end
502
504
 
503
- when AST::Types::Any, AST::Types::Top
505
+ when AST::Types::Any, AST::Types::Top, AST::Types::Var
504
506
  [
505
507
  [instance_type],
506
508
  [type]
@@ -9,7 +9,7 @@ module Steep
9
9
  attr_reader :pure_method_calls
10
10
 
11
11
  def to_s
12
- array = []
12
+ array = [] #: Array[String]
13
13
 
14
14
  local_variable_types.each do |name, entry|
15
15
  if enforced_type = entry[1]
@@ -108,7 +108,7 @@ module Steep
108
108
  end
109
109
 
110
110
  def assign_local_variables(assignments)
111
- local_variable_types = {}
111
+ local_variable_types = {} #: Hash[Symbol, local_variable_entry]
112
112
  invalidated_nodes = Set[]
113
113
 
114
114
  assignments.each do |name, new_type|
@@ -135,7 +135,7 @@ module Steep
135
135
  end
136
136
 
137
137
  def refine_types(local_variable_types: {}, pure_call_types: {})
138
- local_variable_updates = {}
138
+ local_variable_updates = {} #: Hash[Symbol, local_variable_entry]
139
139
 
140
140
  local_variable_types.each do |name, type|
141
141
  local_variable_name!(name)
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "1.5.0.pre.6"
2
+ VERSION = "1.5.1"
3
3
  end
@@ -32,3 +32,8 @@ class HogeHoge
32
32
  bar(self, ...).to_s
33
33
  end
34
34
  end
35
+
36
+
37
+
38
+ conference = nil #: Conference?
39
+
@@ -2,7 +2,7 @@ module Steep
2
2
  module AST
3
3
  module Annotation
4
4
  class Collection
5
- attr_reader annotations: untyped
5
+ attr_reader annotations: Array[Annotation::t]
6
6
 
7
7
  attr_reader factory: Types::Factory
8
8
 
@@ -14,31 +14,34 @@ module Steep
14
14
 
15
15
  attr_reader ivar_type_annotations: Hash[Symbol, IvarType]
16
16
 
17
- attr_reader method_type_annotations: untyped
17
+ attr_reader method_type_annotations: Hash[Symbol, MethodType?]
18
18
 
19
- attr_reader block_type_annotation: untyped
19
+ attr_reader block_type_annotation: BlockType?
20
20
 
21
- attr_reader return_type_annotation: untyped
21
+ attr_reader return_type_annotation: ReturnType?
22
22
 
23
- attr_reader self_type_annotation: untyped
23
+ attr_reader self_type_annotation: SelfType?
24
24
 
25
- attr_reader instance_type_annotation: untyped
25
+ attr_reader instance_type_annotation: InstanceType?
26
26
 
27
- attr_reader module_type_annotation: untyped
27
+ attr_reader module_type_annotation: ModuleType?
28
28
 
29
29
  attr_reader implement_module_annotation: Implements?
30
30
 
31
- attr_reader dynamic_annotations: untyped
31
+ attr_reader dynamic_annotations: Array[Dynamic]
32
32
 
33
- attr_reader break_type_annotation: untyped
33
+ attr_reader break_type_annotation: BreakType?
34
34
 
35
- def initialize: (annotations: untyped, factory: untyped, context: untyped) -> void
35
+ def initialize: (annotations: Array[Annotation::t], factory: Types::Factory, context: RBS::Resolver::context) -> void
36
36
 
37
- def absolute_type: (untyped `type`) -> (untyped | nil)
37
+ def absolute_type: (Types::t) -> Types::t
38
+ | (Types::t?) -> Types::t?
38
39
 
39
- def var_type: (?lvar: untyped?, ?ivar: untyped?, ?const: untyped?) -> untyped
40
+ def var_type: (lvar: Symbol) -> Types::t?
41
+ | (ivar: Symbol) -> Types::t?
42
+ | (const: RBS::TypeName) -> Types::t?
40
43
 
41
- def method_type: (untyped name) -> (untyped | nil)
44
+ def method_type: (Symbol name) -> Interface::MethodType?
42
45
 
43
46
  %a{pure} def block_type: () -> Types::t?
44
47
 
@@ -52,23 +55,23 @@ module Steep
52
55
 
53
56
  %a{pure} def break_type: () -> Types::t?
54
57
 
55
- def lvar_types: () -> untyped
58
+ def lvar_types: () -> Hash[Symbol, Types::t]
56
59
 
57
- def ivar_types: () -> untyped
60
+ def ivar_types: () -> Hash[Symbol, Types::t]
58
61
 
59
- def const_types: () -> untyped
62
+ def const_types: () -> Hash[RBS::TypeName, Types::t]
60
63
 
61
- def instance_dynamics: () -> untyped
64
+ def instance_dynamics: () -> Array[Symbol]
62
65
 
63
- def module_dynamics: () -> untyped
66
+ def module_dynamics: () -> Array[Symbol]
64
67
 
65
- def merge_block_annotations: (untyped annotations) -> untyped
68
+ def merge_block_annotations: (Collection annotations) -> Collection
66
69
 
67
- def any?: () { () -> untyped } -> untyped
70
+ def any?: () { (Annotation::t) -> boolish } -> bool
68
71
 
69
- def size: () -> untyped
72
+ def size: () -> Integer
70
73
 
71
- def include?: (untyped obj) -> untyped
74
+ def include?: (Annotation::t obj) -> bool
72
75
  end
73
76
  end
74
77
  end
@@ -77,13 +77,12 @@ module Steep
77
77
  # Returns a type that doesn't have `nil` in the union component
78
78
  #
79
79
  # * Returns `nil` if given type is `nil`
80
- # * **Doesn't expand type alias automatically**
80
+ # * Expand (unfold) the type aliases automatically
81
81
  #
82
82
  # ```ruby
83
83
  # unwrap_optional(`String?`) # => `String`
84
84
  # unwrap_optional(`String | Integer | false | nil`) # => `String | Integer | false`
85
85
  # unwrap_optional(`nil`) # => nil
86
- # unwrap_optional(`boolish`) # => `boolish`
87
86
  # ```
88
87
  #
89
88
  def unwrap_optional: (Types::t) -> Types::t?
@@ -546,11 +546,9 @@ module Steep
546
546
  end
547
547
 
548
548
  class UnexpectedError < Base
549
- attr_reader message: untyped
550
-
551
- attr_reader error: untyped
549
+ attr_reader error: Exception
552
550
 
553
- def initialize: (node: untyped, error: untyped) -> void
551
+ def initialize: (node: Parser::AST::Node, error: Exception) -> void
554
552
 
555
553
  def header_line: () -> ::String
556
554
  end
@@ -623,7 +621,7 @@ module Steep
623
621
  end
624
622
 
625
623
  # RBS embedded in the Ruby code has validation error
626
- #
624
+ #
627
625
  class RBSError < Base
628
626
  attr_reader error: Signature::Base
629
627
 
@@ -662,21 +660,35 @@ module Steep
662
660
 
663
661
  ALL: Array[singleton(Base)]
664
662
 
665
- type template = Hash[singleton(Base), LSPFormatter::severity]
663
+ type template = Hash[singleton(Base), LSPFormatter::severity?]
666
664
 
667
665
  self.@all_error: template?
666
+ self.@default: template?
667
+ self.@strict: template?
668
+ self.@lenient: template?
669
+ self.@silent: template?
670
+
671
+ # This template reports everything as an error
672
+ #
668
673
  def self.all_error: () -> template
669
674
 
670
- self.@default: template?
675
+ # This template detects inconsistencies between RBS and Ruby code APIs
676
+ #
671
677
  def self.default: () -> template
672
678
 
673
- self.@strict: template?
679
+ # This template helps you keeping your codebase (almost) type-safe
680
+ #
681
+ # You can start with this template to review the problems reported on the project,
682
+ # and you can ignore some kind of errors.
683
+ #
674
684
  def self.strict: () -> template
675
685
 
676
- self.@lenient: template?
686
+ # This template detects inconsistent definition in Ruby code with respect to your RBS definition
687
+ #
677
688
  def self.lenient: () -> template
678
689
 
679
- self.@silent: template?
690
+ # This template reports nothing
691
+ #
680
692
  def self.silent: () -> template
681
693
  end
682
694
  end
@@ -1,3 +1,5 @@
1
+ use Steep::Diagnostic::Ruby::template
2
+
1
3
  module Steep
2
4
  class Project
3
5
  class DSL
@@ -71,10 +73,13 @@ module Steep
71
73
  # D = Steep::Diagnostic
72
74
  #
73
75
  # configure_code_diagnostics(D::Ruby.lenient)
76
+ # configure_code_diagnostics(D::Ruby.strict) do |config|
77
+ # config[D::Ruby::NoMethod] = nil
78
+ # end
74
79
  # ```
75
80
  #
76
- def configure_code_diagnostics: (Hash[untyped, untyped] hash) -> void
77
- | () { (Hash[untyped, untyped]) -> void } -> void
81
+ def configure_code_diagnostics: (template hash) ?{ (template) -> void }-> void
82
+ | () { (template) -> void }-> void
78
83
 
79
84
  def collection_config: (Pathname path) -> void
80
85
 
@@ -1,16 +1,4 @@
1
1
  ---
2
- - file: unexpected.rb
3
- diagnostics:
4
- - range:
5
- start:
6
- line: 1
7
- character: 0
8
- end:
9
- line: 1
10
- character: 14
11
- severity: ERROR
12
- message: 'UnexpectedError: unexpected.rbs:2:17...2:24: Could not find String1'
13
- code: Ruby::UnexpectedError
14
2
  - file: unexpected.rbs
15
3
  diagnostics:
16
4
  - range:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: steep
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0.pre.6
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-11 00:00:00.000000000 Z
11
+ date: 2023-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -266,7 +266,6 @@ files:
266
266
  - lib/steep/ast/builtin.rb
267
267
  - lib/steep/ast/node/type_application.rb
268
268
  - lib/steep/ast/node/type_assertion.rb
269
- - lib/steep/ast/type_params.rb
270
269
  - lib/steep/ast/types/any.rb
271
270
  - lib/steep/ast/types/boolean.rb
272
271
  - lib/steep/ast/types/bot.rb
@@ -401,7 +400,6 @@ files:
401
400
  - sig/steep/ast/builtin.rbs
402
401
  - sig/steep/ast/node/type_application.rbs
403
402
  - sig/steep/ast/node/type_assertion.rbs
404
- - sig/steep/ast/type_params.rbs
405
403
  - sig/steep/ast/types.rbs
406
404
  - sig/steep/ast/types/any.rbs
407
405
  - sig/steep/ast/types/boolean.rbs
@@ -757,7 +755,6 @@ files:
757
755
  - smoke/type_case/test_expectations.yml
758
756
  - smoke/unexpected/Steepfile
759
757
  - smoke/unexpected/test_expectations.yml
760
- - smoke/unexpected/unexpected.rb
761
758
  - smoke/unexpected/unexpected.rbs
762
759
  - smoke/yield/Steepfile
763
760
  - smoke/yield/a.rb
@@ -782,9 +779,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
782
779
  version: 2.7.0
783
780
  required_rubygems_version: !ruby/object:Gem::Requirement
784
781
  requirements:
785
- - - ">"
782
+ - - ">="
786
783
  - !ruby/object:Gem::Version
787
- version: 1.3.1
784
+ version: '0'
788
785
  requirements: []
789
786
  rubygems_version: 3.4.10
790
787
  signing_key:
@@ -1,13 +0,0 @@
1
- module Steep
2
- module AST
3
- class TypeParams
4
- attr_reader :location
5
- attr_reader :variables
6
-
7
- def initialize(location: nil, variables:)
8
- @location = location
9
- @variables = variables
10
- end
11
- end
12
- end
13
- end
@@ -1,11 +0,0 @@
1
- # module Steep
2
- # module AST
3
- # class TypeParams
4
- # attr_reader location: untyped
5
-
6
- # attr_reader variables: untyped
7
-
8
- # def initialize: (variables: untyped, ?location: untyped?) -> void
9
- # end
10
- # end
11
- # end
@@ -1 +0,0 @@
1
- Unexpected.new.foo().bar