ruby-next-core 0.9.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +14 -4
- data/lib/.rbnext/2.3/ruby-next/commands/core_ext.rb +167 -0
- data/lib/.rbnext/2.3/ruby-next/commands/nextify.rb +198 -0
- data/lib/.rbnext/2.3/ruby-next/language/eval.rb +66 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/base.rb +121 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/endless_range.rb +63 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/pattern_matching.rb +944 -0
- data/lib/.rbnext/2.3/ruby-next/utils.rb +65 -0
- data/lib/ruby-next.rb +8 -6
- data/lib/ruby-next/cli.rb +2 -2
- data/lib/ruby-next/commands/core_ext.rb +1 -1
- data/lib/ruby-next/core.rb +27 -21
- data/lib/ruby-next/core/array/deconstruct.rb +9 -9
- data/lib/ruby-next/core/array/difference_union_intersection.rb +12 -12
- data/lib/ruby-next/core/constants/no_matching_pattern_error.rb +3 -3
- data/lib/ruby-next/core/enumerable/filter.rb +8 -8
- data/lib/ruby-next/core/enumerable/filter_map.rb +25 -25
- data/lib/ruby-next/core/enumerable/tally.rb +7 -7
- data/lib/ruby-next/core/enumerator/produce.rb +12 -12
- data/lib/ruby-next/core/hash/deconstruct_keys.rb +9 -9
- data/lib/ruby-next/core/hash/except.rb +11 -0
- data/lib/ruby-next/core/hash/merge.rb +8 -8
- data/lib/ruby-next/core/kernel/then.rb +2 -2
- data/lib/ruby-next/core/proc/compose.rb +11 -11
- data/lib/ruby-next/core/string/split.rb +6 -6
- data/lib/ruby-next/core/struct/deconstruct.rb +2 -2
- data/lib/ruby-next/core/struct/deconstruct_keys.rb +17 -17
- data/lib/ruby-next/core/symbol/end_with.rb +4 -4
- data/lib/ruby-next/core/symbol/start_with.rb +4 -4
- data/lib/ruby-next/core/time/ceil.rb +6 -6
- data/lib/ruby-next/core/time/floor.rb +4 -4
- data/lib/ruby-next/core/unboundmethod/bind_call.rb +4 -4
- data/lib/ruby-next/core_ext.rb +1 -1
- data/lib/ruby-next/language.rb +12 -1
- data/lib/ruby-next/language/parser.rb +0 -3
- data/lib/ruby-next/language/proposed.rb +3 -0
- data/lib/ruby-next/language/rewriters/args_forward.rb +23 -20
- data/lib/ruby-next/language/rewriters/base.rb +1 -1
- data/lib/ruby-next/language/rewriters/endless_method.rb +25 -3
- data/lib/ruby-next/language/rewriters/find_pattern.rb +44 -0
- data/lib/ruby-next/language/rewriters/method_reference.rb +1 -1
- data/lib/ruby-next/language/rewriters/pattern_matching.rb +102 -12
- data/lib/ruby-next/language/rewriters/right_hand_assignment.rb +1 -1
- data/lib/ruby-next/language/rewriters/safe_navigation.rb +87 -0
- data/lib/ruby-next/language/rewriters/shorthand_hash.rb +47 -0
- data/lib/ruby-next/language/rewriters/squiggly_heredoc.rb +36 -0
- data/lib/ruby-next/language/unparser.rb +0 -14
- data/lib/ruby-next/logging.rb +1 -1
- data/lib/ruby-next/rubocop.rb +15 -9
- data/lib/ruby-next/setup_self.rb +22 -0
- data/lib/ruby-next/version.rb +1 -1
- data/lib/uby-next.rb +8 -4
- metadata +20 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cab7345f16f61d3a35a307024885c4b9a0055bb946f473bdd5a386b27175ec2
|
4
|
+
data.tar.gz: c3b2004bf5cd1b9dd49d2a7892bd3e88472a632f4cdc8da310bdb56fb96171d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f6b3d6f64e0303e1b69fa5a99ececcf605c7413285c05feb03d9308da8449296fbea96b8779a3ac6b72dca8351ac10cd20f11161b1581ac6a60a85d951ca0d3
|
7
|
+
data.tar.gz: 44e5f05020cae47e13d1a89627c94d890b07daccd1e7dcf51e2e4e0eed208fca2c946e4db674f53fa0581477a368e80c73474ffc657a53f55c1e962bd3d668ba
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,28 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.10.0 (2020-09-02)
|
6
|
+
|
7
|
+
- Add proposed shorthand Hash syntax. ([@palkan][])
|
8
|
+
|
9
|
+
You can try it: `x = 1; y = 2; data = {x, y}`.
|
10
|
+
|
11
|
+
- Add leading argument support to args forwarding. ([@palkan][])
|
12
|
+
|
13
|
+
`def a(...) b(1, ...); end`.
|
14
|
+
|
15
|
+
- Add `Hash#except`. ([@palkan][])
|
16
|
+
|
17
|
+
`{a: 1, b: 2}.except(:a) == {b: 2}`
|
18
|
+
|
19
|
+
- Add find pattern support. ([@palkan][])
|
20
|
+
|
21
|
+
Now you can do: `[0, 1, 2] in [*, 1 => a, *c]`.
|
22
|
+
|
23
|
+
- Add Ruby 2.2 support. ([@palkan][])
|
24
|
+
|
25
|
+
With support for safe navigation operator (`&.`) and squiggly heredocs (`<<~TXT`).
|
26
|
+
|
5
27
|
## 0.9.2 (2020-06-24)
|
6
28
|
|
7
29
|
- Support passing rewriters to CLI. ([@sl4vr][])
|
data/README.md
CHANGED
@@ -37,6 +37,8 @@ Read more about the motivation behind the Ruby Next in this post: [Ruby Next: Ma
|
|
37
37
|
- Ruby gems
|
38
38
|
- [anyway_config](https://github.com/palkan/anyway_config)
|
39
39
|
- [graphql-fragment_cache](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache)
|
40
|
+
- Rails applications
|
41
|
+
- [anycable_rails_demo](https://github.com/anycable/anycable_rails_demo)
|
40
42
|
- mruby
|
41
43
|
- [ACLI](https://github.com/palkan/acli)
|
42
44
|
|
@@ -68,7 +70,7 @@ Core provides **polyfills** for Ruby core classes APIs via Refinements (default
|
|
68
70
|
Language is responsible for **transpiling** edge Ruby syntax into older versions. It could be done
|
69
71
|
programmatically or via CLI. It also could be done in runtime.
|
70
72
|
|
71
|
-
Currently, Ruby Next supports Ruby versions 2.
|
73
|
+
Currently, Ruby Next supports Ruby versions 2.2+, including JRuby 9.2.8+ and TruffleRuby 20.1+ (with some limitations). Support for EOL versions (<2.5) slightly differs though ([see below](#using-with-eol-rubies)).
|
72
74
|
|
73
75
|
Please, [open an issue](https://github.com/ruby-next/ruby-next/issues/new/choose) or join the discussion in the existing ones if you would like us to support older Ruby versions.
|
74
76
|
|
@@ -139,7 +141,7 @@ The following _rule of thumb_ is recommended when choosing between refinements a
|
|
139
141
|
- Using core extensions could be considered for application development (no need to think about `using RubyNext`); this approach could potentially lead to conflicts with dependencies (if these dependencies are not using refinements 🙂)
|
140
142
|
- Use core extensions if refinements are not supported by your platform
|
141
143
|
|
142
|
-
**NOTE:**
|
144
|
+
**NOTE:** _Edge_ APIs (i.e., from the Ruby's master branch) are included by default.
|
143
145
|
|
144
146
|
[**The list of supported APIs.**][features_core]
|
145
147
|
|
@@ -427,6 +429,8 @@ You must set `TargetRubyVersion: next` to make RuboCop use a Ruby Next parser.
|
|
427
429
|
|
428
430
|
Alternatively, you can load the patch from the command line by running: `rubocop -r ruby-next/rubocop ...`.
|
429
431
|
|
432
|
+
We recommend using the latest RuboCop version, 'cause it has support for new nodes built-in.
|
433
|
+
|
430
434
|
Also, when pre-transpiling source code with `ruby-next nextify`, we suggest ignoring the transpiled files:
|
431
435
|
|
432
436
|
```yml
|
@@ -439,7 +443,7 @@ AllCops:
|
|
439
443
|
|
440
444
|
## Using with EOL Rubies
|
441
445
|
|
442
|
-
We currently provide support for Ruby 2.3 and 2.4.
|
446
|
+
We currently provide support for Ruby 2.2, 2.3 and 2.4.
|
443
447
|
|
444
448
|
Ruby Next itself relies on 2.5 features and contains polyfills only for version 2.5+ (and that won't change).
|
445
449
|
Thus, to make it work with <2.5 we need to backport some APIs ourselves.
|
@@ -469,6 +473,8 @@ RUBY_NEXT_CORE_STRATEGY=backports ruby-next nextify lib/
|
|
469
473
|
|
470
474
|
**NOTE:** Make sure you have `backports` gem installed globally or added to your bundle (if you're using `bundle exec ruby-next ...`).
|
471
475
|
|
476
|
+
**NOTE:** For Ruby 2.2, safe navigation operator (`&.`) and squiggly heredocs (`<<~TXT`) support is provided.
|
477
|
+
|
472
478
|
## Proposed and edge features
|
473
479
|
|
474
480
|
Ruby Next aims to bring edge and proposed features to Ruby community before they (hopefully) reach an official Ruby release.
|
@@ -502,12 +508,16 @@ require "ruby-next/language/runtime"
|
|
502
508
|
|
503
509
|
- "Endless" method definition (`def foo() = 42`) ([#16746](https://bugs.ruby-lang.org/issues/16746)).
|
504
510
|
|
505
|
-
- Right-hand assignment (`13.divmod(5) => a,b`) ([#15921](https://bugs.ruby-lang.org/issues/15921))
|
511
|
+
- Right-hand assignment (`13.divmod(5) => a,b`) ([#15921](https://bugs.ruby-lang.org/issues/15921)).
|
512
|
+
|
513
|
+
- Find pattern (`[0, 1, 2] in [*, 1 => a, *c]`) ([#16828](https://bugs.ruby-lang.org/issues/16828)).
|
506
514
|
|
507
515
|
### Supported proposed features
|
508
516
|
|
509
517
|
- _Method reference_ operator (`.:`) ([#13581](https://bugs.ruby-lang.org/issues/13581)).
|
510
518
|
|
519
|
+
- Shorthand Hash notation (`data = {x, y}`) ([#15236](https://bugs.ruby-lang.org/issues/15236)).
|
520
|
+
|
511
521
|
## Contributing
|
512
522
|
|
513
523
|
Bug reports and pull requests are welcome on GitHub at [https://github.com/ruby-next/ruby-next](ttps://github.com/ruby-next/ruby-next).
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "pathname"
|
5
|
+
|
6
|
+
module RubyNext
|
7
|
+
module Commands
|
8
|
+
class CoreExt < Base
|
9
|
+
using RubyNext
|
10
|
+
|
11
|
+
attr_reader :out_path, :min_version, :names, :list, :filter, :original_command
|
12
|
+
alias list? list
|
13
|
+
|
14
|
+
def run
|
15
|
+
log "Select core extensions for Ruby v#{min_version}" \
|
16
|
+
"#{filter ? " and matching #{filter.inspect}" : ""}"
|
17
|
+
|
18
|
+
matching_patches.then do |patches|
|
19
|
+
next print_list(patches) if list?
|
20
|
+
generate_core_ext(patches)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse!(args)
|
25
|
+
print_help = false
|
26
|
+
@min_version = MIN_SUPPORTED_VERSION
|
27
|
+
@original_command = "ruby-next core_ext #{args.join(" ")}"
|
28
|
+
@names = []
|
29
|
+
@list = false
|
30
|
+
@out_path = File.join(Dir.pwd, "core_ext.rb")
|
31
|
+
|
32
|
+
optparser = base_parser do |opts|
|
33
|
+
opts.banner = "Usage: ruby-next core_ext [options]"
|
34
|
+
|
35
|
+
opts.on("-o", "--output=OUTPUT", "Specify output file or stdout (default: ./core_ext.rb)") do |val|
|
36
|
+
@out_path = val
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("-l", "--list", "List all available extensions") do
|
40
|
+
@list = true
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("--min-version=VERSION", "Specify the minimum Ruby version to support") do |val|
|
44
|
+
@min_version = Gem::Version.new(val)
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on("-n", "--name=NAME", "Filter extensions by name") do |val|
|
48
|
+
names << val
|
49
|
+
end
|
50
|
+
|
51
|
+
opts.on("-h", "--help", "Print help") do
|
52
|
+
print_help = true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
optparser.parse!(args)
|
57
|
+
|
58
|
+
if print_help
|
59
|
+
$stdout.puts optparser.help
|
60
|
+
exit 0
|
61
|
+
end
|
62
|
+
|
63
|
+
@filter = /(#{names.join("|")})/i unless names.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def matching_patches
|
69
|
+
RubyNext::Core.patches.extensions
|
70
|
+
.values
|
71
|
+
.flatten
|
72
|
+
.select do |patch|
|
73
|
+
next if min_version && Gem::Version.new(patch.version) <= min_version
|
74
|
+
next if filter && !filter.match?(patch.name)
|
75
|
+
true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def print_list(patches)
|
80
|
+
grouped_patches = patches.group_by(&:version).sort_by(&:first)
|
81
|
+
grouped_patches.each do |(group, patches)|
|
82
|
+
$stdout.puts "#{group} extensions:\n"
|
83
|
+
$stdout.puts patches.sort_by(&:name).map { |patch| " - #{patch.name}" }.join("\n")
|
84
|
+
$stdout.puts "\n"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def generate_core_ext(patches)
|
89
|
+
grouped_patches = patches.group_by(&:mod).sort_by { |(mod, patch)| mod.singleton_class? ? mod.inspect : mod.name }
|
90
|
+
|
91
|
+
buffer = []
|
92
|
+
|
93
|
+
buffer << "# frozen_string_literal: true\n"
|
94
|
+
|
95
|
+
buffer << generation_meta
|
96
|
+
|
97
|
+
grouped_patches.each do |mod, patches|
|
98
|
+
singleton = mod.singleton_class?
|
99
|
+
extend_name = singleton ? patches.first.singleton.name : mod.name
|
100
|
+
prepend_name = singleton ? "#{patches.first.singleton.name}.singleton_class" : mod.name
|
101
|
+
|
102
|
+
prepended, extended = patches.partition(&:prepend?)
|
103
|
+
|
104
|
+
prepended.map do |patch|
|
105
|
+
name = "RubyNext::Core::#{patch.name}"
|
106
|
+
|
107
|
+
buffer << <<-RUBY
|
108
|
+
module #{name}
|
109
|
+
#{indent_and_trim(patch.body)}
|
110
|
+
end
|
111
|
+
#{prepend_name}.prepend #{name}
|
112
|
+
RUBY
|
113
|
+
|
114
|
+
name
|
115
|
+
end
|
116
|
+
|
117
|
+
class_or_module = mod.is_a?(Class) ? "class" : "module"
|
118
|
+
|
119
|
+
buffer << "#{class_or_module} #{extend_name}"
|
120
|
+
|
121
|
+
buffer << " class << self" if singleton
|
122
|
+
|
123
|
+
indent_size = singleton ? 4 : 2
|
124
|
+
|
125
|
+
buffer << extended.map do |patch|
|
126
|
+
indent_and_trim(patch.body, indent_size)
|
127
|
+
end.join("\n\n")
|
128
|
+
|
129
|
+
buffer << " end" if singleton
|
130
|
+
|
131
|
+
buffer << "end\n"
|
132
|
+
end
|
133
|
+
|
134
|
+
contents = buffer.join("\n")
|
135
|
+
|
136
|
+
return $stdout.puts(contents) if out_path == "stdout"
|
137
|
+
|
138
|
+
unless CLI.dry_run?
|
139
|
+
FileUtils.mkdir_p File.dirname(out_path)
|
140
|
+
File.write(out_path, contents)
|
141
|
+
end
|
142
|
+
|
143
|
+
log "Generated: #{out_path}"
|
144
|
+
end
|
145
|
+
|
146
|
+
def generation_meta
|
147
|
+
<<-MSG
|
148
|
+
# Generated by Ruby Next v#{RubyNext::VERSION} using the following command:
|
149
|
+
#
|
150
|
+
# #{original_command}
|
151
|
+
#
|
152
|
+
MSG
|
153
|
+
end
|
154
|
+
|
155
|
+
def indent_and_trim(src, size = 2)
|
156
|
+
new_src = src.dup
|
157
|
+
# indent code using <size> spaces
|
158
|
+
new_src.gsub!(/^/, " " * size)
|
159
|
+
# remove empty lines
|
160
|
+
new_src.gsub!(/^\s+$/, "")
|
161
|
+
# remove traling blank lines
|
162
|
+
new_src.delete_suffix!("\n")
|
163
|
+
new_src
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "pathname"
|
5
|
+
|
6
|
+
require "ruby-next/language"
|
7
|
+
|
8
|
+
module RubyNext
|
9
|
+
module Commands
|
10
|
+
class Nextify < Base
|
11
|
+
using RubyNext
|
12
|
+
|
13
|
+
attr_reader :lib_path, :paths, :out_path, :min_version, :single_version, :specified_rewriters
|
14
|
+
|
15
|
+
def run
|
16
|
+
log "RubyNext core strategy: #{RubyNext::Core.strategy}"
|
17
|
+
log "RubyNext transpile mode: #{RubyNext::Language.mode}"
|
18
|
+
|
19
|
+
remove_rbnext!
|
20
|
+
|
21
|
+
@min_version ||= MIN_SUPPORTED_VERSION
|
22
|
+
|
23
|
+
paths.each do |path|
|
24
|
+
contents = File.read(path)
|
25
|
+
transpile path, contents
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse!(args)
|
30
|
+
print_help = false
|
31
|
+
print_rewriters = false
|
32
|
+
rewriter_names = []
|
33
|
+
@single_version = false
|
34
|
+
|
35
|
+
optparser = base_parser do |opts|
|
36
|
+
opts.banner = "Usage: ruby-next nextify DIRECTORY_OR_FILE [options]"
|
37
|
+
|
38
|
+
opts.on("-o", "--output=OUTPUT", "Specify output directory or file or stdout") do |val|
|
39
|
+
@out_path = val
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on("--min-version=VERSION", "Specify the minimum Ruby version to support") do |val|
|
43
|
+
@min_version = Gem::Version.new(val)
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on("--single-version", "Only create one version of a file (for the earliest Ruby version)") do
|
47
|
+
@single_version = true
|
48
|
+
end
|
49
|
+
|
50
|
+
opts.on("--edge", "Enable edge (master) Ruby features") do |val|
|
51
|
+
require "ruby-next/language/edge"
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.on("--proposed", "Enable proposed/experimental Ruby features") do |val|
|
55
|
+
require "ruby-next/language/proposed"
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on(
|
59
|
+
"--transpile-mode=MODE",
|
60
|
+
"Transpiler mode (ast or rewrite). Default: ast"
|
61
|
+
) do |val|
|
62
|
+
Language.mode = val.to_sym
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on("--[no-]refine", "Do not inject `using RubyNext`") do |val|
|
66
|
+
Core.strategy = :core_ext unless val
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("--list-rewriters", "List available rewriters") do |val|
|
70
|
+
print_rewriters = true
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on("--rewrite=REWRITERS...", "Specify particular Ruby features to rewrite") do |val|
|
74
|
+
rewriter_names << val
|
75
|
+
end
|
76
|
+
|
77
|
+
opts.on("-h", "--help", "Print help") do
|
78
|
+
print_help = true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
optparser.parse!(args)
|
83
|
+
|
84
|
+
@lib_path = args[0]
|
85
|
+
|
86
|
+
if print_help
|
87
|
+
$stdout.puts optparser.help
|
88
|
+
exit 0
|
89
|
+
end
|
90
|
+
|
91
|
+
if print_rewriters
|
92
|
+
Language.rewriters.each do |rewriter|
|
93
|
+
$stdout.puts "#{rewriter::NAME} (\"#{rewriter::SYNTAX_PROBE}\")"
|
94
|
+
end
|
95
|
+
exit 0
|
96
|
+
end
|
97
|
+
|
98
|
+
unless ((!lib_path.nil?) || nil) && lib_path.then(&File.method(:exist?))
|
99
|
+
$stdout.puts "Path not found: #{lib_path}"
|
100
|
+
$stdout.puts optparser.help
|
101
|
+
exit 2
|
102
|
+
end
|
103
|
+
|
104
|
+
if rewriter_names.any? && min_version
|
105
|
+
$stdout.puts "--rewrite cannot be used with --min-version simultaneously"
|
106
|
+
exit 2
|
107
|
+
end
|
108
|
+
|
109
|
+
@specified_rewriters =
|
110
|
+
if rewriter_names.any?
|
111
|
+
begin
|
112
|
+
Language.select_rewriters(*rewriter_names)
|
113
|
+
rescue Language::RewriterNotFoundError => error
|
114
|
+
$stdout.puts error.message
|
115
|
+
$stdout.puts "Try --list-rewriters to see list of available rewriters"
|
116
|
+
exit 2
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
@paths =
|
121
|
+
if File.directory?(lib_path)
|
122
|
+
Dir[File.join(lib_path, "**/*.rb")]
|
123
|
+
elsif File.file?(lib_path)
|
124
|
+
[lib_path].tap do |_|
|
125
|
+
@lib_path = File.dirname(lib_path)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def transpile(path, contents, version: min_version)
|
133
|
+
rewriters = specified_rewriters || Language.rewriters.select { |rw| rw.unsupported_version?(version) }
|
134
|
+
|
135
|
+
context = Language::TransformContext.new
|
136
|
+
|
137
|
+
new_contents = Language.transform contents, context: context, rewriters: rewriters
|
138
|
+
|
139
|
+
return unless context.dirty?
|
140
|
+
|
141
|
+
versions = context.sorted_versions
|
142
|
+
version = versions.shift
|
143
|
+
|
144
|
+
# First, store already transpiled contents in the minimum required version dir
|
145
|
+
save new_contents, path, version
|
146
|
+
|
147
|
+
return if versions.empty? || single_version?
|
148
|
+
|
149
|
+
# Then, generate the source code for the next version
|
150
|
+
transpile path, contents, version: version
|
151
|
+
end
|
152
|
+
|
153
|
+
def save(contents, path, version)
|
154
|
+
return $stdout.puts(contents) if stdout?
|
155
|
+
|
156
|
+
paths = [Pathname.new(path).relative_path_from(Pathname.new(lib_path))]
|
157
|
+
|
158
|
+
paths.unshift(version.segments[0..1].join(".")) unless single_version?
|
159
|
+
|
160
|
+
next_path =
|
161
|
+
if next_dir_path.end_with?(".rb")
|
162
|
+
out_path
|
163
|
+
else
|
164
|
+
File.join(next_dir_path, *paths)
|
165
|
+
end
|
166
|
+
|
167
|
+
unless CLI.dry_run?
|
168
|
+
FileUtils.mkdir_p File.dirname(next_path)
|
169
|
+
|
170
|
+
File.write(next_path, contents)
|
171
|
+
end
|
172
|
+
|
173
|
+
log "Generated: #{next_path}"
|
174
|
+
end
|
175
|
+
|
176
|
+
def remove_rbnext!
|
177
|
+
return if CLI.dry_run? || stdout?
|
178
|
+
|
179
|
+
return unless File.directory?(next_dir_path)
|
180
|
+
|
181
|
+
log "Remove old files: #{next_dir_path}"
|
182
|
+
FileUtils.rm_r(next_dir_path)
|
183
|
+
end
|
184
|
+
|
185
|
+
def next_dir_path
|
186
|
+
@next_dir_path ||= (out_path || File.join(lib_path, RUBY_NEXT_DIR))
|
187
|
+
end
|
188
|
+
|
189
|
+
def stdout?
|
190
|
+
out_path == "stdout"
|
191
|
+
end
|
192
|
+
|
193
|
+
def single_version?
|
194
|
+
single_version || specified_rewriters
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|