steep 1.4.0 → 1.5.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.vscode/steep-shared.code-snippets +41 -0
  4. data/CHANGELOG.md +37 -0
  5. data/Gemfile +2 -5
  6. data/Gemfile.lock +20 -17
  7. data/Gemfile.steep +1 -1
  8. data/Gemfile.steep.lock +6 -6
  9. data/Rakefile +198 -0
  10. data/Steepfile +3 -1
  11. data/lib/steep/ast/builtin.rb +9 -7
  12. data/lib/steep/ast/node/type_application.rb +13 -5
  13. data/lib/steep/ast/node/type_assertion.rb +28 -9
  14. data/lib/steep/ast/types/factory.rb +39 -7
  15. data/lib/steep/cli.rb +2 -1
  16. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  17. data/lib/steep/diagnostic/lsp_formatter.rb +3 -3
  18. data/lib/steep/diagnostic/ruby.rb +73 -12
  19. data/lib/steep/drivers/annotations.rb +1 -0
  20. data/lib/steep/drivers/check.rb +18 -13
  21. data/lib/steep/drivers/checkfile.rb +1 -1
  22. data/lib/steep/drivers/diagnostic_printer.rb +6 -4
  23. data/lib/steep/drivers/init.rb +2 -1
  24. data/lib/steep/drivers/print_project.rb +3 -1
  25. data/lib/steep/drivers/stats.rb +1 -1
  26. data/lib/steep/drivers/utils/driver_helper.rb +10 -8
  27. data/lib/steep/drivers/utils/jobs_option.rb +6 -1
  28. data/lib/steep/drivers/validate.rb +9 -5
  29. data/lib/steep/drivers/watch.rb +8 -3
  30. data/lib/steep/expectations.rb +144 -75
  31. data/lib/steep/index/signature_symbol_provider.rb +22 -13
  32. data/lib/steep/node_helper.rb +172 -0
  33. data/lib/steep/server/base_worker.rb +2 -1
  34. data/lib/steep/server/change_buffer.rb +17 -15
  35. data/lib/steep/server/interaction_worker.rb +20 -0
  36. data/lib/steep/server/lsp_formatter.rb +20 -1
  37. data/lib/steep/server/master.rb +51 -36
  38. data/lib/steep/server/type_check_worker.rb +18 -2
  39. data/lib/steep/server/worker_process.rb +19 -2
  40. data/lib/steep/services/completion_provider.rb +189 -3
  41. data/lib/steep/services/file_loader.rb +1 -1
  42. data/lib/steep/services/goto_service.rb +123 -27
  43. data/lib/steep/services/signature_help_provider.rb +1 -6
  44. data/lib/steep/signature/validator.rb +6 -1
  45. data/lib/steep/source.rb +165 -108
  46. data/lib/steep/subtyping/check.rb +5 -3
  47. data/lib/steep/subtyping/variable_variance.rb +11 -0
  48. data/lib/steep/thread_waiter.rb +35 -0
  49. data/lib/steep/type_construction.rb +416 -171
  50. data/lib/steep/type_inference/block_params.rb +50 -9
  51. data/lib/steep/type_inference/context.rb +4 -0
  52. data/lib/steep/type_inference/context_array.rb +6 -6
  53. data/lib/steep/type_inference/logic_type_interpreter.rb +202 -68
  54. data/lib/steep/typing.rb +5 -4
  55. data/lib/steep/version.rb +1 -1
  56. data/lib/steep.rb +21 -14
  57. data/sample/Steepfile +1 -0
  58. data/sig/shims/bundler.rbs +3 -0
  59. data/sig/shims/language-server_protocol.rbs +151 -10
  60. data/sig/shims/parser/nodes.rbs +210 -0
  61. data/sig/shims/parser.rbs +10 -0
  62. data/sig/steep/ast/builtin.rbs +2 -2
  63. data/sig/steep/ast/node/type_application.rbs +2 -2
  64. data/sig/steep/ast/node/type_assertion.rbs +8 -2
  65. data/sig/steep/ast/types/factory.rbs +28 -1
  66. data/sig/steep/diagnostic/deprecated/else_on_exhaustive_case.rbs +13 -0
  67. data/sig/steep/diagnostic/lsp_formatter.rbs +5 -2
  68. data/sig/steep/diagnostic/ruby.rbs +76 -6
  69. data/sig/steep/drivers/annotations.rbs +5 -5
  70. data/sig/steep/drivers/check.rbs +11 -11
  71. data/sig/steep/drivers/diagnostic_printer.rbs +9 -9
  72. data/sig/steep/drivers/init.rbs +6 -6
  73. data/sig/steep/drivers/print_project.rbs +4 -4
  74. data/sig/steep/drivers/utils/driver_helper.rbs +8 -6
  75. data/sig/steep/drivers/validate.rbs +4 -4
  76. data/sig/steep/drivers/watch.rbs +1 -1
  77. data/sig/steep/expectations.rbs +72 -0
  78. data/sig/steep/index/signature_symbol_provider.rbs +22 -10
  79. data/sig/steep/interface/block.rbs +2 -0
  80. data/sig/steep/interface/function.rbs +2 -2
  81. data/sig/steep/node_helper.rbs +56 -0
  82. data/sig/steep/path_helper.rbs +1 -1
  83. data/sig/steep/project/options.rbs +1 -1
  84. data/sig/steep/range_extension.rbs +2 -2
  85. data/sig/steep/server/master.rbs +16 -2
  86. data/sig/steep/server/type_check_worker.rbs +5 -1
  87. data/sig/steep/server/worker_process.rbs +5 -1
  88. data/sig/steep/services/completion_provider.rbs +31 -1
  89. data/sig/steep/services/goto_service.rbs +80 -19
  90. data/sig/steep/source.rbs +27 -4
  91. data/sig/steep/subtyping/variable_variance.rbs +9 -9
  92. data/sig/steep/thread_waiter.rbs +13 -0
  93. data/sig/steep/type_construction.rbs +26 -9
  94. data/sig/steep/type_inference/block_params.rbs +13 -1
  95. data/sig/steep/type_inference/context.rbs +5 -1
  96. data/sig/steep/type_inference/context_array.rbs +16 -15
  97. data/sig/steep/type_inference/logic_type_interpreter.rbs +36 -6
  98. data/sig/steep/type_inference/type_env_builder.rbs +4 -0
  99. data/sig/steep/typing.rbs +22 -20
  100. data/sig/steep.rbs +14 -13
  101. data/smoke/and/a.rb +1 -1
  102. data/smoke/and/test_expectations.yml +5 -7
  103. data/smoke/diagnostics/incompatible_annotation.rb +1 -1
  104. data/smoke/diagnostics/test_expectations.yml +2 -2
  105. data/smoke/enumerator/a.rb +0 -7
  106. data/smoke/enumerator/b.rb +0 -2
  107. data/smoke/enumerator/test_expectations.yml +17 -105
  108. data/smoke/lambda/a.rb +0 -5
  109. data/smoke/lambda/test_expectations.yml +0 -22
  110. data/smoke/type_case/test_expectations.yml +10 -0
  111. data/steep.gemspec +2 -2
  112. metadata +16 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d0c3f3309cc8169ca1616f43b6bfcaf977339107d6e6e14f7c256d71921b9455
