rbs_heuristic_prototype 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a07c6fce554f459391e7d81cfee78e42cd54a78704d1ccefa27f6b289cdce67e
4
+ data.tar.gz: 78846ef4bcd829e0cb74de64feedc83314599fac49f9174919f6f72fd8e8c180
5
+ SHA512:
6
+ metadata.gz: a4ad899d1c92ff8ebfa26dab2d041357440724637b1c28094d9748b4024b97214bd9a2328ddbc524e35cc0c468d0658113d31484ee34b93cae6d2d545e1e0aa2
7
+ data.tar.gz: ff09d89ee6476e0951e31fad137b172130cb82820072a8e6a86f85718c9afa9e6a36dcc384e66e12d774d71a38609bb1287b6326bb063c97e1cf94537e5dc046
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,19 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.1
3
+
4
+ Style/Documentation:
5
+ Enabled: false
6
+
7
+ Style/StringLiterals:
8
+ Enabled: true
9
+ EnforcedStyle: double_quotes
10
+
11
+ Style/StringLiteralsInInterpolation:
12
+ Enabled: true
13
+ EnforcedStyle: double_quotes
14
+
15
+ Layout/LineLength:
16
+ Max: 120
17
+
18
+ Metrics/MethodLength:
19
+ Max: 20
@@ -0,0 +1,8 @@
1
+ {
2
+ "recommendations": [
3
+ "shopify.ruby-lsp",
4
+ "soutaro.steep-vscode",
5
+ "tk0miya.rspec-daemon",
6
+ "tk0miya.rbs-helper"
7
+ ]
8
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "[ruby]": {
3
+ "editor.defaultFormatter": "Shopify.ruby-lsp"
4
+ },
5
+ "rbs-helper.signature-directory": "sig",
6
+ "cSpell.words": [
7
+ "boolish",
8
+ "codebases",
9
+ "rubygems"
10
+ ]
11
+ }
@@ -0,0 +1,84 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8
+
9
+ ## Our Standards
10
+
11
+ Examples of behavior that contributes to a positive environment for our community include:
12
+
13
+ * Demonstrating empathy and kindness toward other people
14
+ * Being respectful of differing opinions, viewpoints, and experiences
15
+ * Giving and gracefully accepting constructive feedback
16
+ * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17
+ * Focusing on what is best not just for us as individuals, but for the overall community
18
+
19
+ Examples of unacceptable behavior include:
20
+
21
+ * The use of sexualized language or imagery, and sexual attention or
22
+ advances of any kind
23
+ * Trolling, insulting or derogatory comments, and personal or political attacks
24
+ * Public or private harassment
25
+ * Publishing others' private information, such as a physical or email
26
+ address, without their explicit permission
27
+ * Other conduct which could reasonably be considered inappropriate in a
28
+ professional setting
29
+
30
+ ## Enforcement Responsibilities
31
+
32
+ Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
33
+
34
+ Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
35
+
36
+ ## Scope
37
+
38
+ This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
39
+
40
+ ## Enforcement
41
+
42
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at i.tkomiya@gmail.com. All complaints will be reviewed and investigated promptly and fairly.
43
+
44
+ All community leaders are obligated to respect the privacy and security of the reporter of any incident.
45
+
46
+ ## Enforcement Guidelines
47
+
48
+ Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
49
+
50
+ ### 1. Correction
51
+
52
+ **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
53
+
54
+ **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
55
+
56
+ ### 2. Warning
57
+
58
+ **Community Impact**: A violation through a single incident or series of actions.
59
+
60
+ **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
61
+
62
+ ### 3. Temporary Ban
63
+
64
+ **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
65
+
66
+ **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
67
+
68
+ ### 4. Permanent Ban
69
+
70
+ **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
71
+
72
+ **Consequence**: A permanent ban from any sort of public interaction within the community.
73
+
74
+ ## Attribution
75
+
76
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
77
+ available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
78
+
79
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
80
+
81
+ [homepage]: https://www.contributor-covenant.org
82
+
83
+ For answers to common questions about this code of conduct, see the FAQ at
84
+ https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in rbs_heuristic_prototype.gemspec
6
+ gemspec
7
+
8
+ gem "activerecord"
9
+ gem "railties"
10
+ gem "rake", "~> 13.0"
11
+ gem "rubocop", "~> 1.54"
12
+
13
+ group :development do
14
+ gem "rspec", require: false
15
+ gem "rspec-daemon", require: false
16
+ gem "steep"
17
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,163 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rbs_heuristic_prototype (0.1.0)
5
+ rbs
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actionpack (7.0.6)
11
+ actionview (= 7.0.6)
12
+ activesupport (= 7.0.6)
13
+ rack (~> 2.0, >= 2.2.4)
14
+ rack-test (>= 0.6.3)
15
+ rails-dom-testing (~> 2.0)
16
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
17
+ actionview (7.0.6)
18
+ activesupport (= 7.0.6)
19
+ builder (~> 3.1)
20
+ erubi (~> 1.4)
21
+ rails-dom-testing (~> 2.0)
22
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
23
+ activemodel (7.0.6)
24
+ activesupport (= 7.0.6)
25
+ activerecord (7.0.6)
26
+ activemodel (= 7.0.6)
27
+ activesupport (= 7.0.6)
28
+ activesupport (7.0.6)
29
+ concurrent-ruby (~> 1.0, >= 1.0.2)
30
+ i18n (>= 1.6, < 2)
31
+ minitest (>= 5.1)
32
+ tzinfo (~> 2.0)
33
+ ast (2.4.2)
34
+ builder (3.2.4)
35
+ coderay (1.1.3)
36
+ concurrent-ruby (1.2.2)
37
+ crass (1.0.6)
38
+ csv (3.2.6)
39
+ diff-lcs (1.5.0)
40
+ erubi (1.12.0)
41
+ ffi (1.15.5)
42
+ fileutils (1.7.1)
43
+ i18n (1.14.1)
44
+ concurrent-ruby (~> 1.0)
45
+ json (2.6.3)
46
+ language_server-protocol (3.17.0.3)
47
+ listen (3.8.0)
48
+ rb-fsevent (~> 0.10, >= 0.10.3)
49
+ rb-inotify (~> 0.9, >= 0.9.10)
50
+ logger (1.5.3)
51
+ loofah (2.21.3)
52
+ crass (~> 1.0.2)
53
+ nokogiri (>= 1.12.0)
54
+ method_source (1.0.0)
55
+ minitest (5.18.1)
56
+ nokogiri (1.15.2-x86_64-darwin)
57
+ racc (~> 1.4)
58
+ nokogiri (1.15.2-x86_64-linux)
59
+ racc (~> 1.4)
60
+ parallel (1.23.0)
61
+ parser (3.2.2.3)
62
+ ast (~> 2.4.1)
63
+ racc
64
+ pry (0.14.2)
65
+ coderay (~> 1.1)
66
+ method_source (~> 1.0)
67
+ racc (1.7.1)
68
+ rack (2.2.7)
69
+ rack-test (2.1.0)
70
+ rack (>= 1.3)
71
+ rails-dom-testing (2.1.1)
72
+ activesupport (>= 5.0.0)
73
+ minitest
74
+ nokogiri (>= 1.6)
75
+ rails-html-sanitizer (1.6.0)
76
+ loofah (~> 2.21)
77
+ nokogiri (~> 1.14)
78
+ railties (7.0.6)
79
+ actionpack (= 7.0.6)
80
+ activesupport (= 7.0.6)
81
+ method_source
82
+ rake (>= 12.2)
83
+ thor (~> 1.0)
84
+ zeitwerk (~> 2.5)
85
+ rainbow (3.1.1)
86
+ rake (13.0.6)
87
+ rb-fsevent (0.11.2)
88
+ rb-inotify (0.10.1)
89
+ ffi (~> 1.0)
90
+ rbs (3.1.0)
91
+ regexp_parser (2.8.1)
92
+ rexml (3.2.5)
93
+ rspec (3.12.0)
94
+ rspec-core (~> 3.12.0)
95
+ rspec-expectations (~> 3.12.0)
96
+ rspec-mocks (~> 3.12.0)
97
+ rspec-core (3.12.2)
98
+ rspec-support (~> 3.12.0)
99
+ rspec-daemon (0.1.5)
100
+ pry
101
+ rspec
102
+ rspec-expectations (3.12.3)
103
+ diff-lcs (>= 1.2.0, < 2.0)
104
+ rspec-support (~> 3.12.0)
105
+ rspec-mocks (3.12.5)
106
+ diff-lcs (>= 1.2.0, < 2.0)
107
+ rspec-support (~> 3.12.0)
108
+ rspec-support (3.12.0)
109
+ rubocop (1.54.1)
110
+ json (~> 2.3)
111
+ language_server-protocol (>= 3.17.0)
112
+ parallel (~> 1.10)
113
+ parser (>= 3.2.2.3)
114
+ rainbow (>= 2.2.2, < 4.0)
115
+ regexp_parser (>= 1.8, < 3.0)
116
+ rexml (>= 3.2.5, < 4.0)
117
+ rubocop-ast (>= 1.28.0, < 2.0)
118
+ ruby-progressbar (~> 1.7)
119
+ unicode-display_width (>= 2.4.0, < 3.0)
120
+ rubocop-ast (1.29.0)
121
+ parser (>= 3.2.1.0)
122
+ ruby-progressbar (1.13.0)
123
+ securerandom (0.2.2)
124
+ steep (1.4.0)
125
+ activesupport (>= 5.1)
126
+ concurrent-ruby (>= 1.2.2)
127
+ csv (>= 3.0.9)
128
+ fileutils (>= 1.1.0)
129
+ json (>= 2.1.0)
130
+ language_server-protocol (>= 3.15, < 4.0)
131
+ listen (~> 3.0)
132
+ logger (>= 1.3.0)
133
+ parser (>= 3.1)
134
+ rainbow (>= 2.2.2, < 4.0)
135
+ rbs (>= 2.8.0)
136
+ securerandom (>= 0.1)
137
+ strscan (>= 1.0.0)
138
+ terminal-table (>= 2, < 4)
139
+ strscan (3.0.6)
140
+ terminal-table (3.0.2)
141
+ unicode-display_width (>= 1.1.1, < 3)
142
+ thor (1.2.2)
143
+ tzinfo (2.0.6)
144
+ concurrent-ruby (~> 1.0)
145
+ unicode-display_width (2.4.2)
146
+ zeitwerk (2.6.8)
147
+
148
+ PLATFORMS
149
+ x86_64-darwin-21
150
+ x86_64-linux
151
+
152
+ DEPENDENCIES
153
+ activerecord
154
+ railties
155
+ rake (~> 13.0)
156
+ rbs_heuristic_prototype!
157
+ rspec
158
+ rspec-daemon
159
+ rubocop (~> 1.54)
160
+ steep
161
+
162
+ BUNDLED WITH
163
+ 2.4.13
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Takeshi KOMIYA
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # RBS::Heuristic::Prototype
2
+
3
+ Update prototype signature files by heuristic rules.
4
+
5
+ ## Installation
6
+
7
+ Add a new entry to your Gemfile and run bundle install:
8
+
9
+ ```
10
+ group :development do
11
+ gem 'rbs_heuristic_prototype'
12
+ end
13
+ ```
14
+
15
+ After the installation, please run rake task generator:
16
+
17
+ ```
18
+ bundle exec rails g rbs_heuristic_prototype:install
19
+ ```
20
+
21
+ Additionally, it would be better to add the following entry to your rbs_collection.yml:
22
+
23
+ ```
24
+ gems:
25
+ - name: rbs_heuristic_prototype
26
+ ignore: true
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ 1. Run `rbs prototype rb` or `rbs prototype runtime` first
32
+ 2. Run `rbs:prototype:heuristic`
33
+
34
+ Then rbs_heuristic_prototype will update the prototype signature files generated
35
+ by `rbs prototype` according to the heuristic rules.
36
+
37
+ * Rule 1:
38
+ * Convert a method ending with '?' to a method returning "boolish"
39
+ * Rule 2:
40
+ * Convert a constant annotated with Array of Union of symbols (ex. `Array[:sym1 | :sym2 | ...]`) to a constant annotated with `Array[Symbol]`
41
+ * This is useful to avoid `Ruby::IncompatibleAssignment` warning when right hand value uses `#freeze` method
42
+ * ref: https://github.com/soutaro/steep/issues/363
43
+
44
+ ## Development
45
+
46
+ After checking out the repo, run `bin/setup` to install dependencies. You can also
47
+ run `bin/console` for an interactive prompt that will allow you to experiment.
48
+
49
+ To install this gem onto your local machine, run `bundle exec rake install`.
50
+
51
+ To release a new version, update the version number in `version.rb`, and then put
52
+ a git tag (ex. `git tag v1.0.0`) and push it to the GitHub. Then GitHub Actions
53
+ will release a new package to [rubygems.org](https://rubygems.org) automatically.
54
+
55
+ ## Contributing
56
+
57
+ Bug reports and pull requests are welcome on GitHub at https://github.com/tk0miya/rbs_heuristic_prototype.
58
+ This project is intended to be a safe, welcoming space for collaboration, and contributors are
59
+ expected to adhere to the [code of conduct](https://github.com/tk0miya/rbs_heuristic_prototype/blob/main/CODE_OF_CONDUCT.md).
60
+
61
+ ## License
62
+
63
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
64
+
65
+ ## Code of Conduct
66
+
67
+
68
+
69
+ Everyone interacting in the RbsHeuristicPrototype project's codebases, issue trackers is
70
+ expected to follow the [code of conduct](https://github.com/tk0miya/rbs_heuristic_prototype/blob/main/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rubocop/rake_task"
5
+
6
+ RuboCop::RakeTask.new
7
+
8
+ task default: :rubocop
data/Steepfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ D = Steep::Diagnostic
4
+
5
+ target :lib do
6
+ signature "sig"
7
+
8
+ check "lib" # Directory name
9
+ check "Gemfile" # File name
10
+
11
+ configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
12
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails"
4
+
5
+ module RbsHeuristicPrototype
6
+ class InstallGenerator < Rails::Generators::Base
7
+ def create_raketask
8
+ create_file "lib/tasks/rbs_heuristic_prototype.rake", <<~RUBY
9
+ begin
10
+ require 'rbs_heuristic_prototype/rake_task'
11
+ RbsHeuristicPrototype::RakeTask.new
12
+ rescue LoadError
13
+ # failed to load rbs_heuristic_prototype. Skip to load rbs_heuristic_prototype tasks.
14
+ end
15
+ RUBY
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module RbsHeuristicPrototype
6
+ module Filters
7
+ class ActiveModelValidationsFilter < Base
8
+ attr_reader :klass
9
+
10
+ def process_class(decl)
11
+ @klass = const_get(decl)
12
+
13
+ return decl unless klass&.ancestors&.include?(ActiveModel::Validations)
14
+
15
+ super
16
+ end
17
+
18
+ def process_member(member)
19
+ callbacks = klass ? klass.__callbacks.fetch(:validate, []).map(&:filter) : []
20
+
21
+ case member
22
+ when RBS::AST::Members::MethodDefinition
23
+ if callbacks.include?(member.name)
24
+ overloads = member.overloads.map do |overload|
25
+ overload.update(method_type: process_method_type(overload.method_type))
26
+ end
27
+ member.update(overloads:)
28
+ else
29
+ member
30
+ end
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ def process_method_type(method_type)
37
+ type = process_type(method_type.type)
38
+ method_type.update(type:)
39
+ end
40
+
41
+ def process_type(type)
42
+ # @type var location: untyped
43
+ name = RBS::TypeName.new(namespace: RBS::Namespace.empty, name: :void)
44
+ location = type.return_type.location
45
+ return_type = RBS::Types::Alias.new(name:, args: [], location:)
46
+ type.update(return_type:)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rbs"
4
+
5
+ module RbsHeuristicPrototype
6
+ module Filters
7
+ class Base
8
+ attr_reader :env
9
+
10
+ def initialize(env)
11
+ @env = env
12
+ end
13
+
14
+ def apply
15
+ decls = env.declarations.map do |decl|
16
+ process(decl)
17
+ end
18
+ RBS::Environment.new.tap do |env|
19
+ env.add_signature(buffer: RBS::Buffer.new(name: "dummy", content: ""), directives: [], decls:)
20
+ end
21
+ end
22
+
23
+ def process(decl)
24
+ case decl
25
+ when RBS::AST::Declarations::Module
26
+ process_module(decl)
27
+ when RBS::AST::Declarations::Class
28
+ process_class(decl)
29
+ when RBS::AST::Declarations::Constant
30
+ process_constant(decl)
31
+ else
32
+ decl
33
+ end
34
+ end
35
+
36
+ def process_module(decl)
37
+ members = decl.members.map do |member|
38
+ case member
39
+ when RBS::AST::Members::Base
40
+ process_member(member)
41
+ else
42
+ process(member)
43
+ end
44
+ end
45
+
46
+ RBS::AST::Declarations::Module.new(
47
+ name: decl.name,
48
+ type_params: decl.type_params,
49
+ members:,
50
+ self_types: decl.self_types,
51
+ annotations: decl.annotations,
52
+ location: decl.location,
53
+ comment: decl.comment
54
+ )
55
+ end
56
+
57
+ def process_class(decl)
58
+ members = decl.members.map do |member|
59
+ case member
60
+ when RBS::AST::Members::Base
61
+ process_member(member)
62
+ else
63
+ process(member)
64
+ end
65
+ end
66
+
67
+ RBS::AST::Declarations::Class.new(
68
+ name: decl.name,
69
+ type_params: decl.type_params,
70
+ super_class: decl.super_class,
71
+ members:,
72
+ annotations: decl.annotations,
73
+ location: decl.location,
74
+ comment: decl.comment
75
+ )
76
+ end
77
+
78
+ def process_constant(constant)
79
+ constant
80
+ end
81
+
82
+ def process_member(member)
83
+ member
84
+ end
85
+
86
+ def const_get(decl)
87
+ decl.name.to_namespace.path.inject(Kernel) do |const, mod|
88
+ const.const_get(mod)
89
+ end
90
+ rescue StandardError
91
+ nil
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module RbsHeuristicPrototype
6
+ module Filters
7
+ class BooleanMethodsFilter < Base
8
+ def process_member(member)
9
+ case member
10
+ when RBS::AST::Members::MethodDefinition
11
+ if member.name.end_with?("?")
12
+ overloads = member.overloads.map do |overload|
13
+ overload.update(method_type: process_method_type(overload.method_type))
14
+ end
15
+ member.update(overloads:)
16
+ else
17
+ member
18
+ end
19
+ else
20
+ super
21
+ end
22
+ end
23
+
24
+ def process_method_type(method_type)
25
+ type = process_type(method_type.type)
26
+ method_type.update(type:)
27
+ end
28
+
29
+ def process_type(type)
30
+ # @type var location: untyped
31
+ name = RBS::TypeName.new(namespace: RBS::Namespace.empty, name: :boolish)
32
+ location = type.return_type.location
33
+ return_type = RBS::Types::Alias.new(name:, args: [], location:)
34
+ type.update(return_type:)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module RbsHeuristicPrototype
6
+ module Filters
7
+ class SymbolArrayConstantsFilter < Base
8
+ def process_constant(constant)
9
+ if constant.name.to_s =~ /^[A-Z][A-Z0-9_]*$/ && symbol_array?(constant.type)
10
+ RBS::AST::Declarations::Constant.new(
11
+ name: constant.name,
12
+ type: process_constant_type(constant.type),
13
+ location: constant.location,
14
+ comment: constant.comment
15
+ )
16
+ else
17
+ constant
18
+ end
19
+ end
20
+
21
+ def process_constant_type(type)
22
+ # @type var location: untyped
23
+ name = RBS::TypeName.new(namespace: RBS::Namespace.root, name: :Symbol)
24
+ location = type.location
25
+ symbol = RBS::Types::Alias.new(name:, args: [], location:)
26
+ RBS::Types::ClassInstance.new(name: type.name, args: [symbol], location:)
27
+ end
28
+
29
+ def symbol_array?(type)
30
+ array?(type) && ((type.args.size == 1 && symbol_union?(type.args.first)) || type.args.all? { |t| symbol?(t) })
31
+ end
32
+
33
+ def array?(type)
34
+ type.is_a?(RBS::Types::ClassInstance) && type.name.to_s == "::Array"
35
+ end
36
+
37
+ def symbol_union?(type)
38
+ if type.is_a?(RBS::Types::Union) && type.types.all? { |t| symbol?(t) }
39
+ true
40
+ else
41
+ false
42
+ end
43
+ end
44
+
45
+ def symbol?(type)
46
+ type.is_a?(RBS::Types::Literal) && type.literal.is_a?(Symbol)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "rake"
5
+ require "rake/tasklib"
6
+
7
+ module RbsHeuristicPrototype
8
+ class RakeTask < Rake::TaskLib
9
+ FILTERS = {
10
+ active_model_validations: Filters::ActiveModelValidationsFilter,
11
+ boolean_methods: Filters::BooleanMethodsFilter,
12
+ symbol_array_constants: Filters::SymbolArrayConstantsFilter
13
+ }.freeze
14
+
15
+ attr_reader :name, :path
16
+
17
+ def initialize(name = :"rbs:prototype:heuristic", &block)
18
+ super()
19
+
20
+ @name = name
21
+ @path = Pathname(Rails.root / "sig/prototype")
22
+
23
+ block&.call(self)
24
+
25
+ define_apply_task
26
+ define_setup_task
27
+ end
28
+
29
+ def define_setup_task
30
+ desc "Run all tasks of rbs_heuristic_prototype"
31
+
32
+ deps = [:"#{name}:apply"]
33
+ task("#{name}:setup": deps)
34
+ end
35
+
36
+ def define_apply_task
37
+ desc "Apply heuristic filters to prototype signatures"
38
+ task("#{name}:apply": :environment) do
39
+ path.find do |entry|
40
+ next unless entry.file?
41
+
42
+ env = FILTERS.inject(load_env(entry)) do |result, (_name, filter)|
43
+ filter.new(result).apply
44
+ end
45
+
46
+ write_env(entry, env)
47
+ end
48
+ end
49
+ end
50
+
51
+ def load_env(path)
52
+ loader = RBS::EnvironmentLoader.new(core_root: nil)
53
+ loader.add(path:)
54
+ RBS::Environment.from_loader(loader)
55
+ end
56
+
57
+ def write_env(path, env)
58
+ path.open("wt") do |out|
59
+ RBS::Writer.new(out:).write(env.declarations)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RbsHeuristicPrototype
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rbs_heuristic_prototype/filters/active_model_validations_filter"
4
+ require_relative "rbs_heuristic_prototype/filters/boolean_methods_filter"
5
+ require_relative "rbs_heuristic_prototype/filters/symbol_array_constants_filter"
6
+ require_relative "rbs_heuristic_prototype/rake_task"
7
+ require_relative "rbs_heuristic_prototype/version"
8
+
9
+ module RbsHeuristicPrototype
10
+ class Error < StandardError; end
11
+ # Your code goes here...
12
+ end
@@ -0,0 +1,190 @@
1
+ ---
2
+ sources:
3
+ - type: git
4
+ name: ruby/gem_rbs_collection
5
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
6
+ remote: https://github.com/ruby/gem_rbs_collection.git
7
+ repo_dir: gems
8
+ path: ".gem_rbs_collection"
9
+ gems:
10
+ - name: abbrev
11
+ version: '0'
12
+ source:
13
+ type: stdlib
14
+ - name: actionpack
15
+ version: '6.0'
16
+ source:
17
+ type: git
18
+ name: ruby/gem_rbs_collection
19
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
20
+ remote: https://github.com/ruby/gem_rbs_collection.git
21
+ repo_dir: gems
22
+ - name: actionview
23
+ version: '6.0'
24
+ source:
25
+ type: git
26
+ name: ruby/gem_rbs_collection
27
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
28
+ remote: https://github.com/ruby/gem_rbs_collection.git
29
+ repo_dir: gems
30
+ - name: activemodel
31
+ version: '7.0'
32
+ source:
33
+ type: git
34
+ name: ruby/gem_rbs_collection
35
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
36
+ remote: https://github.com/ruby/gem_rbs_collection.git
37
+ repo_dir: gems
38
+ - name: activerecord
39
+ version: '7.0'
40
+ source:
41
+ type: git
42
+ name: ruby/gem_rbs_collection
43
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
44
+ remote: https://github.com/ruby/gem_rbs_collection.git
45
+ repo_dir: gems
46
+ - name: activesupport
47
+ version: '7.0'
48
+ source:
49
+ type: git
50
+ name: ruby/gem_rbs_collection
51
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
52
+ remote: https://github.com/ruby/gem_rbs_collection.git
53
+ repo_dir: gems
54
+ - name: ast
55
+ version: '2.4'
56
+ source:
57
+ type: git
58
+ name: ruby/gem_rbs_collection
59
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
60
+ remote: https://github.com/ruby/gem_rbs_collection.git
61
+ repo_dir: gems
62
+ - name: cgi
63
+ version: '0'
64
+ source:
65
+ type: stdlib
66
+ - name: concurrent-ruby
67
+ version: '1.1'
68
+ source:
69
+ type: git
70
+ name: ruby/gem_rbs_collection
71
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
72
+ remote: https://github.com/ruby/gem_rbs_collection.git
73
+ repo_dir: gems
74
+ - name: date
75
+ version: '0'
76
+ source:
77
+ type: stdlib
78
+ - name: i18n
79
+ version: '1.10'
80
+ source:
81
+ type: git
82
+ name: ruby/gem_rbs_collection
83
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
84
+ remote: https://github.com/ruby/gem_rbs_collection.git
85
+ repo_dir: gems
86
+ - name: json
87
+ version: '0'
88
+ source:
89
+ type: stdlib
90
+ - name: logger
91
+ version: '0'
92
+ source:
93
+ type: stdlib
94
+ - name: minitest
95
+ version: '0'
96
+ source:
97
+ type: stdlib
98
+ - name: monitor
99
+ version: '0'
100
+ source:
101
+ type: stdlib
102
+ - name: mutex_m
103
+ version: '0'
104
+ source:
105
+ type: stdlib
106
+ - name: nokogiri
107
+ version: '1.11'
108
+ source:
109
+ type: git
110
+ name: ruby/gem_rbs_collection
111
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
112
+ remote: https://github.com/ruby/gem_rbs_collection.git
113
+ repo_dir: gems
114
+ - name: optparse
115
+ version: '0'
116
+ source:
117
+ type: stdlib
118
+ - name: parallel
119
+ version: '1.20'
120
+ source:
121
+ type: git
122
+ name: ruby/gem_rbs_collection
123
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
124
+ remote: https://github.com/ruby/gem_rbs_collection.git
125
+ repo_dir: gems
126
+ - name: pathname
127
+ version: '0'
128
+ source:
129
+ type: stdlib
130
+ - name: rack
131
+ version: '2.2'
132
+ source:
133
+ type: git
134
+ name: ruby/gem_rbs_collection
135
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
136
+ remote: https://github.com/ruby/gem_rbs_collection.git
137
+ repo_dir: gems
138
+ - name: rails-dom-testing
139
+ version: '2.0'
140
+ source:
141
+ type: git
142
+ name: ruby/gem_rbs_collection
143
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
144
+ remote: https://github.com/ruby/gem_rbs_collection.git
145
+ repo_dir: gems
146
+ - name: railties
147
+ version: '6.0'
148
+ source:
149
+ type: git
150
+ name: ruby/gem_rbs_collection
151
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
152
+ remote: https://github.com/ruby/gem_rbs_collection.git
153
+ repo_dir: gems
154
+ - name: rainbow
155
+ version: '3.0'
156
+ source:
157
+ type: git
158
+ name: ruby/gem_rbs_collection
159
+ revision: 80c41dad0190d5968841b8e892523e5031fa3eb1
160
+ remote: https://github.com/ruby/gem_rbs_collection.git
161
+ repo_dir: gems
162
+ - name: rbs
163
+ version: 3.1.0
164
+ source:
165
+ type: rubygems
166
+ - name: rdoc
167
+ version: '0'
168
+ source:
169
+ type: stdlib
170
+ - name: singleton
171
+ version: '0'
172
+ source:
173
+ type: stdlib
174
+ - name: tempfile
175
+ version: '0'
176
+ source:
177
+ type: stdlib
178
+ - name: time
179
+ version: '0'
180
+ source:
181
+ type: stdlib
182
+ - name: tsort
183
+ version: '0'
184
+ source:
185
+ type: stdlib
186
+ - name: uri
187
+ version: '0'
188
+ source:
189
+ type: stdlib
190
+ gemfile_lock_path: Gemfile.lock
@@ -0,0 +1,20 @@
1
+ # Download sources
2
+ sources:
3
+ - type: git
4
+ name: ruby/gem_rbs_collection
5
+ remote: https://github.com/ruby/gem_rbs_collection.git
6
+ revision: main
7
+ repo_dir: gems
8
+
9
+ # You can specify local directories as sources also.
10
+ # - type: local
11
+ # path: path/to/your/local/repository
12
+
13
+ # A directory to install the downloaded RBSs
14
+ path: .gem_rbs_collection
15
+
16
+ gems:
17
+ # Skip loading rbs gem's RBS.
18
+ # It's unnecessary if you don't use rbs as a library.
19
+ - name: steep
20
+ ignore: true
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rbs_heuristic_prototype/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rbs_heuristic_prototype"
7
+ spec.version = RbsHeuristicPrototype::VERSION
8
+ spec.authors = ["Takeshi KOMIYA"]
9
+ spec.email = ["i.tkomiya@gmail.com"]
10
+
11
+ spec.summary = "Update prototype signature files by heuristic rules"
12
+ spec.description = "Update prototype signature files by heuristic rules"
13
+ spec.homepage = "https://github.com/tk0miya/rbs_heuristic_prototype"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 3.1.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ spec.metadata["changelog_uri"] = spec.homepage
20
+
21
+ spec.files = Dir.chdir(__dir__) do
22
+ `git ls-files -z`.split("\x0").reject do |f|
23
+ (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
24
+ end
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_dependency "rbs"
31
+ end
data/sig/gems/rake.rbs ADDED
@@ -0,0 +1,6 @@
1
+ module Rake
2
+ class TaskLib
3
+ def desc: (String) -> void
4
+ def task: (Hash[Symbol, Symbol | Array[Symbol]]) ?{ () -> void } -> void
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module RbsHeuristicPrototype
2
+ class InstallGenerator < Rails::Generators::Base
3
+ def create_raketask: () -> void
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ module RbsHeuristicPrototype
2
+ module Filters
3
+ class ActiveModelValidationsFilter < Base
4
+ @klass: Class?
5
+
6
+ def process_class: (RBS::AST::Declarations::Class decl) -> RBS::AST::Declarations::Class
7
+ def process_member: (RBS::AST::Members::t member) -> RBS::AST::Members::t
8
+ def process_method_type: (RBS::MethodType method_type) -> RBS::MethodType
9
+ def process_type: (RBS::Types::Function type) -> RBS::Types::Function
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ module RbsHeuristicPrototype
2
+ module Filters
3
+ class Base
4
+ attr_reader env: RBS::Environment
5
+
6
+ def initialize: (RBS::Environment env) -> void
7
+ def apply: () -> RBS::Environment
8
+ def process: (RBS::AST::Declarations::t decl) -> RBS::AST::Declarations::t
9
+ def process_module: (RBS::AST::Declarations::Module decl) -> RBS::AST::Declarations::Module
10
+ def process_class: (RBS::AST::Declarations::Class decl) -> RBS::AST::Declarations::Class
11
+ def process_constant: (RBS::AST::Declarations::Constant member) -> RBS::AST::Declarations::Constant
12
+ def process_member: (RBS::AST::Members::t member) -> RBS::AST::Members::t
13
+ def const_get: (RBS::AST::Declarations::t decl) -> Class?
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,9 @@
1
+ module RbsHeuristicPrototype
2
+ module Filters
3
+ class BooleanMethodsFilter < Base
4
+ def process_member: (RBS::AST::Members::t member) -> RBS::AST::Members::t
5
+ def process_method_type: (RBS::MethodType method_type) -> RBS::MethodType
6
+ def process_type: (RBS::Types::Function type) -> RBS::Types::Function
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ module RbsHeuristicPrototype
2
+ module Filters
3
+ class SymbolArrayConstantsFilter < Base
4
+ def process_constant: (RBS::AST::Declarations::Constant constant) -> RBS::AST::Declarations::Constant
5
+ def process_constant_type: (RBS::Types::t type) -> RBS::Types::ClassInstance
6
+ def symbol_array?: (RBS::Types::t type) -> bool
7
+ def array?: (RBS::Types::t type) -> bool
8
+ def symbol_union?: (RBS::Types::t type) -> bool
9
+ def symbol?: (RBS::Types::t type) -> bool
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ module RbsHeuristicPrototype
2
+ class RakeTask < Rake::TaskLib
3
+ FILTERS: Hash[Symbol, singleton(Filters::Base)]
4
+
5
+ attr_reader name: Symbol
6
+ attr_reader path: Pathname
7
+
8
+ @name: Symbol
9
+ @path: Pathname
10
+
11
+ def initialize: (?Symbol name) ?{ (RakeTask) -> void } -> void
12
+ def define_setup_task: () -> void
13
+ def define_apply_task: () -> void
14
+ def load_env: (Pathname path) -> RBS::Environment
15
+ def write_env: (Pathname path, RBS::Environment env) -> void
16
+ end
17
+ end
@@ -0,0 +1,4 @@
1
+ module RbsHeuristicPrototype
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbs_heuristic_prototype
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Takeshi KOMIYA
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-07-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rbs
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: Update prototype signature files by heuristic rules
28
+ email:
29
+ - i.tkomiya@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".rspec"
35
+ - ".rubocop.yml"
36
+ - ".vscode/extensions.json"
37
+ - ".vscode/settings.json"
38
+ - CODE_OF_CONDUCT.md
39
+ - Gemfile
40
+ - Gemfile.lock
41
+ - LICENSE.txt
42
+ - README.md
43
+ - Rakefile
44
+ - Steepfile
45
+ - lib/generators/rbs_heuristic_prototype/install_generator.rb
46
+ - lib/rbs_heuristic_prototype.rb
47
+ - lib/rbs_heuristic_prototype/filters/active_model_validations_filter.rb
48
+ - lib/rbs_heuristic_prototype/filters/base.rb
49
+ - lib/rbs_heuristic_prototype/filters/boolean_methods_filter.rb
50
+ - lib/rbs_heuristic_prototype/filters/symbol_array_constants_filter.rb
51
+ - lib/rbs_heuristic_prototype/rake_task.rb
52
+ - lib/rbs_heuristic_prototype/version.rb
53
+ - rbs_collection.lock.yaml
54
+ - rbs_collection.yaml
55
+ - rbs_heuristic_prototype.gemspec
56
+ - sig/gems/rake.rbs
57
+ - sig/generators/rbs_heuristic_prototype/install_generator.rbs
58
+ - sig/rbs_heuristic_prototype.rbs
59
+ - sig/rbs_heuristic_prototype/filters/active_model_validations_filter.rbs
60
+ - sig/rbs_heuristic_prototype/filters/base.rbs
61
+ - sig/rbs_heuristic_prototype/filters/boolean_methods_filter.rbs
62
+ - sig/rbs_heuristic_prototype/filters/symbol_array_constants_filter.rbs
63
+ - sig/rbs_heuristic_prototype/rake_task.rbs
64
+ homepage: https://github.com/tk0miya/rbs_heuristic_prototype
65
+ licenses:
66
+ - MIT
67
+ metadata:
68
+ homepage_uri: https://github.com/tk0miya/rbs_heuristic_prototype
69
+ source_code_uri: https://github.com/tk0miya/rbs_heuristic_prototype
70
+ changelog_uri: https://github.com/tk0miya/rbs_heuristic_prototype
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 3.1.0
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubygems_version: 3.4.10
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Update prototype signature files by heuristic rules
90
+ test_files: []