ruby-next-core 0.5.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -59,7 +59,7 @@ module RubyNext
59
59
  def unsupported_syntax?
60
60
  save_verbose, $VERBOSE = $VERBOSE, nil
61
61
  eval_mid = Kernel.respond_to?(:eval_without_ruby_next) ? :eval_without_ruby_next : :eval
62
- Kernel.send eval_mid, self::SYNTAX_PROBE
62
+ Kernel.send eval_mid, self::SYNTAX_PROBE, nil, __FILE__, __LINE__
63
63
  false
64
64
  rescue SyntaxError, NameError
65
65
  true
@@ -78,10 +78,6 @@ module RubyNext
78
78
  def transform(source)
79
79
  Language.transform(source, rewriters: [self], using: false)
80
80
  end
81
-
82
- def warn_custom_parser_required_for(feature)
83
- RubyNext.warn(CUSTOM_PARSER_REQUIRED % feature)
84
- end
85
81
  end
86
82
 
87
83
  attr_reader :locals
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyNext
4
+ module Language
5
+ module Rewriters
6
+ class EndlessMethod < Base
7
+ SYNTAX_PROBE = "obj = Object.new; def obj.foo() = 42"
8
+ MIN_SUPPORTED_VERSION = Gem::Version.new("2.8.0")
9
+
10
+ def on_def_e(node)
11
+ context.track! self
12
+
13
+ replace(node.loc.assignment, "; ")
14
+ insert_after(node.loc.expression, "; end")
15
+
16
+ process(
17
+ node.updated(
18
+ :def,
19
+ node.children
20
+ )
21
+ )
22
+ end
23
+
24
+ def on_defs_e(node)
25
+ context.track! self
26
+
27
+ replace(node.loc.assignment, "; ")
28
+ insert_after(node.loc.expression, "; end")
29
+
30
+ process(
31
+ node.updated(
32
+ :defs,
33
+ node.children
34
+ )
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -28,12 +28,6 @@ module RubyNext
28
28
  ]
29
29
  )
30
30
  end
31
-
32
- begin
33
- transform(SYNTAX_PROBE)
34
- rescue ::Parser::SyntaxError
35
- warn_custom_parser_required_for("method reference")
36
- end
37
31
  end
38
32
  end
39
33
  end
@@ -816,11 +816,12 @@ module RubyNext
816
816
  end
817
817
 
818
818
  def respond_to_missing?(mid, *)
819
- return true if mid.match?(/_(clause|array_element)/)
819
+ return true if mid.to_s.match?(/_(clause|array_element)/)
820
820
  super
821
821
  end
822
822
 
823
823
  def method_missing(mid, *args, &block)
824
+ mid = mid.to_s
824
825
  return case_eq_clause(*args) if mid.match?(/_clause$/)
825
826
  return case_eq_array_element(*args) if mid.match?(/_array_element$/)