4
- data.tar.gz: 0a85c1429383a0321fe2932befbd880942c00df1e788913a4f5c2e3d8abd9479
3
+ metadata.gz: 18cb0e6ad22037ae5eef2ace2a587c6a11bd3ce8bf4b7a151783fe26155f81ad
4
+ data.tar.gz: ecdcae004ee4b0c55b0cb7253011bee234cd5a521c8aa70735454ecd1f08137b
5
5
  SHA512:
6
- metadata.gz: 8ce071dd59d2a6e4c21c9c2114d33603e4628052074b7a6f8500f8e4380ca53dfdd77baac210c1ced711eeccc7da94257baceefdafe5633cbd3932687dab6e8c
7
- data.tar.gz: db71a9ab6ca415b266e62b7ef17a34e88dd4135326bae512fcf8fe8051610a6c2259bcf11773f09ebb8192958d96f03154a5a1be955beddc7088f2bfc0bf57a5
6
+ metadata.gz: cd262e3d39a04dd6a728cbecaa5bd09af17094b8db23877a84e99c2b0a101cb2d78562988779a08c04db3518e653abfe59673a5463b317c0bec948f618ae64c8
7
+ data.tar.gz: fce4bb70eefb5dc1c7bc86f2b82cbd898f5bf1a90b0342f19e8af1540d387cc67bc6fd299fb7494c0a69cd15953eaa17f7e1ae631f51358f6f87b95a1296b183
data/.gitignore CHANGED
@@ -10,3 +10,5 @@
10
10
  /lib/steep/parser.rb
