rbs 0.3.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +7 -1
- data/.gitignore +1 -1
- data/CHANGELOG.md +39 -0
- data/COPYING +1 -1
- data/Gemfile +16 -2
- data/README.md +87 -48
- data/Rakefile +54 -22
- data/bin/rbs-prof +9 -0
- data/bin/run_in_md.rb +49 -0
- data/bin/test_runner.rb +0 -2
- data/docs/sigs.md +6 -6
- data/docs/stdlib.md +3 -5
- data/docs/syntax.md +6 -3
- data/goodcheck.yml +65 -0
- data/lib/rbs.rb +3 -0
- data/lib/rbs/ast/declarations.rb +115 -14
- data/lib/rbs/ast/members.rb +41 -17
- data/lib/rbs/cli.rb +315 -122
- data/lib/rbs/constant.rb +4 -4
- data/lib/rbs/constant_table.rb +51 -45
- data/lib/rbs/definition.rb +175 -59
- data/lib/rbs/definition_builder.rb +802 -604
- data/lib/rbs/environment.rb +352 -210
- data/lib/rbs/environment_walker.rb +14 -23
- data/lib/rbs/errors.rb +184 -3
- data/lib/rbs/factory.rb +14 -0
- data/lib/rbs/parser.y +95 -27
- data/lib/rbs/prototype/rb.rb +119 -117
- data/lib/rbs/prototype/rbi.rb +5 -3
- data/lib/rbs/prototype/runtime.rb +34 -7
- data/lib/rbs/substitution.rb +12 -1
- data/lib/rbs/test.rb +82 -3
- data/lib/rbs/test/errors.rb +5 -1
- data/lib/rbs/test/hook.rb +133 -259
- data/lib/rbs/test/observer.rb +17 -0
- data/lib/rbs/test/setup.rb +35 -19
- data/lib/rbs/test/setup_helper.rb +29 -0
- data/lib/rbs/test/spy.rb +0 -321
- data/lib/rbs/test/tester.rb +116 -0
- data/lib/rbs/test/type_check.rb +43 -7
- data/lib/rbs/type_name_resolver.rb +58 -0
- data/lib/rbs/types.rb +94 -2
- data/lib/rbs/validator.rb +51 -0
- data/lib/rbs/variance_calculator.rb +12 -2
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +127 -91
- data/rbs.gemspec +0 -9
- data/schema/annotation.json +14 -0
- data/schema/comment.json +26 -0
- data/schema/decls.json +353 -0
- data/schema/function.json +87 -0
- data/schema/location.json +56 -0
- data/schema/members.json +248 -0
- data/schema/methodType.json +44 -0
- data/schema/types.json +299 -0
- data/stdlib/benchmark/benchmark.rbs +151 -151
- data/stdlib/builtin/encoding.rbs +2 -0
- data/stdlib/builtin/enumerable.rbs +4 -4
- data/stdlib/builtin/enumerator.rbs +3 -1
- data/stdlib/builtin/fiber.rbs +5 -1
- data/stdlib/builtin/file.rbs +0 -3
- data/stdlib/builtin/io.rbs +4 -4
- data/stdlib/builtin/proc.rbs +1 -2
- data/stdlib/builtin/symbol.rbs +1 -1
- data/stdlib/builtin/thread.rbs +2 -2
- data/stdlib/csv/csv.rbs +4 -6
- data/stdlib/fiber/fiber.rbs +117 -0
- data/stdlib/json/json.rbs +1 -1
- data/stdlib/logger/formatter.rbs +23 -0
- data/stdlib/logger/log_device.rbs +39 -0
- data/stdlib/logger/logger.rbs +507 -0
- data/stdlib/logger/period.rbs +7 -0
- data/stdlib/logger/severity.rbs +8 -0
- data/stdlib/mutex_m/mutex_m.rbs +77 -0
- data/stdlib/pathname/pathname.rbs +6 -6
- data/stdlib/prime/integer-extension.rbs +1 -1
- data/stdlib/prime/prime.rbs +44 -44
- data/stdlib/pty/pty.rbs +159 -0
- data/stdlib/tmpdir/tmpdir.rbs +1 -1
- metadata +28 -116
- data/lib/rbs/test/test_helper.rb +0 -183
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2e86d5e87d89f97eed8e2674aa5f5035413179ba104a5cb265ab748268c51fe
|
4
|
+
data.tar.gz: 9d58fa00413d5a334496ee688bbc72520e1911558f39ad2d01b180b790e5d894
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 328850c1f912cd7cc45e1c210140c098206f668c0400a817cde00e36dec1591ec235b5b6a1255b0e66d585745d4f6f7effeb09f28ae2a7536091852f9ba8bc89
|
7
|
+
data.tar.gz: 96bc5adc81b98d723a98d20dcbeef13424fb0a4267272ff1ad6daaab5ef310f24c038f4e23793253beade1e55a00a6eece457697a3a4ec62413f08b7c42ace99
|
data/.github/workflows/ruby.yml
CHANGED
@@ -24,5 +24,11 @@ jobs:
|
|
24
24
|
ruby -v
|
25
25
|
gem install bundler
|
26
26
|
bin/setup
|
27
|
-
bundle exec rake
|
27
|
+
bundle exec rake test
|
28
|
+
bundle exec rake stdlib_test
|
29
|
+
bundle exec rake rubocop
|
30
|
+
bundle exec rake validate
|
31
|
+
bundle exec rake test_doc
|
28
32
|
bundle exec rake build
|
33
|
+
RBS_GENERATE_TEST_PATH=/tmp/Array_test.rb bundle exec rake 'generate:stdlib_test[Array]'
|
34
|
+
ruby -c /tmp/Array_test.rb
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,45 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.8.0 (2020-08-01)
|
6
|
+
|
7
|
+
* Signature updates for `Enumerator` and `PTY`
|
8
|
+
* Fix prototype rb/rbi error handling [#349](https://github.com/ruby/rbs/pull/349)
|
9
|
+
* Runtime test improvements [#344](https://github.com/ruby/rbs/pull/344), [#343](https://github.com/ruby/rbs/pull/343)
|
10
|
+
* Add `...` syntax [#342](https://github.com/ruby/rbs/pull/342)
|
11
|
+
|
12
|
+
## 0.7.0 (2020-07-20)
|
13
|
+
|
14
|
+
* Add `DefinitionBuilder#one_instance_ancestors` and `DefinitionBuilder#one_singleton_ancestors` [#341](https://github.com/ruby/rbs/pull/341)
|
15
|
+
* Bug fix in ConstantTable [#340](https://github.com/ruby/rbs/pull/340)
|
16
|
+
* Make `rbs validate` faster [#338](https://github.com/ruby/rbs/pull/338)
|
17
|
+
* Dedup methods generated by `rbs prototype rb` [#334](https://github.com/ruby/rbs/pull/334)
|
18
|
+
|
19
|
+
## 0.6.0 (2020-07-12)
|
20
|
+
|
21
|
+
* Signature update for `Logger`.
|
22
|
+
* Clean `Environment#inspect`. [#331](https://github.com/ruby/rbs/pull/331)
|
23
|
+
* Module self type syntax update. [#329](https://github.com/ruby/rbs/pull/329)
|
24
|
+
* Better validation. [#328](https://github.com/ruby/rbs/pull/328)
|
25
|
+
* Parser performance improvement. [#327](https://github.com/ruby/rbs/pull/327)
|
26
|
+
* Runtime type checking performance improvements with sampling [#323](https://github.com/ruby/rbs/pull/323)
|
27
|
+
|
28
|
+
## 0.5.0 (2020-07-04)
|
29
|
+
|
30
|
+
* Signature updates for `Mutex_m`, `IO`, and `Enumerable`.
|
31
|
+
* Syntax update. [#307](https://github.com/ruby/rbs/pull/307)
|
32
|
+
* AST command prints _absolute_ type names with file name filtering. [#312](https://github.com/ruby/rbs/pull/312)
|
33
|
+
* Improve CLI message. [#309](https://github.com/ruby/rbs/pull/309)
|
34
|
+
|
35
|
+
## 0.4.0 (2020-06-15)
|
36
|
+
|
37
|
+
* Signature update for `Fiber`, `Encoding`, and `Enumerator`.
|
38
|
+
* Fix syntax error for underscore and `!` `?` [#304](https://github.com/ruby/rbs/pull/304)
|
39
|
+
* Improved return type inference in `rbs prototype rb` [#303](https://github.com/ruby/rbs/pull/303)
|
40
|
+
* Skip anonymous modules/classes in `rbs prototype runtime` [#302](https://github.com/ruby/rbs/pull/302)
|
41
|
+
* Fix `--require-relative` option in `rbs prototype runtime` [#299](https://github.com/ruby/rbs/pull/299)
|
42
|
+
* Add JSON schema for `rbs ast` [#295](https://github.com/ruby/rbs/pull/295)
|
43
|
+
|
5
44
|
## 0.3.1 (2020-05-22)
|
6
45
|
|
7
46
|
* Fix constant resolution again [#289](https://github.com/ruby/rbs/pull/289)
|
data/COPYING
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
rbs is copyrighted free software by Soutaro Matsumoto <matsumoto@soutaro.com>.
|
2
2
|
You can redistribute it and/or modify it under either the terms of the
|
3
3
|
2-clause BSDL (see the file BSDL), or the conditions below:
|
4
4
|
|
data/Gemfile
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in
|
3
|
+
# Specify your gem's dependencies in rbs.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
|
6
|
+
# Development dependencies
|
7
|
+
gem "rake"
|
8
|
+
gem "minitest"
|
9
|
+
gem "racc"
|
10
|
+
gem "rubocop"
|
11
|
+
gem "rubocop-rubycw"
|
12
|
+
gem "minitest-reporters"
|
13
|
+
gem "json"
|
14
|
+
gem "json-schema"
|
15
|
+
gem 'stackprof'
|
16
|
+
gem "goodcheck"
|
17
|
+
|
18
|
+
# Test gems
|
19
|
+
gem "rbs-amber", path: "test/assets/test-gem"
|
20
|
+
|
data/README.md
CHANGED
@@ -1,79 +1,118 @@
|
|
1
1
|
# RBS
|
2
2
|
|
3
|
-
RBS
|
4
|
-
|
3
|
+
RBS is a language to describe the structure of Ruby programs.
|
4
|
+
You can write down the definition of a class or module: methods defined in the class, instance variables and their types, and inheritance/mix-in relations.
|
5
|
+
It also allows declaring constants and global variables.
|
5
6
|
|
6
|
-
|
7
|
+
The following is a small example of RBS for a chat app.
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
<!-- run-start:a.rbs:bundle exec rbs -I a.rbs validate -->
|
10
|
+
```rbs
|
11
|
+
module ChatApp
|
12
|
+
VERSION: String
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
```
|
14
|
+
class User
|
15
|
+
attr_reader login: String
|
16
|
+
attr_reader email: String
|
15
17
|
|
16
|
-
|
18
|
+
def initialize: (login: String, email: String) -> void
|
19
|
+
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
$ rbs method ::Object tap
|
23
|
-
```
|
21
|
+
class Bot
|
22
|
+
attr_reader name: String
|
23
|
+
attr_reader email: String
|
24
|
+
attr_reader owner: User
|
24
25
|
|
25
|
-
|
26
|
+
def initialize: (name: String, owner: User) -> void
|
27
|
+
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
29
|
+
class Message
|
30
|
+
attr_reader id: String
|
31
|
+
attr_reader string: String
|
32
|
+
attr_reader from: User | Bot # `|` means union types: `#from` can be `User` or `Bot`
|
33
|
+
attr_reader reply_to: Message? # `?` means optional type: `#reply_to` can be `nil`
|
30
34
|
|
31
|
-
|
35
|
+
def initialize: (from: User | Bot, string: String) -> void
|
32
36
|
|
33
|
-
|
37
|
+
def reply: (from: User | Bot, string: String) -> Message
|
38
|
+
end
|
34
39
|
|
40
|
+
class Channel
|
41
|
+
attr_reader name: String
|
42
|
+
attr_reader messages: Array[Message]
|
43
|
+
attr_reader users: Array[User]
|
44
|
+
attr_reader bots: Array[Bot]
|
45
|
+
|
46
|
+
def initialize: (name: String) -> void
|
47
|
+
|
48
|
+
def each_member: () { (User | Bot) -> void } -> void # `{` and `}` means block.
|
49
|
+
| () -> Enumerable[User | Bot, void] # Method can be overloaded.
|
50
|
+
end
|
51
|
+
end
|
35
52
|
```
|
36
|
-
|
37
|
-
$ rbs ancestors --singleton Array # (Array.class.ancestors)
|
38
|
-
```
|
53
|
+
<!-- run-end -->
|
39
54
|
|
40
|
-
|
41
|
-
The name of the command is borrowed from `Class#ancestors`, but the semantics is a bit different.
|
42
|
-
The `ancestors` command is more precise (I believe).
|
55
|
+
## Installation
|
43
56
|
|
44
|
-
|
57
|
+
Install the `rbs` gem. `$ gem install rbs` from the command line, or add a line in your `Gemfile`.
|
45
58
|
|
46
|
-
```
|
47
|
-
|
48
|
-
$ rbs methods --singleton ::Object # Object.methods
|
59
|
+
```rb
|
60
|
+
gem "rbs"
|
49
61
|
```
|
50
62
|
|
51
|
-
|
63
|
+
## CLI
|
52
64
|
|
53
|
-
|
65
|
+
The gem ships with the `rbs` command line tool to demonstrate what it can do and help develop RBS.
|
54
66
|
|
55
|
-
```
|
56
|
-
$ rbs
|
57
|
-
$ rbs
|
67
|
+
```bash
|
68
|
+
$ rbs version
|
69
|
+
$ rbs list
|
70
|
+
$ rbs ancestors ::Object
|
71
|
+
$ rbs methods ::Object
|
72
|
+
$ rbs method Object then
|
58
73
|
```
|
59
74
|
|
60
|
-
|
75
|
+
## Library
|
61
76
|
|
62
|
-
|
77
|
+
There are two important concepts, _environment_ and _definition_.
|
63
78
|
|
64
|
-
|
79
|
+
An _environment_ is a dictionary that keeps track of all declarations. What is the declaration associated with `String` class? An _environment_ will give you the answer.
|
65
80
|
|
66
|
-
|
81
|
+
A _definition_ gives you the detail of the class. What is the type of the return value of `gsub` method of the `String` class? The _definition_ for `String` class knows the list of methods it provides and their types.
|
67
82
|
|
68
|
-
|
69
|
-
$ rbs -r set list
|
70
|
-
```
|
83
|
+
The following is a small code to retrieve the definition of the `String#gsub` method.
|
71
84
|
|
72
|
-
|
85
|
+
<!-- run-start:a.rb:bundle exec ruby a.rb -->
|
86
|
+
```rb
|
87
|
+
require "rbs"
|
73
88
|
|
89
|
+
loader = RBS::EnvironmentLoader.new()
|
90
|
+
|
91
|
+
# loader.add(path: Pathname("sig")) # Load .rbs files from `sig` directory
|
92
|
+
# loader.add(library: "pathname") # Load pathname library
|
93
|
+
|
94
|
+
environment = RBS::Environment.from_loader(loader).resolve_type_names
|
95
|
+
|
96
|
+
# ::String
|
97
|
+
string = RBS::TypeName.new(name: :String, namespace: RBS::Namespace.root)
|
98
|
+
|
99
|
+
# Class declaration for ::String
|
100
|
+
decl = environment.class_decls[string]
|
101
|
+
|
102
|
+
# Builder provides the translation from `declaration` to `definition`
|
103
|
+
builder = RBS::DefinitionBuilder.new(env: environment)
|
104
|
+
|
105
|
+
# Definition of instance of String
|
106
|
+
instance = builder.build_instance(string)
|
107
|
+
# Print the types of `gsub` method
|
108
|
+
puts instance.methods[:gsub].method_types.join("\n")
|
109
|
+
|
110
|
+
# Definition of singleton of String
|
111
|
+
singleton = builder.build_singleton(string)
|
112
|
+
# No `gsub` method for String singleton
|
113
|
+
puts singleton.methods[:gsub]
|
74
114
|
```
|
75
|
-
|
76
|
-
```
|
115
|
+
<!-- run-end -->
|
77
116
|
|
78
117
|
## Guides
|
79
118
|
|
@@ -90,4 +129,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
90
129
|
|
91
130
|
## Contributing
|
92
131
|
|
93
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/
|
132
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/rbs.
|
data/Rakefile
CHANGED
@@ -9,10 +9,23 @@ Rake::TestTask.new(:test) do |t|
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
multitask :default => [:test, :stdlib_test, :rubocop, :validate]
|
12
|
+
multitask :default => [:test, :stdlib_test, :rubocop, :validate, :test_doc]
|
13
|
+
|
14
|
+
task :test_doc => :parser do
|
15
|
+
files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
16
|
+
`git ls-files -z`.split("\x0").select do |file| Pathname(file).extname == ".md" end
|
17
|
+
end
|
18
|
+
|
19
|
+
sh "ruby bin/run_in_md.rb #{files.join(" ")}"
|
20
|
+
end
|
13
21
|
|
14
22
|
task :validate => :parser do
|
15
23
|
sh "rbs validate"
|
24
|
+
|
25
|
+
FileList["stdlib/*"].each do |path|
|
26
|
+
next if path =~ %r{stdlib/builtin}
|
27
|
+
sh "rbs -r#{File.basename(path)} validate"
|
28
|
+
end
|
16
29
|
end
|
17
30
|
|
18
31
|
FileList["test/stdlib/**/*_test.rb"].each do |test|
|
@@ -41,11 +54,11 @@ namespace :generate do
|
|
41
54
|
raise "Class name is necessary. e.g. rake 'generate:stdlib_test[String]'"
|
42
55
|
end
|
43
56
|
|
44
|
-
path = Pathname("test/stdlib/#{klass}_test.rb")
|
57
|
+
path = Pathname(ENV["RBS_GENERATE_TEST_PATH"] || "test/stdlib/#{klass}_test.rb")
|
45
58
|
raise "#{path} already exists!" if path.exist?
|
46
59
|
|
47
60
|
require "erb"
|
48
|
-
require "
|
61
|
+
require "rbs"
|
49
62
|
|
50
63
|
class TestTemplateBuilder
|
51
64
|
attr_reader :klass, :env
|
@@ -53,35 +66,54 @@ namespace :generate do
|
|
53
66
|
def initialize(klass)
|
54
67
|
@klass = klass
|
55
68
|
|
56
|
-
|
57
|
-
|
69
|
+
loader = RBS::EnvironmentLoader.new
|
70
|
+
Dir['stdlib/*'].each do |lib|
|
71
|
+
next if lib.end_with?('builtin')
|
72
|
+
|
73
|
+
loader.add(library: File.basename(lib))
|
74
|
+
end
|
75
|
+
@env = RBS::Environment.from_loader(loader).resolve_type_names
|
58
76
|
end
|
59
77
|
|
60
78
|
def call
|
61
79
|
ERB.new(<<~ERB, trim_mode: "-").result(binding)
|
62
80
|
require_relative "test_helper"
|
63
81
|
|
64
|
-
|
65
|
-
|
82
|
+
<%- unless class_methods.empty? -%>
|
83
|
+
class <%= klass %>SingletonTest < Minitest::Test
|
84
|
+
include TypeAssertions
|
85
|
+
|
66
86
|
# library "pathname", "set", "securerandom" # Declare library signatures to load
|
67
|
-
|
87
|
+
testing "singleton(::<%= klass %>)"
|
88
|
+
|
68
89
|
<%- class_methods.each do |method_name, definition| %>
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
90
|
+
def test_<%= test_name_for(method_name) %>
|
91
|
+
<%- definition.method_types.each do |method_type| -%>
|
92
|
+
assert_send_type "<%= method_type %>",
|
93
|
+
<%= klass %>, :<%= method_name %>
|
94
|
+
<%- end -%>
|
74
95
|
end
|
75
96
|
<%- end -%>
|
97
|
+
end
|
98
|
+
<%- end -%>
|
99
|
+
|
100
|
+
<%- unless instance_methods.empty? -%>
|
101
|
+
class <%= klass %>Test < Minitest::Test
|
102
|
+
include TypeAssertions
|
103
|
+
|
104
|
+
# library "pathname", "set", "securerandom" # Declare library signatures to load
|
105
|
+
testing "::<%= klass %>"
|
106
|
+
|
76
107
|
<%- instance_methods.each do |method_name, definition| %>
|
77
108
|
def test_<%= test_name_for(method_name) %>
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
109
|
+
<%- definition.method_types.each do |method_type| -%>
|
110
|
+
assert_send_type "<%= method_type %>",
|
111
|
+
<%= klass %>.new, :<%= method_name %>
|
112
|
+
<%- end -%>
|
82
113
|
end
|
83
114
|
<%- end -%>
|
84
115
|
end
|
116
|
+
<%- end -%>
|
85
117
|
ERB
|
86
118
|
end
|
87
119
|
|
@@ -117,18 +149,18 @@ namespace :generate do
|
|
117
149
|
end
|
118
150
|
|
119
151
|
def type_name
|
120
|
-
@type_name ||=
|
152
|
+
@type_name ||= RBS::TypeName.new(name: klass.to_sym, namespace: RBS::Namespace.new(path: [], absolute: true))
|
121
153
|
end
|
122
154
|
|
123
155
|
def class_methods
|
124
|
-
@class_methods ||=
|
125
|
-
definition.implemented_in
|
156
|
+
@class_methods ||= RBS::DefinitionBuilder.new(env: env).build_singleton(type_name).methods.select {|_, definition|
|
157
|
+
definition.implemented_in == type_name
|
126
158
|
}
|
127
159
|
end
|
128
160
|
|
129
161
|
def instance_methods
|
130
|
-
@instance_methods ||=
|
131
|
-
definition.implemented_in
|
162
|
+
@instance_methods ||= RBS::DefinitionBuilder.new(env: env).build_instance(type_name).methods.select {|_, definition|
|
163
|
+
definition.implemented_in == type_name
|
132
164
|
}
|
133
165
|
end
|
134
166
|
end
|
data/bin/rbs-prof
ADDED
data/bin/run_in_md.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require "tmpdir"
|
2
|
+
require "shellwords"
|
3
|
+
|
4
|
+
ARGV.each do |path|
|
5
|
+
puts "~~~~~~~ Checking #{path} ~~~~~~"
|
6
|
+
content = File.read(path)
|
7
|
+
|
8
|
+
snippets = []
|
9
|
+
lines = []
|
10
|
+
content.lines.each.with_index do |line, index|
|
11
|
+
case line
|
12
|
+
when /run-start:/
|
13
|
+
lines = [[line, index+1]]
|
14
|
+
when /run-end/
|
15
|
+
lines << [line, index+1]
|
16
|
+
snippets << lines
|
17
|
+
lines = []
|
18
|
+
else
|
19
|
+
lines << [line, index+1]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
snippets.each do |lines|
|
24
|
+
puts ">>> Code detected: "
|
25
|
+
hd, _, *code_lines, _, _ = lines
|
26
|
+
|
27
|
+
head = hd[0]
|
28
|
+
head.gsub!(/^<!-- +/, "").gsub!(/ +-->$/, "")
|
29
|
+
_,name,command = head.split(/:/)
|
30
|
+
|
31
|
+
puts "# command=#{Shellwords.split(command).inspect}"
|
32
|
+
puts "# name=#{name}"
|
33
|
+
puts code_lines.map {|line, i| "#{"%4d" % i} #{line}" }.join
|
34
|
+
|
35
|
+
code = code_lines.map(&:first).join
|
36
|
+
|
37
|
+
puts ">>> Running..."
|
38
|
+
Dir.mktmpdir do |dir|
|
39
|
+
File.write(File.join(dir, name), code)
|
40
|
+
pid = spawn({ "BUNDLE_GEMFILE" => File.join(__dir__, "../Gemfile") },
|
41
|
+
*Shellwords.split(command),
|
42
|
+
chdir: dir)
|
43
|
+
|
44
|
+
_, status = Process.waitpid2(pid)
|
45
|
+
|
46
|
+
status.success? or raise "Failed to execute code: #{code_lines.join}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|