steep 0.40.0 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/bin/output_rebaseline.rb +15 -30
  4. data/bin/output_test.rb +17 -57
  5. data/lib/steep.rb +4 -0
  6. data/lib/steep/cli.rb +9 -3
  7. data/lib/steep/drivers/check.rb +106 -14
  8. data/lib/steep/drivers/diagnostic_printer.rb +11 -11
  9. data/lib/steep/expectations.rb +159 -0
  10. data/lib/steep/project.rb +6 -0
  11. data/lib/steep/version.rb +1 -1
  12. data/smoke/alias/test_expectations.yml +96 -0
  13. data/smoke/and/test_expectations.yml +31 -0
  14. data/smoke/array/test_expectations.yml +103 -0
  15. data/smoke/block/test_expectations.yml +125 -0
  16. data/smoke/case/test_expectations.yml +47 -0
  17. data/smoke/class/test_expectations.yml +120 -0
  18. data/smoke/const/test_expectations.yml +139 -0
  19. data/smoke/diagnostics-rbs-duplicated/test_expectations.yml +13 -0
  20. data/smoke/diagnostics-rbs/test_expectations.yml +229 -0
  21. data/smoke/diagnostics/test_expectations.yml +477 -0
  22. data/smoke/dstr/test_expectations.yml +13 -0
  23. data/smoke/ensure/test_expectations.yml +62 -0
  24. data/smoke/enumerator/test_expectations.yml +135 -0
  25. data/smoke/extension/test_expectations.yml +61 -0
  26. data/smoke/hash/test_expectations.yml +81 -0
  27. data/smoke/hello/test_expectations.yml +25 -0
  28. data/smoke/if/test_expectations.yml +34 -0
  29. data/smoke/implements/test_expectations.yml +23 -0
  30. data/smoke/initialize/test_expectations.yml +1 -0
  31. data/smoke/integer/test_expectations.yml +101 -0
  32. data/smoke/interface/test_expectations.yml +23 -0
  33. data/smoke/kwbegin/test_expectations.yml +17 -0
  34. data/smoke/lambda/test_expectations.yml +39 -0
  35. data/smoke/literal/test_expectations.yml +106 -0
  36. data/smoke/map/test_expectations.yml +1 -0
  37. data/smoke/method/test_expectations.yml +90 -0
  38. data/smoke/module/test_expectations.yml +75 -0
  39. data/smoke/regexp/test_expectations.yml +615 -0
  40. data/smoke/regression/test_expectations.yml +43 -0
  41. data/smoke/rescue/test_expectations.yml +79 -0
  42. data/smoke/self/test_expectations.yml +23 -0
  43. data/smoke/skip/test_expectations.yml +23 -0
  44. data/smoke/stdout/test_expectations.yml +1 -0
  45. data/smoke/super/test_expectations.yml +79 -0
  46. data/smoke/toplevel/test_expectations.yml +15 -0
  47. data/smoke/tsort/test_expectations.yml +43 -0
  48. data/smoke/type_case/test_expectations.yml +48 -0
  49. data/smoke/yield/test_expectations.yml +68 -0
  50. metadata +41 -44
  51. data/smoke/alias/test.yaml +0 -73
  52. data/smoke/and/test.yaml +0 -24
  53. data/smoke/array/test.yaml +0 -80
  54. data/smoke/block/test.yaml +0 -96
  55. data/smoke/broken/Steepfile +0 -5
  56. data/smoke/broken/broken.rb +0 -0
  57. data/smoke/broken/broken.rbs +0 -0
  58. data/smoke/broken/test.yaml +0 -6
  59. data/smoke/case/test.yaml +0 -36
  60. data/smoke/class/test.yaml +0 -89
  61. data/smoke/const/test.yaml +0 -96
  62. data/smoke/diagnostics-rbs-duplicated/test.yaml +0 -10
  63. data/smoke/diagnostics-rbs/test.yaml +0 -142
  64. data/smoke/diagnostics/test.yaml +0 -333
  65. data/smoke/dstr/test.yaml +0 -10
  66. data/smoke/ensure/test.yaml +0 -47
  67. data/smoke/enumerator/test.yaml +0 -100
  68. data/smoke/extension/test.yaml +0 -50
  69. data/smoke/hash/test.yaml +0 -62
  70. data/smoke/hello/test.yaml +0 -18
  71. data/smoke/if/test.yaml +0 -27
  72. data/smoke/implements/test.yaml +0 -16
  73. data/smoke/initialize/test.yaml +0 -4
  74. data/smoke/integer/test.yaml +0 -66
  75. data/smoke/interface/test.yaml +0 -16
  76. data/smoke/kwbegin/test.yaml +0 -14
  77. data/smoke/lambda/test.yaml +0 -28
  78. data/smoke/literal/test.yaml +0 -79
  79. data/smoke/map/test.yaml +0 -4
  80. data/smoke/method/test.yaml +0 -71
  81. data/smoke/module/test.yaml +0 -51
  82. data/smoke/regexp/test.yaml +0 -372
  83. data/smoke/regression/test.yaml +0 -38
  84. data/smoke/rescue/test.yaml +0 -60
  85. data/smoke/self/test.yaml +0 -16
  86. data/smoke/skip/test.yaml +0 -16
  87. data/smoke/stdout/test.yaml +0 -4
  88. data/smoke/super/test.yaml +0 -52
  89. data/smoke/toplevel/test.yaml +0 -12
  90. data/smoke/tsort/test.yaml +0 -32
  91. data/smoke/type_case/test.yaml +0 -33
  92. data/smoke/yield/test.yaml +0 -49