11
11
  /log
12
12
  /.gem_rbs_collection
13
+ /.vscode/*
14
+ !/.vscode/steep-shared.code-snippets
@@ -0,0 +1,41 @@
1
+ {
2
+ // Place your steep workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
3
+ // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
4
+ // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
5
+ // used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
6
+ // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
7
+ // Placeholders with the same ids are connected.
8
+ // Example:
9
+ // "Print to console": {
10
+ // "scope": "javascript,typescript",
11
+ // "prefix": "log",
12
+ // "body": [
13
+ // "console.log('$1');",
14
+ // "$2"
15
+ // ],
16
+ // "description": "Log output to console"
17
+ // }
18
+
19
+ "Add type_check_test case": {
20
+ "scope": "ruby",
21
+ "body": [
22
+ "def test_${1:name}",
23
+ " run_type_check_test(",
24
+ " signatures: {",
25
+ " \"a.rbs\" => <<~RBS",
26
+ " ${2:rbs}",
27
+ " RBS",
28
+ " },",
29
+ " code: {",
30
+ " \"a.rb\" => <<~RUBY",
31
+ " ${3:ruby code}",
32
+ " RUBY",
33
+ " },",
34
+ " expectations: <<~YAML",
35
+ " YAML",
36
+ " )",
37
+ "end",
38
+ ],
39
+ "description": "Insert a new test case"
40
+ }
41
+ }
data/CHANGELOG.md CHANGED
@@ -2,6 +2,43 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.5.0.pre.1 (2023-07-05)
6
+
7
+ ### Type checker core
8
+
9
+ * Refactor occurrence typing ([#831](https://github.com/soutaro/steep/pull/831))
10
+ * Better flow-sensitive typing ([#825](https://github.com/soutaro/steep/pull/825))
11
+ * Fix interface type inference ([#816](https://github.com/soutaro/steep/pull/816))
12
+ * Make `nth_ref` and `:back_ref` nodes optional ([#815](https://github.com/soutaro/steep/pull/815))
13
+ * Add new diagnostic for setter methods ([#809](https://github.com/soutaro/steep/pull/809))
14
+ * Better hint type handling given to lambda ([#807](https://github.com/soutaro/steep/pull/807))
15
+ * Fix type assertion parsing error ([#805](https://github.com/soutaro/steep/pull/805))
16
+ * Distribute `untyped` to block params ([#798](https://github.com/soutaro/steep/pull/798))
17
+ * Should escape underscore for method name ([#770](https://github.com/soutaro/steep/pull/770))
18
+
19
+ ### Commandline tool
20
+
21
+ * Ensure at least one type check worker runs ([#814](https://github.com/soutaro/steep/pull/814))
22
+ * Improve worker process handling ([#801](https://github.com/soutaro/steep/pull/801))
23
+ * Add `Steep::Diagnostic::Ruby.silent` template to suppress all warnings ([#800](https://github.com/soutaro/steep/pull/800))
24
+ * Suppress `UnsupportedSyntax` warnings by default ([#799](https://github.com/soutaro/steep/pull/799))
25
+ * Infer method return types using hint ([#789](https://github.com/soutaro/steep/pull/789))
26
+ * Handling splat nodes in `super` ([#788](https://github.com/soutaro/steep/pull/788))
27
+ * Add handling splat node in tuple type checking ([#786](https://github.com/soutaro/steep/pull/786))
28
+ * Let `return` have multiple values ([#785](https://github.com/soutaro/steep/pull/785))
29
+ * Remove trailing extra space from Steepfile generated by steep init ([#774](https://github.com/soutaro/steep/pull/774))
30
+
31
+ ### Language server
32
+
33
+ * Fix signature help is not shown for the optional chaining (&.) ([#832](https://github.com/soutaro/steep/pull/832))
34
+ * Completion in annotations ([#818](https://github.com/soutaro/steep/pull/818))
35
+ * Implement *go to type definition* ([#784](https://github.com/soutaro/steep/pull/784))
36
+
37
+ ### Miscellaneous
38
+
39
+ * Typecheck sources ([#820](https://github.com/soutaro/steep/pull/820))
40
+ * Relax concurrent-ruby requirement ([#812](https://github.com/soutaro/steep/pull/812))
41
+
5
42
  ## 1.4.0 (2023-04-25)
6
43
 
7
44
  ### Type checker core
data/Gemfile CHANGED
@@ -3,8 +3,6 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in steep.gemspec
4
4
  gemspec
5
5
 
6
- gem "rbs", "~> 3.0.0"
7
-
8
6
  gem "rake"
9
7
  gem "minitest", "~> 5.18"
10
8
  gem "minitest-hooks"
@@ -13,7 +11,6 @@ group :stackprof, optional: true do
13
11
  end
14
12
  gem 'minitest-slow_test'
15
13
 
16
- group :ide, optional: true do
17
- gem "ruby-debug-ide"
18
- gem "debase", ">= 0.2.5.beta2"
14
+ group :development do
15
+ gem "ruby-lsp", require: false
19
16
  end
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- steep (1.4.0)
4
+ steep (1.5.0.pre.1)
5
5
  activesupport (>= 5.1)
6
- concurrent-ruby (>= 1.2.2)
6
+ concurrent-ruby (>= 1.1.10)
7
7
  csv (>= 3.0.9)
8
8
  fileutils (>= 1.1.0)
9
9
  json (>= 2.1.0)
@@ -12,7 +12,7 @@ PATH
12
12
  logger (>= 1.3.0)
13
13
  parser (>= 3.1)
14
14
  rainbow (>= 2.2.2, < 4.0)
15
- rbs (>= 2.8.0)
15
+ rbs (>= 3.1.0)
16
16
  securerandom (>= 0.1)
17
17
  strscan (>= 1.0.0)
18
18
  terminal-table (>= 2, < 4)
@@ -20,20 +20,17 @@ PATH
20
20
  GEM
21
21
  remote: https://rubygems.org/
22
22
  specs:
23
- activesupport (7.0.4.3)
23
+ activesupport (7.0.6)
24
24
  concurrent-ruby (~> 1.0, >= 1.0.2)
25
25
  i18n (>= 1.6, < 2)
26
26
  minitest (>= 5.1)
27
27
  tzinfo (~> 2.0)
28
28
  ast (2.4.2)
29
29
  concurrent-ruby (1.2.2)
30
- csv (3.2.6)
31
- debase (0.2.5.beta2)
32
- debase-ruby_core_source (>= 0.10.12)
33
- debase-ruby_core_source (3.2.0)
30
+ csv (3.2.7)
34
31
  ffi (1.15.5)
35
32
  fileutils (1.7.1)
36
- i18n (1.12.0)
33
+ i18n (1.14.1)
37
34
  concurrent-ruby (~> 1.0)
38
35
  json (2.6.3)
39
36
  language_server-protocol (3.17.0.3)
@@ -41,24 +38,32 @@ GEM
41
38
  rb-fsevent (~> 0.10, >= 0.10.3)
42
39
  rb-inotify (~> 0.9, >= 0.9.10)
43
40
  logger (1.5.3)
44
- minitest (5.18.0)
41
+ minitest (5.18.1)
45
42
  minitest-hooks (1.5.0)
46
43
  minitest (> 5.3)
47
44
  minitest-slow_test (0.2.0)
48
45
  minitest (>= 5.0)
49
- parser (3.2.2.1)
46
+ parser (3.2.2.3)
50
47
  ast (~> 2.4.1)
48
+ racc
49
+ prettier_print (1.2.1)
50
+ racc (1.7.1)
51
51
  rainbow (3.1.1)
52
52
  rake (13.0.6)
53
53
  rb-fsevent (0.11.2)
54
54
  rb-inotify (0.10.1)
55
55
  ffi (~> 1.0)
56
- rbs (3.0.4)
57
- ruby-debug-ide (0.7.3)
58
- rake (>= 0.8.1)
56
+ rbs (3.1.0)
57
+ ruby-lsp (0.5.1)
58
+ language_server-protocol (~> 3.17.0)
59
+ sorbet-runtime
60
+ syntax_tree (>= 6.1.1, < 7)
59
61
  securerandom (0.2.2)
62
+ sorbet-runtime (0.5.10832)
60
63
  stackprof (0.2.25)
61
64
  strscan (3.0.6)
65
+ syntax_tree (6.1.1)
66
+ prettier_print (>= 1.2.0)
62
67
  terminal-table (3.0.2)
63
68
  unicode-display_width (>= 1.1.1, < 3)
64
69
  tzinfo (2.0.6)
@@ -69,13 +74,11 @@ PLATFORMS
69
74
  ruby
70
75
 
71
76
  DEPENDENCIES
72
- debase (>= 0.2.5.beta2)
73
77
  minitest (~> 5.18)
74
78
  minitest-hooks
75
79
  minitest-slow_test
76
80
  rake
77
- rbs (~> 3.0.0)
78
- ruby-debug-ide
81
+ ruby-lsp
79
82
  stackprof
80
83
  steep!
81
84
 
data/Gemfile.steep CHANGED
@@ -1,3 +1,3 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'steep', '~> 1.4.0.dev', require: false
3
+ gem 'steep', require: false
data/Gemfile.steep.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
- activesupport (7.0.4.3)
4
+ activesupport (7.0.5)
5
5
  concurrent-ruby (~> 1.0, >= 1.0.2)
6
6
  i18n (>= 1.6, < 2)
7
7
  minitest (>= 5.1)
@@ -11,7 +11,7 @@ GEM
11
11
  csv (3.2.6)
12
12
  ffi (1.15.5)
13
13
  fileutils (1.7.1)
14
- i18n (1.12.0)
14
+ i18n (1.13.0)
15
15
  concurrent-ruby (~> 1.0)
16
16
  json (2.6.3)
17
17
  language_server-protocol (3.17.0.3)
@@ -20,15 +20,15 @@ GEM
20
20
  rb-inotify (~> 0.9, >= 0.9.10)
21
21
  logger (1.5.3)
22
22
  minitest (5.18.0)
23
- parser (3.2.2.0)
23
+ parser (3.2.2.1)
24
24
  ast (~> 2.4.1)
25
25
  rainbow (3.1.1)
26
26
  rb-fsevent (0.11.2)
27
27
  rb-inotify (0.10.1)
28
28
  ffi (~> 1.0)
29
- rbs (3.0.4)
29
+ rbs (3.1.0)
30
30
  securerandom (0.2.2)
31
- steep (1.4.0.dev.5)
31
+ steep (1.4.0)
32
32
  activesupport (>= 5.1)
33
33
  concurrent-ruby (>= 1.2.2)
34
34
  csv (>= 3.0.9)
@@ -55,7 +55,7 @@ PLATFORMS
55
55
  arm64-darwin-22
56
56
 
57
57
  DEPENDENCIES
58
- steep (~> 1.4.0.dev)
58
+ steep
59
59
 
60
60
  BUNDLED WITH
61
61
  2.3.15
data/Rakefile CHANGED
@@ -20,3 +20,201 @@ namespace :test do
20
20
  sh "ruby", "bin/output_test.rb"
21
21
  end
22
22
  end
23
+
24
+ Rake::Task[:release].enhance do
25
+ Rake::Task[:"release:note"].invoke
26
+ Rake::Task[:"release:github"].invoke
27
+ Rake::Task[:"release:release-prs"].invoke
28
+ end
29
+
30
+ desc "Generate changelog template from GH pull requests"
31
+ task :changelog do
32
+ major, minor, patch, pre = Steep::VERSION.split(".", 4)
33
+ major = major.to_i
34
+ minor = minor.to_i
35
+ patch = patch.to_i
36
+
37
+ if patch == 0
38
+ milestone = "Steep #{major}.#{minor}"
39
+ else
40
+ milestone = "Steep #{major}.#{minor}.x"
41
+ end
42
+
43
+ puts "🔍 Finding pull requests that is associated to milestone `#{milestone}`..."
44
+
45
+ command = [
46
+ "gh",
47
+ "pr",
48
+ "list",
49
+ "--json",
50
+ "url,title,number",
51
+ "--search" ,
52
+ "milestone:\"#{milestone}\" is:merged sort:updated-desc -label:Released"
53
+ ]
54
+
55
+ require "open3"
56
+ output, status = Open3.capture2(*command)
57
+ raise status.inspect unless status.success?
58
+
59
+ require "json"
60
+ json = JSON.parse(output, symbolize_names: true)
61
+
62
+ unless json.empty?
63
+ puts
64
+ json.each do |line|
65
+ puts "* #{line[:title]} ([##{line[:number]}](#{line[:url]}))"
66
+ end
67
+ else
68
+ puts " (🤑 There is no *unreleased* pull request associated to the milestone.)"
69
+ end
70
+ end
71
+
72
+ namespace :release do
73
+ desc "Ensure release note"
74
+ task :note do
75
+ version = Gem::Version.new(Steep::VERSION)
76
+ major, minor, patch, pre = Steep::VERSION.split(".", 4)
77
+ major = major.to_i
78
+ minor = minor.to_i
79
+ patch = patch.to_i
80
+
81
+ wiki_url = "https://github.com/soutaro/steep/wiki/Release-Note-#{major}.#{minor}"
82
+
83
+ puts "🧐 Checking if Release note page already exists..."
84
+
85
+ unless `curl --silent -o/dev/null --head #{wiki_url} -w '%{http_code}'` == "200"
86
+ pre_flag = version.prerelease? ? " --pre" : ""
87
+ pre_requirement = version.prerelease? ? ", '~> #{major}.#{minor}.#{patch}.#{pre}'" : ""
88
+
89
+ puts "----"
90
+
91
+ puts <<~PREFIX if patch
92
+ **The latest version of Steep #{major}.#{minor} is `#{pre}`.**
93
+
94
+ PREFIX
95
+
96
+ puts <<~TEMPLATE
97
+ Some of the highlights in Steep #{major}.#{minor} are:
98
+
99
+ * New feature 1 (URL)
100
+ * New feature 2 (URL)
101
+ * New feature 3 (URL)
102
+
103
+ You can install it with `$ gem install steep#{pre_flag}` or using Bundler.
104
+
105
+ ```rb
106
+ gem 'steep', require: false#{pre_requirement}
107
+ ```
108
+
109
+ See the [CHANGELOG](https://github.com/soutaro/steep/blob/master/CHANGELOG.md) for the details.
110
+
111
+ ## New feature 1
112
+
113
+ ## New feature 2
114
+
115
+ ## New feature 3
116
+
117
+ ## Diagnostics updates
118
+
119
+ ## Updating Steep
120
+
121
+ TEMPLATE
122
+ puts "----"
123
+ puts
124
+
125
+ puts " ⏩️ Create the release note with the template: #{wiki_url}"
126
+ else
127
+ if patch == 0 || version.prerelease?
128
+ puts " ⏩️ Open the release note and update it at: #{wiki_url}"
129
+ else
130
+ puts " ✅ Release note is ready!"
131
+ end
132
+ end
133
+ puts
134
+ end
135
+
136
+ desc "Create GitHub release automatically"
137
+ task :github do
138
+ version = Gem::Version.new(Steep::VERSION)
139
+ major, minor, patch, *_ = Steep::VERSION.split(".")
140
+ major = major.to_i
141
+ minor = minor.to_i
142
+ patch = patch.to_i
143
+
144
+ puts "✏️ Making a draft release on GitHub..."
145
+
146
+ content = File.read(File.join(__dir__, "CHANGELOG.md"))
147
+ changelog = content.scan(/^## \d.*?(?=^## \d)/m)[0]
148
+ changelog = changelog.sub(/^.*\n^.*\n/, "").rstrip
149
+
150
+ notes = <<NOTES
151
+ [Release note](https://github.com/soutaro/steep/wiki/Release-Note-#{major}.#{minor})
152
+
153
+ #{changelog}
154
+ NOTES
155
+
156
+ command = [
157
+ "gh",
158
+ "release",
159
+ "create",
160
+ "--draft",
161
+ "v#{Steep::VERSION}",
162
+ "--title=#{Steep::VERSION}",
163
+ "--notes=#{notes}"
164
+ ]
165
+
166
+ if version.prerelease?
167
+ command << "--prerelease"
168
+ end
169
+
170
+ require "open3"
171
+ output, status = Open3.capture2(*command)
172
+ if status.success?
173
+ puts " ⏩️ Done! Open #{output.chomp} and publish the release!"
174
+ puts
175
+ end
176
+ end
177
+
178
+ desc "Add `Released` labels to pull requests associated to the version"
179
+ task "release-prs" do
180
+ major, minor, patch, pre = Steep::VERSION.split(".", 4)
181
+ major = major.to_i
182
+ minor = minor.to_i
183
+ patch = patch.to_i
184
+
185
+ if patch == 0
186
+ milestone = "Steep #{major}.#{minor}"
187
+ else
188
+ milestone = "Steep #{major}.#{minor}.x"
189
+ end
190
+
191
+ puts "🔍 Finding pull requests that is associated to milestone `#{milestone}`..."
192
+
193
+ command = [
194
+ "gh",
195
+ "pr",
196
+ "list",
197
+ "--json",
198
+ "url,title,number",
199
+ "--search" ,
200
+ "milestone:\"#{milestone}\" is:merged sort:updated-desc -label:Released"
201
+ ]
202
+
203
+ require "open3"
204
+ output, status = Open3.capture2(*command)
205
+ raise status.inspect unless status.success?
206
+
207
+ require "json"
208
+ json = JSON.parse(output, symbolize_names: true)
209
+
210
+ puts " ✅ Found #{json.size} PRs..."
211
+
212
+ json.each do |pr|
213
+ puts "🧐 Updating #{pr[:url]}..."
214
+ output, status = Open3.capture2("gh", "pr", "edit", pr[:number].to_s, "--add-label", "Released")
215
+ raise status.inspect unless status.success?
216
+ puts " ✅ Done!"
217
+ sleep 0.5
218
+ end
219
+ end
220
+ end
data/Steepfile CHANGED
@@ -2,6 +2,8 @@ D = Steep::Diagnostic
2
2
 
3
3
  target :app do
4
4
  check "lib"
5
+ ignore "lib/steep/shims"
6
+
5
7
  signature "sig"
6
8
 
7
9
  collection_config "rbs_collection.steep.yaml"
@@ -15,7 +17,7 @@ target :app do
15
17
 
16
18
  definition = Bundler::Definition.build(Pathname("Gemfile"), Pathname("Gemfile.lock"), nil)
17
19
  rbs_dep = definition.dependencies.find {|dep| dep.name == "rbs" }
18
- if (source = rbs_dep.source).is_a?(Bundler::Source::Path)
20
+ if (source = rbs_dep&.source).is_a?(Bundler::Source::Path)
19
21
  unless Pathname(tmp_rbs_dir).exist?
20
22
  FileUtils.ln_s(Pathname.pwd + source.path + "sig", tmp_rbs_dir, force: true)
21
23
  end
@@ -29,20 +29,22 @@ module Steep
29
29
  if type.is_a?(Types::Name::Instance)
30
30
  if args
31
31
  arity == args.size or raise "Malformed instance type: name=#{module_name}, args=#{args}"
32
- type.name == module_name && type.args == args
32
+ if type.name == module_name && type.args == args
33
+ type
34
+ end
33
35
  else
34
- type.name == module_name && type.args.size == arity
36
+ if type.name == module_name && type.args.size == arity
37
+ type
38
+ end
35
39
  end
36
- else
37
- false
38
40
  end
39
41
  end
40
42
 
41
43
  def module_type?(type)
42
44
  if type.is_a?(Types::Name::Singleton)
43
- type.name == module_name
44
- else
45
- false
45
+ if type.name == module_name
46
+ type
47
+ end
46
48
  end
47
49
  end
48
50
  end
@@ -24,7 +24,7 @@ module Steep
24
24
  location.source
25
25
  end
26
26
 
27
- def types(context, factory, type_vars)
27
+ def types(context, subtyping, type_vars)
28
28
  # @type var types: Array[Types::t]
29
29
  types = []
30
30
 
@@ -32,8 +32,16 @@ module Steep
32
32
 
33
33
  while true
34
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)
35
+
36
+ validator = Signature::Validator.new(checker: subtyping)
37
+ validator.validate_type(ty)
38
+
39
+ if validator.has_error?
40
+ return
41
+ end
42
+
43
+ ty = subtyping.factory.type(ty)
44
+ types << subtyping.factory.absolute_type(ty, context: context)
37
45
 
38
46
  match = RBS::Location.new(loc.buffer, ty.location.end_pos, type_location.end_pos).source.match(/\A\s*,\s*/) or break
