steep-relaxed 1.9.4.3 → 2.0.0.0.beta1
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 +4 -4
- data/CHANGELOG.md +143 -0
- data/CLAUDE.md +114 -0
- data/README.md +1 -1
- data/Rakefile +35 -0
- data/Steepfile +15 -12
- data/lib/steep/annotation_parser.rb +5 -1
- data/lib/steep/annotations_helper.rb +53 -0
- data/lib/steep/ast/ignore.rb +3 -4
- data/lib/steep/ast/node/type_application.rb +22 -16
- data/lib/steep/ast/node/type_assertion.rb +7 -4
- data/lib/steep/ast/types/factory.rb +3 -2
- data/lib/steep/cli.rb +348 -25
- data/lib/steep/daemon/configuration.rb +19 -0
- data/lib/steep/daemon/server.rb +476 -0
- data/lib/steep/daemon.rb +201 -0
- data/lib/steep/diagnostic/lsp_formatter.rb +17 -3
- data/lib/steep/diagnostic/ruby.rb +83 -8
- data/lib/steep/diagnostic/signature.rb +78 -7
- data/lib/steep/drivers/check.rb +304 -141
- data/lib/steep/drivers/diagnostic_printer/base_formatter.rb +19 -0
- data/lib/steep/drivers/diagnostic_printer/code_formatter.rb +95 -0
- data/lib/steep/drivers/diagnostic_printer/github_actions_formatter.rb +44 -0
- data/lib/steep/drivers/diagnostic_printer.rb +9 -86
- data/lib/steep/drivers/langserver.rb +4 -1
- data/lib/steep/drivers/print_project.rb +9 -10
- data/lib/steep/drivers/query.rb +102 -0
- data/lib/steep/drivers/start_server.rb +19 -0
- data/lib/steep/drivers/stop_server.rb +20 -0
- data/lib/steep/drivers/watch.rb +2 -2
- data/lib/steep/drivers/worker.rb +2 -0
- data/lib/steep/index/rbs_index.rb +38 -13
- data/lib/steep/index/signature_symbol_provider.rb +24 -3
- data/lib/steep/interface/builder.rb +50 -17
- data/lib/steep/interface/shape.rb +13 -5
- data/lib/steep/locator.rb +377 -0
- data/lib/steep/project/dsl.rb +26 -5
- data/lib/steep/project/group.rb +8 -2
- data/lib/steep/project/target.rb +16 -2
- data/lib/steep/project.rb +21 -2
- data/lib/steep/server/base_worker.rb +2 -2
- data/lib/steep/server/change_buffer.rb +2 -1
- data/lib/steep/server/custom_methods.rb +24 -0
- data/lib/steep/server/inline_source_change_detector.rb +94 -0
- data/lib/steep/server/interaction_worker.rb +84 -80
- data/lib/steep/server/lsp_formatter.rb +48 -12
- data/lib/steep/server/master.rb +201 -23
- data/lib/steep/server/target_group_files.rb +124 -151
- data/lib/steep/server/type_check_controller.rb +276 -123
- data/lib/steep/server/type_check_worker.rb +149 -2
- data/lib/steep/server/worker_process.rb +31 -20
- data/lib/steep/services/completion_provider/rbs.rb +74 -0
- data/lib/steep/services/completion_provider/ruby.rb +652 -0
- data/lib/steep/services/completion_provider/type_name.rb +243 -0
- data/lib/steep/services/completion_provider.rb +48 -661
- data/lib/steep/services/content_change.rb +14 -1
- data/lib/steep/services/file_loader.rb +4 -2
- data/lib/steep/services/goto_service.rb +271 -68
- data/lib/steep/services/hover_provider/content.rb +67 -0
- data/lib/steep/services/hover_provider/rbs.rb +8 -9
- data/lib/steep/services/hover_provider/ruby.rb +123 -64
- data/lib/steep/services/hover_provider/singleton_methods.rb +4 -0
- data/lib/steep/services/signature_service.rb +131 -56
- data/lib/steep/services/type_check_service.rb +72 -27
- data/lib/steep/signature/validator.rb +79 -15
- data/lib/steep/source/ignore_ranges.rb +14 -4
- data/lib/steep/source.rb +18 -4
- data/lib/steep/subtyping/check.rb +5 -6
- data/lib/steep/tagged_logging.rb +39 -0
- data/lib/steep/type_construction.rb +263 -57
- data/lib/steep/type_inference/block_params.rb +7 -7
- data/lib/steep/type_inference/context.rb +8 -2
- data/lib/steep/type_inference/logic_type_interpreter.rb +98 -18
- data/lib/steep/type_inference/method_call.rb +9 -3
- data/lib/steep/type_inference/type_env.rb +1 -1
- data/lib/steep/typing.rb +0 -2
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +51 -31
- data/manual/ruby-diagnostics.md +113 -0
- data/sample/Steepfile +1 -2
- data/sample/lib/conference.rb +1 -0
- data/sample/lib/deprecated.rb +13 -0
- data/sample/lib/inline.rb +43 -0
- data/sample/sig/deprecated.rbs +16 -0
- data/sample/sig/generics.rbs +3 -0
- data/steep-relaxed.gemspec +12 -11
- metadata +121 -20
- data/lib/steep/services/type_name_completion.rb +0 -236
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf5a5feae44a03f61bc114e4e4fe1de58935bc27843fc9045d7346327a836094
|
|
4
|
+
data.tar.gz: d81ebcda41a90a75d91d46a977ca7c463c75930d89be38834d19be0ce782fea1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 841398130d2c8acc7b526cd9f5f6256fbbb384838761df34edaab396a622917604bcc53ba1c97e3203c1448946b1f4ef1d5b4ee53f0c406d89afb1417ef9f34a
|
|
7
|
+
data.tar.gz: 0e910c89be4bb2a820db10a634b0fedee8f413e4bc1436f69a602e19082bc030a43ea64b41e57bdfe2f381fb4861520079c8b1d024f8bd215c271c05aea95a1e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,148 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 2.0.0 (2026-04-14)
|
|
4
|
+
|
|
5
|
+
### Summary
|
|
6
|
+
|
|
7
|
+
Steep 2.0 introduces three major new features.
|
|
8
|
+
|
|
9
|
+
* **Inline RBS Declaration (Experimental)**: Files configured with `check(inline: true)` can now have RBS type declarations written directly in Ruby code. Supports method types, `attr_*`, instance variables, constants, mixins, inheritance, and more, with editor integration for completion, hover, and go-to-definition.
|
|
10
|
+
* **`steep server` command**: A daemon server that persists the RBS environment. By connecting to the daemon during `steep check`, it skips RBS environment setup and speeds up type checking.
|
|
11
|
+
* **`steep query` command**: Query type information from the daemon server. `steep query hover` retrieves hover information and `steep query definition` retrieves definition locations, making type information accessible outside of editors.
|
|
12
|
+
|
|
13
|
+
In addition, this release includes many improvements such as type narrowing for `block_given?`, type checking arbitrary expressions with the `steep check` with `-e` option, and Prism parser introduction for Ruby 3.4+.
|
|
14
|
+
|
|
15
|
+
### Type checker core
|
|
16
|
+
|
|
17
|
+
* Handle RBS library syntax error
|
|
18
|
+
([#2211](https://github.com/soutaro/steep/pull/2211))
|
|
19
|
+
* Fix literal type hints to unwrap nil ([#2205](https://github.com/soutaro/steep/pull/2205))
|
|
20
|
+
* Fix array literal type inference with union tuple hint ([#2096](https://github.com/soutaro/steep/pull/2096))
|
|
21
|
+
* Fix union narrowing in the else branch ([#2101](https://github.com/soutaro/steep/pull/2101))
|
|
22
|
+
* feat: type narrowing for block_given? ([#2186](https://github.com/soutaro/steep/pull/2186))
|
|
23
|
+
* Support @type var annotations in ensure blocks to suppress type errors ([#2194](https://github.com/soutaro/steep/pull/2194))
|
|
24
|
+
* Fix ancestor error diagnostics reporting in library RBS files ([#2198](https://github.com/soutaro/steep/pull/2198))
|
|
25
|
+
* Allow yield in methods with untyped parameters ([#2193](https://github.com/soutaro/steep/pull/2193))
|
|
26
|
+
* Prepare for Ruby 3.4+ syntax support by introducing Prism parser ([#1845](https://github.com/soutaro/steep/pull/1845))
|
|
27
|
+
* Trigger full type checking when type signature of inline RBS declaration is changed ([#1829](https://github.com/soutaro/steep/pull/1829))
|
|
28
|
+
* Support inline class/module alias declaration ([#1819](https://github.com/soutaro/steep/pull/1819))
|
|
29
|
+
* Fix `Locator::Inline` ([#1815](https://github.com/soutaro/steep/pull/1815))
|
|
30
|
+
* Support inline constant declaration ([#1814](https://github.com/soutaro/steep/pull/1814))
|
|
31
|
+
* Support instance variable declaration ([#1812](https://github.com/soutaro/steep/pull/1812))
|
|
32
|
+
* Support inheritance ([#1809](https://github.com/soutaro/steep/pull/1809))
|
|
33
|
+
* `attr_***` Inline RBS type declaration ([#1800](https://github.com/soutaro/steep/pull/1800))
|
|
34
|
+
* Implement inline mixin ([#1788](https://github.com/soutaro/steep/pull/1788))
|
|
35
|
+
* Provide workspace symbols feature for inline declarations ([#1741](https://github.com/soutaro/steep/pull/1741))
|
|
36
|
+
* Fix splat/kwsplat param typing without name ([#1731](https://github.com/soutaro/steep/pull/1731))
|
|
37
|
+
* Fix empty comment error ([#1730](https://github.com/soutaro/steep/pull/1730))
|
|
38
|
+
* Type check service supports inline type declarations ([#1728](https://github.com/soutaro/steep/pull/1728))
|
|
39
|
+
* Fix redundant ignore comment ([#1722](https://github.com/soutaro/steep/pull/1722))
|
|
40
|
+
* Add `RedundantIgnoreComment` diagnostic ([#1670](https://github.com/soutaro/steep/pull/1670))
|
|
41
|
+
* Update project and `Steepfile` DSL to support inline RBS declaration ([#1602](https://github.com/soutaro/steep/pull/1602))
|
|
42
|
+
* Setup inline rbs integration ([#1585](https://github.com/soutaro/steep/pull/1585))
|
|
43
|
+
|
|
44
|
+
### Commandline tool
|
|
45
|
+
|
|
46
|
+
* Add `steep query definition NAME` command ([#2208](https://github.com/soutaro/steep/pull/2208))
|
|
47
|
+
* Add `steep query hover` command for querying type info from daemon ([#2206](https://github.com/soutaro/steep/pull/2206))
|
|
48
|
+
|
|
49
|
+
* Handle special characters in path when globbing ([#2203](https://github.com/soutaro/steep/pull/2203))
|
|
50
|
+
* Add daemon server for persistent RBS environment ([#2080](https://github.com/soutaro/steep/pull/2080))
|
|
51
|
+
* Fix `steep check` with inline source paths ([#2182](https://github.com/soutaro/steep/pull/2182))
|
|
52
|
+
* Don't use `logger.fatal` for non-fatal info ([#2158](https://github.com/soutaro/steep/pull/2158))
|
|
53
|
+
* Add -e flag to steep check for type checking arbitrary expressions ([#2102](https://github.com/soutaro/steep/pull/2102))
|
|
54
|
+
|
|
55
|
+
### Language server
|
|
56
|
+
|
|
57
|
+
* Fix goto-definition in inline source files ([#2192](https://github.com/soutaro/steep/pull/2192))
|
|
58
|
+
* Support completion and signature help for inline type annotations ([#2191](https://github.com/soutaro/steep/pull/2191))
|
|
59
|
+
* Implement completion for type names in inline RBS comments ([#1777](https://github.com/soutaro/steep/pull/1777))
|
|
60
|
+
* Small bug fixes for goto inline definition ([#1775](https://github.com/soutaro/steep/pull/1775))
|
|
61
|
+
* Goto definition into inline declaration ([#1774](https://github.com/soutaro/steep/pull/1774))
|
|
62
|
+
* Implement goto definition from inline RBS types ([#1773](https://github.com/soutaro/steep/pull/1773))
|
|
63
|
+
* Implement hover for Inline RBS types ([#1771](https://github.com/soutaro/steep/pull/1771))
|
|
64
|
+
* Refactor hover content classes ([#1742](https://github.com/soutaro/steep/pull/1742))
|
|
65
|
+
* Call `Process.warmup` before refork ([#1665](https://github.com/soutaro/steep/pull/1665))
|
|
66
|
+
|
|
67
|
+
### Miscellaneous
|
|
68
|
+
|
|
69
|
+
* Add RBS for test method ([#2204](https://github.com/soutaro/steep/pull/2204))
|
|
70
|
+
* Add missing RBS definition for test_ensure_annotation ([#2202](https://github.com/soutaro/steep/pull/2202))
|
|
71
|
+
* Add RBS signature generation and validation workflow ([#2200](https://github.com/soutaro/steep/pull/2200))
|
|
72
|
+
* Fix rbs collection setup ([#2199](https://github.com/soutaro/steep/pull/2199))
|
|
73
|
+
* Skip fork tests (2) ([#2196](https://github.com/soutaro/steep/pull/2196))
|
|
74
|
+
* Fix test failure on Windows ([#2195](https://github.com/soutaro/steep/pull/2195))
|
|
75
|
+
* Fix type checking ([#2181](https://github.com/soutaro/steep/pull/2181))
|
|
76
|
+
* Remove activesupport dependency ([#2172](https://github.com/soutaro/steep/pull/2172))
|
|
77
|
+
* bundle rbs-4.0.0 ([#2114](https://github.com/soutaro/steep/pull/2114))
|
|
78
|
+
* Fix type errors ([#2170](https://github.com/soutaro/steep/pull/2170))
|
|
79
|
+
* Remove unused `mutex_m` dependency ([#2106](https://github.com/soutaro/steep/pull/2106))
|
|
80
|
+
* Use `rbs` gem from git repository ([#2068](https://github.com/soutaro/steep/pull/2068))
|
|
81
|
+
* Fix typos ([#1572](https://github.com/soutaro/steep/pull/1572))
|
|
82
|
+
* Let claude-code fix type errors ([#1709](https://github.com/soutaro/steep/pull/1709))
|
|
83
|
+
* Drop Ruby 3.1 ([#1721](https://github.com/soutaro/steep/pull/1721))
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## 1.10.0 (2025-03-18)
|
|
87
|
+
|
|
88
|
+
Nothing changed since `1.10.0.pre.3`.
|
|
89
|
+
|
|
90
|
+
## 1.10.0.pre.3 (2025-03-14)
|
|
91
|
+
|
|
92
|
+
### Type checker core
|
|
93
|
+
|
|
94
|
+
* Fix block type checking ([#1534](https://github.com/soutaro/steep/pull/1534))
|
|
95
|
+
|
|
96
|
+
## 1.10.0.pre.2 (2025-03-14)
|
|
97
|
+
|
|
98
|
+
### Type checker core
|
|
99
|
+
|
|
100
|
+
* Fix `self` type handling at block-self-hint ([#1531](https://github.com/soutaro/steep/pull/1531))
|
|
101
|
+
* Delay type variable resolution on method call with blocks ([#1530](https://github.com/soutaro/steep/pull/1530))
|
|
102
|
+
* Fix type checking block calls on `untyped` receiver ([#1528](https://github.com/soutaro/steep/pull/1528))
|
|
103
|
+
* Catch the message of VariableDuplicationError ([#1521](https://github.com/soutaro/steep/pull/1521))
|
|
104
|
+
|
|
105
|
+
## 1.10.0.pre.1 (2025-03-11)
|
|
106
|
+
|
|
107
|
+
### Type checker core
|
|
108
|
+
|
|
109
|
+
* Skip type checking forwarded argument if the method is undeclared ([#1519](https://github.com/soutaro/steep/pull/1519))
|
|
110
|
+
* Dedup error message on ancestors check ([#1515](https://github.com/soutaro/steep/pull/1515))
|
|
111
|
+
* Add deprecation validation on RBS ([#1518](https://github.com/soutaro/steep/pull/1518))
|
|
112
|
+
* Fix union self type refinement based on method call ([#1517](https://github.com/soutaro/steep/pull/1517))
|
|
113
|
+
* Check deprecations in Ruby code ([#1513](https://github.com/soutaro/steep/pull/1513))
|
|
114
|
+
* Support `InvalidTypeApplication` on `#update_env` ([#1507](https://github.com/soutaro/steep/pull/1507))
|
|
115
|
+
* Fix Source.parse crashes with selector-less sendish node ([#1433](https://github.com/soutaro/steep/pull/1433))
|
|
116
|
+
* Fix steep:ignore does not work with CR/LF ([#1406](https://github.com/soutaro/steep/pull/1406))
|
|
117
|
+
* Fix self union type checking ([#1467](https://github.com/soutaro/steep/pull/1467))
|
|
118
|
+
* Type narrowing union types via return type of method call ([#1497](https://github.com/soutaro/steep/pull/1497))
|
|
119
|
+
* Fix `else` clause of `case-when` syntax typing ([#1475](https://github.com/soutaro/steep/pull/1475))
|
|
120
|
+
* Strict record and tuple subtyping ([#1460](https://github.com/soutaro/steep/pull/1460))
|
|
121
|
+
* Allow to annotate "self" on toplevel ([#1455](https://github.com/soutaro/steep/pull/1455))
|
|
122
|
+
* Let annotations in `when` clause without `cond` expression work ([#1459](https://github.com/soutaro/steep/pull/1459))
|
|
123
|
+
* Fix `RuntimeError` on `when` clause with assertion ([#1458](https://github.com/soutaro/steep/pull/1458))
|
|
124
|
+
* Add diagnostic for method definition without types ([#1457](https://github.com/soutaro/steep/pull/1457))
|
|
125
|
+
|
|
126
|
+
### Commandline tool
|
|
127
|
+
|
|
128
|
+
* Implement GitHub formatter ([#1516](https://github.com/soutaro/steep/pull/1516))
|
|
129
|
+
* Refine `--help` messages ([#1463](https://github.com/soutaro/steep/pull/1463))
|
|
130
|
+
|
|
131
|
+
### Language server
|
|
132
|
+
|
|
133
|
+
* Reforking steep ([#1492](https://github.com/soutaro/steep/pull/1492))
|
|
134
|
+
* Set up file watcher for groups ([#1485](https://github.com/soutaro/steep/pull/1485))
|
|
135
|
+
|
|
136
|
+
### Miscellaneous
|
|
137
|
+
|
|
138
|
+
* Fix a runtime warning for ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator ([#1438](https://github.com/soutaro/steep/pull/1438))
|
|
139
|
+
* Fix a runtime warning for ambiguous `*` has been interpreted as an argument prefix ([#1439](https://github.com/soutaro/steep/pull/1439))
|
|
140
|
+
* Fix a runtime warning for key :cursor is duplicated and overwritten on line 99 ([#1440](https://github.com/soutaro/steep/pull/1440))
|
|
141
|
+
* Use release version of RBS ([#1511](https://github.com/soutaro/steep/pull/1511))
|
|
142
|
+
* Prepare for rbs-3.9 ([#1510](https://github.com/soutaro/steep/pull/1510))
|
|
143
|
+
* Fix typos ([#1506](https://github.com/soutaro/steep/pull/1506))
|
|
144
|
+
* Fix CI ([#1486](https://github.com/soutaro/steep/pull/1486))
|
|
145
|
+
|
|
3
146
|
## 1.9.3 (2024-12-26)
|
|
4
147
|
|
|
5
148
|
### Miscellaneous
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Steep is a gradual type checker for Ruby that requires explicit type declarations using RBS (Ruby Signature) files. It performs static type checking without type inference and integrates with editors via Language Server Protocol.
|
|
8
|
+
|
|
9
|
+
## Common Development Commands
|
|
10
|
+
|
|
11
|
+
### Running Tests
|
|
12
|
+
```bash
|
|
13
|
+
# Run all unit tests
|
|
14
|
+
rake test
|
|
15
|
+
|
|
16
|
+
# Run smoke tests (integration tests with expected diagnostics)
|
|
17
|
+
rake test:output
|
|
18
|
+
|
|
19
|
+
# Run a specific test file
|
|
20
|
+
ruby -Itest test/type_check_test.rb
|
|
21
|
+
|
|
22
|
+
# Run current smoke test in a directory
|
|
23
|
+
cd smoke/alias && rake test:output:current
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Type Checking
|
|
27
|
+
```bash
|
|
28
|
+
# Type check the Steep codebase itself
|
|
29
|
+
bin/steep check
|
|
30
|
+
|
|
31
|
+
# Type check with specific severity
|
|
32
|
+
bin/steep check --severity=error
|
|
33
|
+
|
|
34
|
+
# Watch mode for continuous type checking
|
|
35
|
+
bin/steep watch
|
|
36
|
+
|
|
37
|
+
# Start language server
|
|
38
|
+
bin/steep langserver
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Building and Development
|
|
42
|
+
```bash
|
|
43
|
+
# Initial setup
|
|
44
|
+
bin/setup
|
|
45
|
+
|
|
46
|
+
# Generate RBS signatures from test files using rbs-inline
|
|
47
|
+
rake rbs:generate
|
|
48
|
+
|
|
49
|
+
# Watch and regenerate RBS signatures
|
|
50
|
+
rake rbs:watch
|
|
51
|
+
|
|
52
|
+
# Install gem locally
|
|
53
|
+
bundle exec rake install
|
|
54
|
+
|
|
55
|
+
# Build gem
|
|
56
|
+
bundle exec rake build
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Architecture Overview
|
|
60
|
+
|
|
61
|
+
### Core Type Checking Flow
|
|
62
|
+
1. **Parser Phase**: Ruby code is parsed into AST using the parser gem
|
|
63
|
+
2. **Type Construction**: `TypeConstruction` class builds typed AST by:
|
|
64
|
+
- Reading RBS signatures from sig/ directories
|
|
65
|
+
- Processing annotations (@type, @dynamic, etc.)
|
|
66
|
+
- Building type environments
|
|
67
|
+
3. **Subtyping Check**: `Subtyping::Check` validates type relationships
|
|
68
|
+
4. **Diagnostics**: Type errors are collected and formatted
|
|
69
|
+
|
|
70
|
+
### Key Components
|
|
71
|
+
|
|
72
|
+
**Type System Core** (`lib/steep/`):
|
|
73
|
+
- `type_construction.rb`: Main type checking logic that traverses AST
|
|
74
|
+
- `type_inference/`: Components for inferring types in specific contexts
|
|
75
|
+
- `subtyping/`: Subtyping relationship validation
|
|
76
|
+
- `interface/`: Type interface definitions and method resolution
|
|
77
|
+
|
|
78
|
+
**Language Server** (`lib/steep/server/`):
|
|
79
|
+
- `master.rb`: Coordinates worker processes
|
|
80
|
+
- `type_check_worker.rb`: Performs type checking in background
|
|
81
|
+
- `interaction_worker.rb`: Handles completion, hover, goto definition
|
|
82
|
+
|
|
83
|
+
**Services** (`lib/steep/services/`):
|
|
84
|
+
- `type_check_service.rb`: Manages incremental type checking
|
|
85
|
+
- `signature_service.rb`: Manages RBS signatures and dependencies
|
|
86
|
+
- `completion_provider.rb`: Provides code completion
|
|
87
|
+
|
|
88
|
+
### Testing Strategy
|
|
89
|
+
|
|
90
|
+
1. **Unit Tests**: Traditional tests in `test/` directory
|
|
91
|
+
2. **Smoke Tests**: Integration tests in `smoke/` with:
|
|
92
|
+
- Each test case in its own directory
|
|
93
|
+
- `test_expectations.yml` defines expected diagnostics
|
|
94
|
+
- Tests cover Ruby features and edge cases
|
|
95
|
+
|
|
96
|
+
### Configuration
|
|
97
|
+
|
|
98
|
+
**Steepfile**: Defines type checking targets
|
|
99
|
+
- `check`: Directories to type check
|
|
100
|
+
- `signature`: RBS signature directories
|
|
101
|
+
- `library`: Standard library dependencies
|
|
102
|
+
- `collection_config`: External RBS definitions
|
|
103
|
+
- Multiple targets supported (app, test, bin)
|
|
104
|
+
|
|
105
|
+
**RBS Collection**: Manages external type definitions via `rbs_collection.steep.yaml`
|
|
106
|
+
|
|
107
|
+
## Key Implementation Details
|
|
108
|
+
|
|
109
|
+
- Self-hosted: Steep type-checks its own codebase
|
|
110
|
+
- Uses RBS 4.0.0.dev (development version)
|
|
111
|
+
- Requires Ruby 3.1.0+
|
|
112
|
+
- Diagnostic severity levels: error, warning, information, hint
|
|
113
|
+
- Supports gradual typing with @dynamic annotations
|
|
114
|
+
- Implements LSP for IDE integration
|
data/README.md
CHANGED
data/Rakefile
CHANGED
|
@@ -19,6 +19,14 @@ namespace :test do
|
|
|
19
19
|
task :output do
|
|
20
20
|
sh "ruby", "bin/output_test.rb"
|
|
21
21
|
end
|
|
22
|
+
|
|
23
|
+
namespace :output do
|
|
24
|
+
desc "Run current output test"
|
|
25
|
+
task :current do
|
|
26
|
+
puts ">> Running `steep check` in #{ENV["PWD"]}"
|
|
27
|
+
sh "steep", "check", "--with-expectations=test_expectations.yml", chdir: ENV["PWD"]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
22
30
|
end
|
|
23
31
|
|
|
24
32
|
# Disable the following task enhancement add upstream
|
|
@@ -225,3 +233,30 @@ NOTES
|
|
|
225
233
|
end
|
|
226
234
|
end
|
|
227
235
|
end
|
|
236
|
+
|
|
237
|
+
namespace :rbs do
|
|
238
|
+
task :watch do
|
|
239
|
+
require "listen"
|
|
240
|
+
listener = Listen.to('test') do |modified, added, removed|
|
|
241
|
+
paths = (modified + added).map do
|
|
242
|
+
Pathname(_1).relative_path_from(Pathname.pwd)
|
|
243
|
+
end
|
|
244
|
+
Bundler.with_unbundled_env do
|
|
245
|
+
sh "bin/rbs-inline", "--opt-out", "--output=sig", *paths.map(&:to_s)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
listener.start
|
|
249
|
+
begin
|
|
250
|
+
sleep
|
|
251
|
+
rescue Interrupt
|
|
252
|
+
listener.stop
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
task :generate do
|
|
257
|
+
Bundler.with_unbundled_env do
|
|
258
|
+
sh "bin/rbs-inline --opt-out --output=sig test"
|
|
259
|
+
sh "bin/rbs-inline --opt-out --output=tmp/rbs-inline bin/generate-diagnostics-docs.rb"
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
data/Steepfile
CHANGED
|
@@ -5,15 +5,16 @@ D = Steep::Diagnostic
|
|
|
5
5
|
FileUtils.mkpath("tmp")
|
|
6
6
|
tmp_rbs_dir = Pathname("tmp/rbs-sig")
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
# The DSL is executed in the main process and worker processes, and the file operations introduce a race condition.
|
|
9
|
+
# This line ensures the operations are executed only in the main process.
|
|
10
|
+
if caller.none? {|c| c =~ /\/worker_process\.rb:/ }
|
|
11
|
+
tmp_rbs_dir.delete if tmp_rbs_dir.exist?
|
|
12
|
+
|
|
13
|
+
definition = Bundler::Definition.build(Pathname("Gemfile"), Pathname("Gemfile.lock"), nil)
|
|
14
|
+
rbs_dep = definition.dependencies.find {|dep| dep.name == "rbs" }
|
|
15
|
+
if (source = rbs_dep&.source).is_a?(Bundler::Source::Path)
|
|
16
|
+
tmp_rbs_dir.make_symlink(Pathname.pwd + source.path + "sig")
|
|
13
17
|
end
|
|
14
|
-
else
|
|
15
|
-
FileUtils.rm_f(tmp_rbs_dir)
|
|
16
|
-
library "rbs"
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
target :app do
|
|
@@ -48,9 +49,7 @@ target :test do
|
|
|
48
49
|
|
|
49
50
|
configure_code_diagnostics(D::Ruby.lenient)
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
signature tmp_rbs_dir.to_s
|
|
53
|
-
else
|
|
52
|
+
unless tmp_rbs_dir.directory?
|
|
54
53
|
library "rbs"
|
|
55
54
|
end
|
|
56
55
|
end
|
|
@@ -64,5 +63,9 @@ target :bin do
|
|
|
64
63
|
check "bin/generate-diagnostics-docs.rb"
|
|
65
64
|
signature "tmp/rbs-inline/bin"
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
configure_code_diagnostics(D::Ruby.lenient)
|
|
67
|
+
|
|
68
|
+
unless tmp_rbs_dir.directory?
|
|
69
|
+
library "rbs"
|
|
70
|
+
end
|
|
68
71
|
end
|
|
@@ -56,8 +56,12 @@ module Steep
|
|
|
56
56
|
RBS::Parser.parse_type(string)
|
|
57
57
|
rescue RBS::ParsingError => exn
|
|
58
58
|
raise SyntaxError.new(source: string, location: loc, exn: exn)
|
|
59
|
-
end
|
|
59
|
+
end
|
|
60
60
|
|
|
61
|
+
unless type
|
|
62
|
+
raise SyntaxError.new(source: string, location: loc, message: "Failed to parse a type in annotation")
|
|
63
|
+
end
|
|
64
|
+
|
|
61
65
|
unless (type.location || raise).source == string.strip
|
|
62
66
|
raise SyntaxError.new(source: string, location: loc, message: "Failed to parse a type in annotation")
|
|
63
67
|
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Steep
|
|
2
|
+
module AnnotationsHelper
|
|
3
|
+
module_function
|
|
4
|
+
|
|
5
|
+
def deprecated_annotation?(annotations)
|
|
6
|
+
annotations.reverse_each do |annotation|
|
|
7
|
+
if match = annotation.string.match(/deprecated(:\s*(?<message>.+))?/)
|
|
8
|
+
return [annotation, match[:message]]
|
|
9
|
+
end
|
|
10
|
+
if match = annotation.string.match(/steep:deprecated(:\s*(?<message>.+))?/)
|
|
11
|
+
return [annotation, match[:message]]
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def deprecated_type_name?(type_name, env)
|
|
19
|
+
annotations =
|
|
20
|
+
case
|
|
21
|
+
when type_name.class?
|
|
22
|
+
case
|
|
23
|
+
when decl = env.class_decls.fetch(type_name, nil)
|
|
24
|
+
decl.each_decl.flat_map do |decl|
|
|
25
|
+
if decl.is_a?(RBS::AST::Declarations::Base)
|
|
26
|
+
decl.annotations
|
|
27
|
+
else
|
|
28
|
+
[]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
when decl = env.class_alias_decls.fetch(type_name, nil)
|
|
32
|
+
if decl.decl.is_a?(RBS::AST::Declarations::Base)
|
|
33
|
+
decl.decl.annotations
|
|
34
|
+
else
|
|
35
|
+
[] #: Array[RBS::AST::Annotation]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
when type_name.interface?
|
|
39
|
+
if decl = env.interface_decls.fetch(type_name, nil)
|
|
40
|
+
decl.decl.annotations
|
|
41
|
+
end
|
|
42
|
+
when type_name.alias?
|
|
43
|
+
if decl = env.type_alias_decls.fetch(type_name, nil)
|
|
44
|
+
decl.decl.annotations
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
if annotations
|
|
49
|
+
deprecated_annotation?(annotations)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
data/lib/steep/ast/ignore.rb
CHANGED
|
@@ -93,15 +93,14 @@ module Steep
|
|
|
93
93
|
def self.parse(comment, buffer)
|
|
94
94
|
return unless comment.inline?
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
begin_pos = buffer.loc_to_pos([comment.loc.line, comment.loc.column])
|
|
97
|
+
end_pos = buffer.loc_to_pos([comment.loc.last_line, comment.loc.last_column])
|
|
98
|
+
comment_location = RBS::Location.new(buffer, begin_pos, end_pos)
|
|
97
99
|
scanner = BufferScanner.new(comment_location)
|
|
98
100
|
|
|
99
101
|
scanner.scan(/#/)
|
|
100
102
|
scanner.skip(/\s*/)
|
|
101
103
|
|
|
102
|
-
begin_pos = comment.location.expression.begin_pos
|
|
103
|
-
end_pos = comment.location.expression.end_pos
|
|
104
|
-
|
|
105
104
|
case
|
|
106
105
|
when loc = scanner.scan(/steep:ignore:start\b/)
|
|
107
106
|
scanner.skip(/\s*/)
|
|
@@ -25,33 +25,21 @@ module Steep
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def types(context, subtyping, type_vars)
|
|
28
|
-
resolver = RBS::Resolver::TypeNameResolver.new(subtyping.factory.env)
|
|
29
|
-
|
|
30
28
|
# @type var types: Array[LocatedValue[Types::t]]
|
|
31
29
|
types = []
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
while true
|
|
36
|
-
rbs_ty = RBS::Parser.parse_type(loc.buffer, range: loc.range, variables: type_vars) or break
|
|
37
|
-
rbs_loc = rbs_ty.location or raise
|
|
38
|
-
ty = rbs_ty.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
|
|
39
|
-
|
|
31
|
+
each_rbs_type(context, subtyping, type_vars) do |rbs_ty|
|
|
40
32
|
validator = Signature::Validator.new(checker: subtyping)
|
|
41
33
|
validator.rescue_validation_errors do
|
|
42
|
-
validator.validate_type(
|
|
34
|
+
validator.validate_type(rbs_ty)
|
|
43
35
|
end
|
|
44
36
|
|
|
45
37
|
if validator.has_error?
|
|
46
38
|
return validator.each_error
|
|
47
39
|
end
|
|
48
40
|
|
|
49
|
-
ty = subtyping.factory.type(
|
|
50
|
-
types << LocatedValue.new(value: ty, location:
|
|
51
|
-
|
|
52
|
-
match = RBS::Location.new(loc.buffer, rbs_loc.end_pos, type_location.end_pos).source.match(/\A\s*,\s*/) or break
|
|
53
|
-
offset = match.length
|
|
54
|
-
loc = RBS::Location.new(loc.buffer, rbs_loc.end_pos + offset, type_location.end_pos)
|
|
41
|
+
ty = subtyping.factory.type(rbs_ty)
|
|
42
|
+
types << LocatedValue.new(value: ty, location: rbs_ty.location || raise)
|
|
55
43
|
end
|
|
56
44
|
|
|
57
45
|
types
|
|
@@ -68,6 +56,24 @@ module Steep
|
|
|
68
56
|
end
|
|
69
57
|
end
|
|
70
58
|
|
|
59
|
+
def each_rbs_type(context, subtyping, type_vars)
|
|
60
|
+
resolver = RBS::Resolver::TypeNameResolver.build(subtyping.factory.env)
|
|
61
|
+
|
|
62
|
+
loc = type_location
|
|
63
|
+
|
|
64
|
+
while true
|
|
65
|
+
type = RBS::Parser.parse_type(loc.buffer, range: loc.range, variables: type_vars) or break
|
|
66
|
+
type_loc = type.location or raise
|
|
67
|
+
type = type.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
|
|
68
|
+
|
|
69
|
+
yield type
|
|
70
|
+
|
|
71
|
+
match = RBS::Location.new(loc.buffer, type_loc.end_pos, type_location.end_pos).source.match(/\A\s*,\s*/) or break
|
|
72
|
+
offset = match.length
|
|
73
|
+
loc = RBS::Location.new(loc.buffer, type_loc.end_pos + offset, type_location.end_pos)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
71
77
|
def type_str
|
|
72
78
|
@type_str ||= source.delete_prefix("$").lstrip
|
|
73
79
|
end
|
|
@@ -16,11 +16,15 @@ module Steep
|
|
|
16
16
|
location.start_line
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def rbs_type(context, subtyping, type_vars)
|
|
20
20
|
if ty = RBS::Parser.parse_type(type_location.buffer, range: type_location.range, variables: type_vars, require_eof: true)
|
|
21
|
-
resolver = RBS::Resolver::TypeNameResolver.
|
|
21
|
+
resolver = RBS::Resolver::TypeNameResolver.build(subtyping.factory.env)
|
|
22
22
|
ty = ty.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
23
25
|
|
|
26
|
+
def type(context, subtyping, type_vars)
|
|
27
|
+
if ty = rbs_type(context, subtyping, type_vars)
|
|
24
28
|
validator = Signature::Validator.new(checker: subtyping)
|
|
25
29
|
validator.rescue_validation_errors do
|
|
26
30
|
validator.validate_type(ty)
|
|
@@ -40,9 +44,8 @@ module Steep
|
|
|
40
44
|
|
|
41
45
|
def type_syntax?
|
|
42
46
|
RBS::Parser.parse_type(type_location.buffer, range: type_location.range, variables: [], require_eof: true)
|
|
43
|
-
true
|
|
44
47
|
rescue ::RBS::ParsingError
|
|
45
|
-
|
|
48
|
+
nil
|
|
46
49
|
end
|
|
47
50
|
|
|
48
51
|
def type?(context, subtyping, type_vars)
|
|
@@ -21,7 +21,7 @@ module Steep
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def type_name_resolver
|
|
24
|
-
@type_name_resolver ||= RBS::Resolver::TypeNameResolver.
|
|
24
|
+
@type_name_resolver ||= RBS::Resolver::TypeNameResolver.build(definition_builder.env)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def type_opt(type)
|
|
@@ -39,7 +39,7 @@ module Steep
|
|
|
39
39
|
def normalize_args(type_name, args)
|
|
40
40
|
case
|
|
41
41
|
when type_name.class?
|
|
42
|
-
if entry = env.
|
|
42
|
+
if entry = env.module_class_entry(type_name, normalized: true)
|
|
43
43
|
type_params = entry.type_params
|
|
44
44
|
end
|
|
45
45
|
when type_name.interface?
|
|
@@ -294,6 +294,7 @@ module Steep
|
|
|
294
294
|
raise "`#{u_}` cannot be type parameter upper bound"
|
|
295
295
|
end
|
|
296
296
|
},
|
|
297
|
+
lower_bound: nil,
|
|
297
298
|
location: type_param.location
|
|
298
299
|
).unchecked!(type_param.unchecked)
|
|
299
300
|
end
|