@@ -0,0 +1,159 @@
1
+ module Steep
2
+ class Expectations
3
+ class TestResult
4
+ attr_reader :path
5
+ attr_reader :expectation
6
+ attr_reader :actual
7
+
8
+ def initialize(path:, expectation:, actual:)
9
+ @path = path
10
+ @expectation = expectation
11
+ @actual = actual
12
+ end
13
+
14
+ def empty?
15
+ actual.empty?
16
+ end
17
+
18
+ def satisfied?
19
+ unexpected_diagnostics.empty? && missing_diagnostics.empty?
20
+ end
21
+
22
+ def each_diagnostics
23
+ if block_given?
24
+ expected_set = Set.new(expectation)
25
+ actual_set = Set.new(actual)
26
+
27
+ (expected_set + actual_set).sort_by {|a| Expectations.sort_key(a) }.each do |lsp|
28
+ case
29
+ when expected_set.include?(lsp) && actual_set.include?(lsp)
30
+ yield :expected, lsp
31
+ when expected_set.include?(lsp)
32
+ yield :missing, lsp
33
+ when actual_set.include?(lsp)
34
+ yield :unexpected, lsp
35
+ end
36
+ end
37
+ else
38
+ enum_for :each_diagnostics
39
+ end
40
+ end
41
+
42
+ def expected_diagnostics
43
+ each_diagnostics.select {|type, _| type == :expected }.map {|_, diag| diag }
44
+ end
45
+
46
+ def unexpected_diagnostics
47
+ each_diagnostics.select {|type, _| type == :unexpected }.map {|_, diag| diag }
48
+ end
49
+
50
+ def missing_diagnostics
51
+ each_diagnostics.select {|type, _| type == :missing }.map {|_, diag| diag }
52
+ end
53
+ end
54
+
55
+ LSP = LanguageServer::Protocol
56
+
57
+ attr_reader :diagnostics
58
+
59
+ def self.sort_key(hash)
60
+ [
61
+ hash.dig(:range, :start, :line),
62
+ hash.dig(:range, :start, :character),
63
+ hash.dig(:range, :end, :line),
64
+ hash.dig(:range, :end, :character),
65
+ hash[:code],
66
+ hash[:severity],
67
+ hash[:message]
68
+ ]
69
+ end
70
+
71
+ def initialize()
72
+ @diagnostics = {}
73
+ end
74
+
75
+ def test(path:, diagnostics:)
76
+ TestResult.new(path: path, expectation: self.diagnostics[path] || [], actual: diagnostics)
77
+ end
78
+
79
+ def self.empty
80
+ new()
81
+ end
82
+
83
+ def to_yaml
84
+ array = []
85
+
86
+ diagnostics.each_key.sort.each do |key|
87
+ ds = diagnostics[key]
88
+ array << {
89
+ "file" => key.to_s,
90
+ 'diagnostics' => ds.sort_by {|hash| Expectations.sort_key(hash) }
91
+ .map { |d| Expectations.lsp_to_hash(d) }
92
+ }
93
+ end
94
+
95
+ YAML.dump(array)
96
+ end
97
+
98
+ def self.load(path:, content:)
99
+ expectations = new()
100
+
101
+ YAML.load(content, filename: path.to_s).each do |entry|
102
+ file = Pathname(entry["file"])
103
+ expectations.diagnostics[file] = entry["diagnostics"]
104
+ .map {|hash| hash_to_lsp(hash) }
105
+ .sort_by! {|h| sort_key(h) }
106
+ end
107
+
108
+ expectations
109
+ end
110
+
111
+ # Translate hash to LSP Diagnostic message
112
+ def self.hash_to_lsp(hash)
113
+ {
114
+ range: {
115
+ start: {
116
+ line: hash.dig("range", "start", "line") - 1,
117
+ character: hash.dig("range", "start", "character")
118
+ },
119
+ end: {
120
+ line: hash.dig("range", "end", "line") - 1,
121
+ character: hash.dig("range", "end", "character")
122
+ }
123
+ },
124
+ severity: {
125
+ "ERROR" => LSP::Constant::DiagnosticSeverity::ERROR,
126
+ "WARNING" => LSP::Constant::DiagnosticSeverity::WARNING,
127
+ "INFORMATION" => LSP::Constant::DiagnosticSeverity::INFORMATION,
128
+ "HINT" => LSP::Constant::DiagnosticSeverity::HINT
129
+ }[hash["severity"] || "ERROR"],
130
+ message: hash["message"],
131
+ code: hash["code"]
132
+ }
133
+ end
134
+
135
+ # Translate LSP diagnostic message to hash
136
+ def self.lsp_to_hash(lsp)
137
+ {
138
+ "range" => {
139
+ "start" => {
140
+ "line" => lsp.dig(:range, :start, :line) + 1,
141
+ "character" => lsp.dig(:range, :start, :character)
142
+ },
143
+ "end" => {
144
+ "line" => lsp.dig(:range, :end, :line) + 1,
145
+ "character" => lsp.dig(:range, :end, :character)
146
+ }
147
+ },
148
+ "severity" => {
149
+ LSP::Constant::DiagnosticSeverity::ERROR => "ERROR",
150
+ LSP::Constant::DiagnosticSeverity::WARNING => "WARNING",
151
+ LSP::Constant::DiagnosticSeverity::INFORMATION => "INFORMATION",
152
+ LSP::Constant::DiagnosticSeverity::HINT => "HINT"
153
+ }[lsp[:severity] || LSP::Constant::DiagnosticSeverity::ERROR],
154
+ "message" => lsp[:message],
155
+ "code" => lsp[:code]
156
+ }
157
+ end
158
+ end
159
+ end
data/lib/steep/project.rb CHANGED
@@ -49,6 +49,12 @@ module Steep
49
49
  end