39
47
  offset = match.length
@@ -45,8 +53,8 @@ module Steep
45
53
  exn
46
54
  end
47
55
 
48
- def types?(context, factory, type_vars)
49
- case types = types(context, factory, type_vars)
56
+ def types?(context, subtyping, type_vars)
57
+ case types = types(context, subtyping, type_vars)
50
58
  when RBS::ParsingError
51
59
  nil
52
60
  else
@@ -16,10 +16,15 @@ module Steep
16
16
  location.start_line
17
17
  end
18
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)
19
+ def type(context, subtyping, type_vars)
20
+ if ty = RBS::Parser.parse_type(type_location.buffer, range: type_location.range, variables: type_vars, require_eof: true)
21
+ validator = Signature::Validator.new(checker: subtyping)
22
+ validator.validate_type(ty)
23
+
24
+ unless validator.has_error?
25
+ ty = subtyping.factory.type(ty)
26
+ subtyping.factory.absolute_type(ty, context: context)
27
+ end
23
28
  else
24
29
  nil
25
30
  end
@@ -27,9 +32,18 @@ module Steep
27
32
  exn
28
33
  end
29
34
 
30
- def type?(context, factory, type_vars)
31
- case type = type(context, factory, type_vars)
32
- when RBS::ParsingError
35
+ def type_syntax?
36
+ RBS::Parser.parse_type(type_location.buffer, range: type_location.range, variables: [], require_eof: true)
37
+ true
38
+ rescue::RBS::ParsingError
39
+ false
40
+ end
41
+
42
+ def type?(context, subtyping, type_vars)
43
+ type = type(context, subtyping, type_vars)
44
+
45
+ case type
46
+ when RBS::ParsingError, nil
33
47
  nil