826
827
  return case_eq_hash_element(*args) if mid.match?(/_hash_element$/)
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyNext
4
+ module Language
5
+ module Rewriters
6
+ class RightHandAssignment < Base
7
+ SYNTAX_PROBE = "1 + 2 => a"
8
+ MIN_SUPPORTED_VERSION = Gem::Version.new("2.8.0")
9
+
10
+ def on_rasgn(node)
11
+ context.track! self
12
+
13
+ val_node, asgn_node = *node
14
+
15
+ remove(val_node.loc.expression.end.join(asgn_node.loc.expression))
16
+ insert_before(val_node.loc.expression, "#{asgn_node.loc.expression.source} = ")
17
+
18
+ process(
19
+ asgn_node.updated(
20
+ nil,
21
+ asgn_node.children + [val_node]
22
+ )
23
+ )
24
+ end
25
+
26
+ def on_mrasgn(node)
27
+ context.track! self
28
+
29
+ lhs, rhs = *node
30
+
31
+ replace(lhs.loc.expression.end.join(rhs.loc.expression), ")")
32
+ insert_before(lhs.loc.expression, "#{rhs.loc.expression.source} = (")
33
+
34
+ process(
35
+ node.updated(
36
+ :masgn,
37
+ [rhs, lhs]
38
+ )
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Load rewriters only required for runtime transpiling
4
+
5
+ require "ruby-next/language/rewriters/runtime/dir"
6
+ RubyNext::Language.rewriters << RubyNext::Language::Rewriters::Dir
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyNext
4
+ module Language
5
+ module Rewriters
6
+ # Special rewriter for Ruby <=2.3, which doesn't support __dir__ in iseq.eval
7
+ class Dir < Base
8
+ SYNTAX_PROBE = "defined?(RubyVM::InstructionSequence) && RubyVM::InstructionSequence.compile('raise SyntaxError if __dir__.nil?', 'test.rb').eval"
9
+ MIN_SUPPORTED_VERSION = Gem::Version.new("2.4.0")
10
+
11
+ def on_send(node)
12
+ return super(node) unless node.children[1] == :__dir__
13
+
14
+ context.track! self
15
+
16
+ replace(node.loc.expression, "File.dirname(__FILE__)")
17
+
18
+ process(
19
+ node.updated(
20
+ nil,
21
+ [
22
+ s(:const, nil, :File),
23
+ :dirname,
24
+ s(:send, nil, "__FILE__")
25
+ ]
26
+ )
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -42,7 +42,7 @@ module RubyNext
42
42
  path
43
43
  end
44
44
 
45
- if defined?(JRUBY_VERSION)
45
+ if defined?(JRUBY_VERSION) || defined?(TruffleRuby)
46
46
  def evaluate(code, filepath)
47
47
  new_toplevel.eval(code, filepath)
48
48
  end
@@ -89,7 +89,8 @@ module Kernel
89
89
 
90
90
  alias_method :require_relative_without_ruby_next, :require_relative
91
91
  def require_relative(path)
92
- from = caller_locations(1..1).first.absolute_path || File.join(Dir.pwd, "main")
92
+ loc = caller_locations(1..1).first
93
+ from = loc.absolute_path || loc.path || File.join(Dir.pwd, "main")
93
94
  realpath = File.absolute_path(
94
95
  File.join(
95
96
  File.dirname(File.absolute_path(from)),
@@ -5,6 +5,21 @@ require "ruby-next"
5
5
 
6
6
  module RubyNext
7
7
  module Language
8
+ # Module responsible for transpiling a library at load time
9
+ module GemTranspiler
10
+ def self.maybe_transpile(root_dir, lib_dir, target_dir)
11
+ return if File.directory?(target_dir)
12
+
13
+ Dir.chdir(root_dir) do
14
+ unless system("bundle exec ruby-next nextify ./#{lib_dir} -o #{target_dir} > /dev/null 2>&1")
15
+ RubyNext.warn "Traspiled files are missing in: #{target_dir}. \n" \
16
+ "Make sure you have gem 'ruby-next' in your Gemfile to auto-transpile the required files from source on load. " \
17
+ "Otherwise the code from #{root_dir} may not work correctly."
18
+ end
19
+ end
20
+ end
21
+ end
22
+
8
23
  class << self
9
24
  unless method_defined?(:runtime?)
10
25
  def runtime?
@@ -12,7 +27,7 @@ module RubyNext
12
27
  end
13
28
  end
14
29
 
15
- def setup_gem_load_path(lib_dir = "lib", rbnext_dir: RUBY_NEXT_DIR)
30
+ def setup_gem_load_path(lib_dir = "lib", rbnext_dir: RUBY_NEXT_DIR, transpile: false)
16
31
  called_from = caller_locations(1, 1).first.path
17
32
  dirname = File.dirname(called_from)
18
33
 
@@ -29,6 +44,10 @@ module RubyNext
29
44
 
30
45
  return if Language.runtime? && Language.watch_dirs.include?(dirname)
31
46
 
47
+ next_dirname = File.join(dirname, rbnext_dir)
48
+
49
+ GemTranspiler.maybe_transpile(File.dirname(dirname), lib_dir, next_dirname) if transpile
50
+
32
51
  current_index = $LOAD_PATH.index(dirname)
33
52
 
34
53
  raise "Gem's lib is not in the $LOAD_PATH: #{dirname}" if current_index.nil?
@@ -38,7 +57,7 @@ module RubyNext
38
57
  loop do
39
58
  break unless version
40
59
 
41
- version_dir = File.join(dirname, rbnext_dir, version.segments[0..1].join("."))
60
+ version_dir = File.join(next_dirname, version.segments[0..1].join("."))
42
61
 
43
62
  if File.exist?(version_dir)
44
63
  $LOAD_PATH.insert current_index, version_dir
@@ -38,6 +38,6 @@ module RubyNext
38
38
  attr_reader :debug_filter
39
39
  end
40
40
 
41
- self.silence_warnings = ENV["RUBY_NEXT_WARN"] != "false"
41
+ self.silence_warnings = ENV["RUBY_NEXT_WARN"] == "false"
42
42
  self.debug_enabled = ENV["RUBY_NEXT_DEBUG"]
43
43
  end
@@ -1,7 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This file contains patches to RuboCop to support
4
- # edge features and fix some bugs with 2.7 syntax
4
+ # edge features and fix some bugs with 2.7+ syntax
5
+
6
+ require "parser/ruby-next/version"
7
+
8
+ module RuboCop
9
+ # Transform Ruby Next parser version to a float, e.g.: "2.8.0.1" => 2.801
10
+ RUBY_NEXT_VERSION = Parser::NEXT_VERSION.match(/(^\d+)\.(.+)$/)[1..-1].map { |part| part.delete(".") }.join(".").to_f
11
+
12
+ class TargetRuby
13
+ class RuboCopNextConfig < RuboCopConfig
14
+ private
15
+
16
+ def find_version
17
+ version = @config.for_all_cops["TargetRubyVersion"]
18
+ return unless version == "next"
19
+
20
+ RUBY_NEXT_VERSION
21
+ end
22
+ end
23
+
24
+ new_rubies = KNOWN_RUBIES + [RUBY_NEXT_VERSION]
25
+ remove_const :KNOWN_RUBIES
26
+ const_set :KNOWN_RUBIES, new_rubies
27
+
28
+ new_sources = [RuboCopNextConfig] + SOURCES
29
+ remove_const :SOURCES
30
+ const_set :SOURCES, new_sources
31
+ end
32
+ end
33
+
34
+ module RuboCop
35
+ class ProcessedSource
36
+ module ParserClassExt
37
+ def parser_class(version)
38
+ return super unless version == RUBY_NEXT_VERSION
39
+
40
+ require "parser/rubynext"
41
+ Parser::RubyNext
42
+ end
43
+ end
44
+
45
+ prepend ParserClassExt
46
+ end
47
+ end
5
48
 
6
49
  module RuboCop
7
50
  module AST
@@ -41,6 +84,32 @@ module RuboCop
41
84
  send(:"on_#{child.type}", child)
42
85
  end
43
86
  end
87
+
88
+ unless method_defined?(:on_def_e)
89
+ def on_def_e(node)
90
+ _name, _args_node, body_node = *node
91
+ send(:"on_#{body_node.type}", body_node)
92
+ end
93
+
94
+ def on_defs_e(node)
95
+ _definee_node, _name, _args_node, body_node = *node
96
+ send(:"on_#{body_node.type}", body_node)
97
+ end
98
+ end
99
+
100
+ unless method_defined?(:on_rasgn)
101
+ def on_rasgn(node)
102
+ val_node, asgn_node = *node
103
+ send(:"on_#{asgn_node.type}", asgn_node)
104
+ send(:"on_#{val_node.type}", val_node)
105
+ end
106
+
107
+ def on_mrasgn(node)
108
+ lhs, rhs = *node
109
+ send(:"on_#{lhs.type}", lhs)
110
+ send(:"on_#{rhs.type}", rhs)
111
+ end
112
+ end
44
113
  end
45
114
  end
46
115
  end
@@ -33,5 +33,35 @@ module RubyNext
33
33
  lines.unshift " 0: # source: #{path}"
34
34
  end
35
35
  end
36
+
37
+ # Returns true if modules refinement is supported in current version
38
+ def refine_modules?
39
+ @refine_modules ||=
40
+ begin
41
+ # Make sure that including modules within refinements works
42
+ # See https://github.com/oracle/truffleruby/issues/2026
43
+ eval <<~RUBY, TOPLEVEL_BINDING, __FILE__, __LINE__ + 1
44
+ module RubyNext::Utils::A; end
45
+ class RubyNext::Utils::B
46
+ include RubyNext::Utils::A
47
+ end
48
+
49
+ using(Module.new do
50
+ refine RubyNext::Utils::A do
51
+ include(Module.new do
52
+ def i_am_refinement
53
+ "yes, you are!"
54
+ end
55
+ end)
56
+ end
57
+ end)
58
+
59
+ RubyNext::Utils::B.new.i_am_refinement
60
+ RUBY
61
+ true
62
+ rescue TypeError, NoMethodError
63
+ false
64
+ end
65
+ end
36
66
  end
37
67
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyNext
4
- VERSION = "0.5.3"
4
+ VERSION = "0.9.0"
5
5
  end
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Activate all features
4
+ ENV["RUBY_NEXT_EDGE"] = "1"
5
+ ENV["RUBY_NEXT_PROPOSED"] = "1"
6
+
3
7
  require "ruby-next/language/runtime"
4
8
  require "ruby-next/core/runtime"
5
9
 
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-next-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-25 00:00:00.000000000 Z
11
+ date: 2020-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: parser
14
+ name: ruby-next-parser
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 2.7.0.5
19
+ version: 2.8.0.6
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 2.7.0.5
26
+ version: 2.8.0.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: unparser
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -84,14 +84,20 @@ files:
84
84
  - lib/ruby-next/core_ext.rb
85
85
  - lib/ruby-next/language.rb
86
86
  - lib/ruby-next/language/bootsnap.rb
87
+ - lib/ruby-next/language/edge.rb
87
88
  - lib/ruby-next/language/eval.rb
88
89
  - lib/ruby-next/language/parser.rb
90
+ - lib/ruby-next/language/proposed.rb
89
91
  - lib/ruby-next/language/rewriters/args_forward.rb
90
92
  - lib/ruby-next/language/rewriters/base.rb
93
+ - lib/ruby-next/language/rewriters/endless_method.rb
91
94
  - lib/ruby-next/language/rewriters/endless_range.rb
92
95
  - lib/ruby-next/language/rewriters/method_reference.rb
93
96
  - lib/ruby-next/language/rewriters/numbered_params.rb
94
97
  - lib/ruby-next/language/rewriters/pattern_matching.rb
98
+ - lib/ruby-next/language/rewriters/right_hand_assignment.rb
99
+ - lib/ruby-next/language/rewriters/runtime.rb
100
+ - lib/ruby-next/language/rewriters/runtime/dir.rb
95
101
  - lib/ruby-next/language/runtime.rb
96
102
  - lib/ruby-next/language/setup.rb
97
103
  - lib/ruby-next/language/unparser.rb
@@ -117,7 +123,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
123
  requirements:
118
124
  - - ">="
119
125
  - !ruby/object:Gem::Version
120
- version: 2.5.0
126
+ version: 2.3.0
121
127
  required_rubygems_version: !ruby/object:Gem::Requirement
122
128
  requirements:
123
129
  - - ">="