50
50
  end
51
51
 
52
+ def all_signature_files
53
+ targets.each.with_object(Set[]) do |target, paths|
54
+ paths.merge(target.signature_files.keys)
55
+ end
56
+ end
57
+
52
58
  def type_of_node(path:, line:, column:)
53
59
  source_file = targets.map {|target| target.source_files[path] }.compact[0]
54
60
 
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.40.0"
2
+ VERSION = "0.41.0"
3
3
  end
@@ -0,0 +1,96 @@
1
+ ---
2
+ - file: a.rb
3
+ diagnostics:
4
+ - range:
5
+ start:
6
+ line: 4
7
+ character: 0
8
+ end:
9
+ line: 4
10
+ character: 7
11
+ severity: ERROR
12
+ message: |-
13
+ Cannot find compatible overloading of method `+` of type `(::String | ::Integer)`
14
+ Method types:
15
+ def +: ((::string & ::Integer)) -> (::String | ::Integer)
16
+ | ((::string & ::Float)) -> (::String | ::Float)
17
+ | ((::string & ::Rational)) -> (::String | ::Rational)
18
+ | ((::string & ::Complex)) -> (::String | ::Complex)
19
+ code: Ruby::UnresolvedOverloading
20
+ - range:
21
+ start:
22
+ line: 13
23
+ character: 2
24
+ end:
25
+ line: 13
26
+ character: 7
27
+ severity: ERROR
28
+ message: |-
29
+ Cannot assign a value of type `::String` to a variable of type `::Symbol`
30
+ ::String <: ::Symbol
31
+ ::Object <: ::Symbol
32
+ ::BasicObject <: ::Symbol
33
+ code: Ruby::IncompatibleAssignment
34
+ - range:
35
+ start:
36
+ line: 15
37
+ character: 2
38
+ end:
39
+ line: 15
40
+ character: 7
41
+ severity: ERROR
42
+ message: |-
43
+ Cannot assign a value of type `::Integer` to a variable of type `::Symbol`
44
+ ::Integer <: ::Symbol
45
+ ::Numeric <: ::Symbol
46
+ ::Object <: ::Symbol
47
+ ::BasicObject <: ::Symbol
48
+ code: Ruby::IncompatibleAssignment
49
+ - file: b.rb
50
+ diagnostics:
51
+ - range:
52
+ start:
53
+ line: 6
54
+ character: 0
55
+ end:
56
+ line: 6
57
+ character: 8
58
+ severity: ERROR
59
+ message: |-
60
+ Cannot assign a value of type `::String` to a variable of type `::Integer`
61
+ ::String <: ::Integer
62
+ ::Object <: ::Integer
63
+ ::BasicObject <: ::Integer
64
+ code: Ruby::IncompatibleAssignment
65
+ - file: c.rb
66
+ diagnostics:
67
+ - range:
68
+ start:
69
+ line: 3
70
+ character: 0
71
+ end:
72
+ line: 3
73
+ character: 32
74
+ severity: ERROR
75
+ message: |-
76
+ Cannot assign a value of type `::Integer` to a variable of type `::String`
77
+ ::Integer <: ::String
78
+ ::Numeric <: ::String
79
+ ::Object <: ::String
80
+ ::BasicObject <: ::String
81
+ code: Ruby::IncompatibleAssignment
82
+ - range:
83
+ start:
84
+ line: 8
85
+ character: 0
86
+ end:
87
+ line: 8
88
+ character: 32
89
+ severity: ERROR
90
+ message: |-
91
+ Cannot assign a value of type `::Integer` to a variable of type `::String`
92
+ ::Integer <: ::String
93
+ ::Numeric <: ::String
94
+ ::Object <: ::String
95
+ ::BasicObject <: ::String
96
+ code: Ruby::IncompatibleAssignment
@@ -0,0 +1,31 @@
1
+ ---
2
+ - file: a.rb
3
+ diagnostics:
4
+ - range:
5
+ start:
6
+ line: 6
7
+ character: 0
8
+ end:
9
+ line: 6
10
+ character: 17
11
+ severity: ERROR
12
+ message: |-
13
+ Cannot assign a value of type `(::String | nil)` to a variable of type `::String`
14
+ (::String | nil) <: ::String
15
+ nil <: ::String
16
+ code: Ruby::IncompatibleAssignment
17
+ - range:
18
+ start:
19
+ line: 8
20
+ character: 0
21
+ end:
22
+ line: 8
23
+ character: 17
24
+ severity: ERROR
25
+ message: |-
26
+ Cannot assign a value of type `(::String | nil)` to a variable of type `::Integer`
27
+ (::String | nil) <: ::Integer
28
+ ::String <: ::Integer
29
+ ::Object <: ::Integer
30
+ ::BasicObject <: ::Integer
31
+ code: Ruby::IncompatibleAssignment
@@ -0,0 +1,103 @@
1
+ ---
2
+ - file: a.rb
3
+ diagnostics:
4
+ - range:
5
+ start:
6
+ line: 6
7
+ character: 0
8
+ end:
9
+ line: 6
10
+ character: 12
11
+ severity: ERROR
12
+ message: |-
13
+ Cannot find compatible overloading of method `[]=` of type `::Array[::Integer]`
14
+ Method types:
15
+ def []=: (::int, ::Integer) -> ::Integer
16
+ | (::int, ::int, ::Integer) -> ::Integer
17
+ | (::int, ::int, ::Array[::Integer]) -> ::Array[::Integer]
18
+ | (::int, ::int, nil) -> nil
19
+ | (::Range[::Integer], ::Integer) -> ::Integer
20
+ | (::Range[::Integer], ::Array[::Integer]) -> ::Array[::Integer]
21
+ | (::Range[::Integer], nil) -> nil
22
+ code: Ruby::UnresolvedOverloading
23
+ - range:
24
+ start:
25
+ line: 12
26
+ character: 0
27
+ end:
28
+ line: 12
29
+ character: 8
30
+ severity: ERROR
31
+ message: |-
32
+ Cannot assign a value of type `::Integer` to a variable of type `::String`
33
+ ::Integer <: ::String
34
+ ::Numeric <: ::String
35
+ ::Object <: ::String
36
+ ::BasicObject <: ::String
37
+ code: Ruby::IncompatibleAssignment
38
+ - range:
39
+ start:
40
+ line: 18
41
+ character: 0
42
+ end:
43
+ line: 18
44
+ character: 8
45
+ severity: ERROR
46
+ message: |-
47
+ Cannot assign a value of type `::String` to a variable of type `::Integer`
48
+ ::String <: ::Integer
49
+ ::Object <: ::Integer
50
+ ::BasicObject <: ::Integer
51
+ code: Ruby::IncompatibleAssignment
52
+ - file: b.rb
53
+ diagnostics:
54
+ - range:
55
+ start:
56
+ line: 11
57
+ character: 0
58
+ end:
59
+ line: 11
60
+ character: 5
61
+ severity: ERROR
62
+ message: |-
63
+ Cannot assign a value of type `::Array[::Integer]` to a variable of type `::Array[::String]`
64
+ ::Array[::Integer] <: ::Array[::String]
65
+ ::Integer <: ::String
66
+ ::Numeric <: ::String
67
+ ::Object <: ::String
68
+ ::BasicObject <: ::String
69
+ code: Ruby::IncompatibleAssignment
70
+ - range:
71
+ start:
72
+ line: 12
73
+ character: 0
74
+ end:
75
+ line: 12
76
+ character: 5
77
+ severity: ERROR
78
+ message: |-
79
+ Cannot assign a value of type `::Array[::String]` to a variable of type `::Array[::Integer]`
80
+ ::Array[::String] <: ::Array[::Integer]
81
+ ::String <: ::Integer
82
+ ::Object <: ::Integer
83
+ ::BasicObject <: ::Integer
84
+ code: Ruby::IncompatibleAssignment
85
+ - file: c.rb
86
+ diagnostics:
87
+ - range:
88
+ start:
89
+ line: 6
90
+ character: 0
91
+ end:
92
+ line: 6
93
+ character: 7
94
+ severity: ERROR
95
+ message: |-
96
+ Cannot assign a value of type `::Array[::Integer]` to a variable of type `::Array[(::String | nil)]`
97
+ ::Array[::Integer] <: ::Array[(::String | nil)]
98
+ ::Integer <: (::String | nil)
99
+ ::Integer <: ::String
100
+ ::Numeric <: ::String
101
+ ::Object <: ::String
102
+ ::BasicObject <: ::String
103
+ code: Ruby::IncompatibleAssignment
@@ -0,0 +1,125 @@
1
+ ---
2
+ - file: a.rb
3
+ diagnostics:
4
+ - range:
5
+ start:
6
+ line: 8
7
+ character: 0
8
+ end:
9
+ line: 8
10
+ character: 9
11
+ severity: ERROR
12
+ message: |-
13
+ Cannot assign a value of type `::Integer` to a variable of type `::String`
14
+ ::Integer <: ::String
15
+ ::Numeric <: ::String
16
+ ::Object <: ::String
17
+ ::BasicObject <: ::String
18
+ code: Ruby::IncompatibleAssignment
19
+ - range:
20
+ start:
21
+ line: 10
22
+ character: 0
23
+ end:
24
+ line: 10
25
+ character: 17
26
+ severity: ERROR
27
+ message: |-
28
+ Cannot assign a value of type `::String` to a variable of type `::Integer`
29
+ ::String <: ::Integer
30
+ ::Object <: ::Integer
31
+ ::BasicObject <: ::Integer
32
+ code: Ruby::IncompatibleAssignment
33
+ - file: b.rb
34
+ diagnostics:
35
+ - range:
36
+ start:
37
+ line: 5
38
+ character: 2
39
+ end:
40
+ line: 5
41
+ character: 9
42
+ severity: ERROR
43
+ message: |-
44
+ Cannot break with a value of type `::Integer` because type `::Symbol` is assumed
45
+ ::Integer <: ::Symbol
46
+ ::Numeric <: ::Symbol
47
+ ::Object <: ::Symbol
48
+ ::BasicObject <: ::Symbol
49
+ code: Ruby::BreakTypeMismatch
50
+ - range:
51
+ start:
52
+ line: 10
53
+ character: 0
54
+ end:
55
+ line: 13
56
+ character: 3
57
+ severity: ERROR
58
+ message: |-
59
+ Cannot assign a value of type `(::Integer | ::Symbol)` to a variable of type `::String`
60
+ (::Integer | ::Symbol) <: ::String
61
+ ::Integer <: ::String
62
+ ::Numeric <: ::String
63
+ ::Object <: ::String
64
+ ::BasicObject <: ::String
65
+ code: Ruby::IncompatibleAssignment
66
+ - file: d.rb
67
+ diagnostics:
68
+ - range:
69
+ start:
70
+ line: 6
71
+ character: 0
72
+ end:
73
+ line: 6
74
+ character: 19
75
+ severity: ERROR
76
+ message: |-
77
+ Cannot assign a value of type `::Array[::String]` to a variable of type `::Array[::Float]`
78
+ ::Array[::String] <: ::Array[::Float]
79
+ ::String <: ::Float
80
+ ::Object <: ::Float
81
+ ::BasicObject <: ::Float
82
+ code: Ruby::IncompatibleAssignment
83
+ - range:
84
+ start:
85
+ line: 8
86
+ character: 0
87
+ end:
88
+ line: 8
89
+ character: 23
90
+ severity: ERROR
91
+ message: |-
92
+ Cannot assign a value of type `::Array[::String]` to a variable of type `::Array[::Float]`
93
+ ::Array[::String] <: ::Array[::Float]
94
+ ::String <: ::Float
95
+ ::Object <: ::Float
96
+ ::BasicObject <: ::Float
97
+ code: Ruby::IncompatibleAssignment
98
+ - range:
99
+ start:
100
+ line: 10
101
+ character: 0
102
+ end:
103
+ line: 10
104
+ character: 29
105
+ severity: ERROR
106
+ message: |-
107
+ Cannot find compatible overloading of method `map` of type `::Array[::Integer]`
108
+ Method types:
109
+ def map: [U] () { (::Integer) -> U } -> ::Array[U]
110
+ | () -> ::Enumerator[::Integer, ::Array[untyped]]
111
+ code: Ruby::UnresolvedOverloading
112
+ - range:
113
+ start:
114
+ line: 11
115
+ character: 0
116
+ end:
117
+ line: 11
118
+ character: 21
119
+ severity: ERROR
120
+ message: |-
121
+ Cannot find compatible overloading of method `map` of type `::Array[::Integer]`
122
+ Method types:
123
+ def map: [U] () { (::Integer) -> U } -> ::Array[U]
124
+ | () -> ::Enumerator[::Integer, ::Array[untyped]]
125
+ code: Ruby::UnresolvedOverloading