34
48
  else
35
49
  type
@@ -46,8 +60,13 @@ module Steep
46
60
  end
47
61
 
48
62
  def self.parse(location)
49
- if location.source =~/\A:\s*(.+)/
50
- TypeAssertion.new(location)
63
+ source = location.source.strip
64
+
65
+ if source =~/\A:\s*(.+)/
66
+ assertion = TypeAssertion.new(location)
67
+ if assertion.type_syntax?
68
+ assertion
69
+ end
51
70
  end
52
71
  end
53
72
  end
@@ -348,8 +348,15 @@ module Steep
348
348
  acc
349
349
  end
350
350
 
351
- def unwrap_optional(type)
351
+ def partition_union(type)
352
352
  case type
353
+ when AST::Types::Name::Alias
354
+ unfold = expand_alias(type)
355
+ if unfold == type
356
+ [type, type]
357
+ else
358
+ partition_union(unfold)
359
+ end
353
360
  when AST::Types::Union
354
361
  falsy_types, truthy_types = type.types.partition do |type|
355
362
  (type.is_a?(AST::Types::Literal) && type.value == false) ||
@@ -357,15 +364,40 @@ module Steep
357
364
  end
358
365
 
359
366
  [
360
- AST::Types::Union.build(types: truthy_types),
361
- AST::Types::Union.build(types: falsy_types)
367
+ truthy_types.empty? ? nil : AST::Types::Union.build(types: truthy_types),
368
+ falsy_types.empty? ? nil : AST::Types::Union.build(types: falsy_types)
362
369
  ]
363
- when AST::Types::Name::Alias
364
- unwrap_optional(expand_alias(type))
365
- when AST::Types::Boolean
370
+ when AST::Types::Any, AST::Types::Boolean
366
371
  [type, type]
372
+ when AST::Types::Nil
373
+ [nil, type]
374
+ when AST::Types::Literal
375
+ if type.value == false
376
+ [nil, type]
377
+ else
378
+ [type, nil]
379
+ end
380
+ else
381
+ [type, nil]
382
+ end
383
+ end
384
+
385
+ def unwrap_optional(type)
386
+ case type
387
+ when AST::Types::Union
388
+ unwrap = type.types.filter_map do |type|
389
+ unless type.is_a?(AST::Types::Nil)
390
+ type
391
+ end
392
+ end
393
+
394
+ unless unwrap.empty?
395
+ AST::Types::Union.build(types: unwrap)
396
+ end
397
+ when AST::Types::Nil
398
+ nil
367
399
  else
368
- [type, AST::Types::Bot.new()]
400
+ type
369
401
  end
370
402
  end
371
403