ruby-next-core 0.14.0 → 1.0.1

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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -0
  3. data/README.md +163 -56
  4. data/bin/mspec +11 -0
  5. data/lib/.rbnext/2.1/ruby-next/commands/nextify.rb +295 -0
  6. data/lib/.rbnext/2.1/ruby-next/core.rb +12 -4
  7. data/lib/.rbnext/2.1/ruby-next/language.rb +62 -12
  8. data/lib/.rbnext/2.3/ruby-next/commands/nextify.rb +97 -3
  9. data/lib/.rbnext/2.3/ruby-next/config.rb +79 -0
  10. data/lib/.rbnext/2.3/ruby-next/core/data.rb +163 -0
  11. data/lib/.rbnext/2.3/ruby-next/language/eval.rb +4 -4
  12. data/lib/.rbnext/2.3/ruby-next/language/rewriters/2.7/args_forward.rb +134 -0
  13. data/lib/.rbnext/2.3/ruby-next/language/rewriters/2.7/pattern_matching.rb +122 -47
  14. data/lib/.rbnext/2.3/ruby-next/language/rewriters/base.rb +6 -32
  15. data/lib/.rbnext/2.3/ruby-next/utils.rb +3 -22
  16. data/lib/.rbnext/2.6/ruby-next/core/data.rb +163 -0
  17. data/lib/.rbnext/2.7/ruby-next/core/data.rb +163 -0
  18. data/lib/.rbnext/2.7/ruby-next/core.rb +12 -4
  19. data/lib/.rbnext/2.7/ruby-next/language/paco_parsers/string_literals.rb +109 -0
  20. data/lib/.rbnext/2.7/ruby-next/language/rewriters/2.7/pattern_matching.rb +1095 -0
  21. data/lib/.rbnext/2.7/ruby-next/language/rewriters/text.rb +132 -0
  22. data/lib/.rbnext/3.2/ruby-next/commands/base.rb +55 -0
  23. data/lib/.rbnext/3.2/ruby-next/language/rewriters/2.7/pattern_matching.rb +1095 -0
  24. data/lib/.rbnext/3.2/ruby-next/rubocop.rb +210 -0
  25. data/lib/ruby-next/cli.rb +10 -15
  26. data/lib/ruby-next/commands/nextify.rb +99 -3
  27. data/lib/ruby-next/config.rb +31 -4
  28. data/lib/ruby-next/core/data.rb +163 -0
  29. data/lib/ruby-next/core/matchdata/deconstruct.rb +9 -0
  30. data/lib/ruby-next/core/matchdata/deconstruct_keys.rb +20 -0
  31. data/lib/ruby-next/core/matchdata/named_captures.rb +11 -0
  32. data/lib/ruby-next/core/proc/compose.rb +0 -1
  33. data/lib/ruby-next/core/refinement/import.rb +44 -36
  34. data/lib/ruby-next/core/time/deconstruct_keys.rb +30 -0
  35. data/lib/ruby-next/core.rb +11 -3
  36. data/lib/ruby-next/irb.rb +24 -0
  37. data/lib/ruby-next/language/bootsnap.rb +2 -25
  38. data/lib/ruby-next/language/eval.rb +4 -4
  39. data/lib/ruby-next/language/paco_parser.rb +7 -0
  40. data/lib/ruby-next/language/paco_parsers/base.rb +47 -0
  41. data/lib/ruby-next/language/paco_parsers/comments.rb +26 -0
  42. data/lib/ruby-next/language/paco_parsers/string_literals.rb +109 -0
  43. data/lib/ruby-next/language/parser.rb +31 -6
  44. data/lib/ruby-next/language/rewriters/2.5/rescue_within_block.rb +41 -0
  45. data/lib/ruby-next/language/rewriters/2.7/args_forward.rb +57 -0
  46. data/lib/ruby-next/language/rewriters/2.7/pattern_matching.rb +120 -45
  47. data/lib/ruby-next/language/rewriters/3.0/args_forward_leading.rb +2 -2
  48. data/lib/ruby-next/language/rewriters/3.1/oneline_pattern_parensless.rb +1 -1
  49. data/lib/ruby-next/language/rewriters/3.1/shorthand_hash.rb +2 -1
  50. data/lib/ruby-next/language/rewriters/3.2/anonymous_restargs.rb +104 -0
  51. data/lib/ruby-next/language/rewriters/abstract.rb +57 -0
  52. data/lib/ruby-next/language/rewriters/base.rb +6 -32
  53. data/lib/ruby-next/language/rewriters/edge/it_param.rb +58 -0
  54. data/lib/ruby-next/language/rewriters/edge.rb +12 -0
  55. data/lib/ruby-next/language/rewriters/proposed/bind_vars_pattern.rb +3 -0
  56. data/lib/ruby-next/language/rewriters/proposed/method_reference.rb +9 -20
  57. data/lib/ruby-next/language/rewriters/text.rb +132 -0
  58. data/lib/ruby-next/language/runtime.rb +9 -86
  59. data/lib/ruby-next/language/setup.rb +5 -2
  60. data/lib/ruby-next/language/unparser.rb +5 -0
  61. data/lib/ruby-next/language.rb +62 -12
  62. data/lib/ruby-next/pry.rb +90 -0
  63. data/lib/ruby-next/rubocop.rb +2 -0
  64. data/lib/ruby-next/utils.rb +3 -22
  65. data/lib/ruby-next/version.rb +1 -1
  66. data/lib/uby-next/irb.rb +3 -0
  67. data/lib/uby-next/pry.rb +3 -0
  68. data/lib/uby-next.rb +2 -2
  69. metadata +70 -10
@@ -1,33 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "parser/rubynext"
4
+ RubyNext::Language.parser_class = ::Parser::RubyNext
5
+
3
6
  module RubyNext
4
7
  module Language
5
8
  module Rewriters
6
- class MethodReference < Base
9
+ class MethodReference < Text
7
10
  NAME = "method-reference"
8
11
  SYNTAX_PROBE = "Language.:transform"
9
12
  MIN_SUPPORTED_VERSION = Gem::Version.new(RubyNext::NEXT_VERSION)
10
13
 
11
- def on_meth_ref(node)
12
- context.track! self
13
-
14
- receiver, mid = *node.children
15
-
16
- replace(
17
- node.children.first.loc.expression.end.join(
18
- node.loc.expression.end
19
- ),
20
- ".method(:#{mid})"
21
- )
14
+ def safe_rewrite(source)
15
+ source.gsub(/\.:([\w_]+)/) do |match|
16
+ context.track! self
22
17
 
23
- node.updated(
24
- :send,
25
- [
26
- receiver,
27
- :method,
28
- s(:sym, mid)
29
- ]
30
- )
18
+ ".method(:#{$1})"
19
+ end
31
20
  end
32
21
  end
33
22
  end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ruby-next/language/paco_parser"
4
+
5
+ module RubyNext
6
+ module Language
7
+ module Rewriters
8
+ class Text < Abstract
9
+ using RubyNext
10
+
11
+ class Normalizer < PacoParsers::Base
12
+ attr_reader :store
13
+
14
+ def initialize
15
+ @store = []
16
+ end
17
+
18
+ def normalizing(source)
19
+ many(
20
+ alt(
21
+ ruby_comment,
22
+ ruby_string,
23
+ ruby_code
24
+ )
25
+ ).parse(source, with_callstack: true)
26
+ .then(&:join)
27
+ .then do
28
+ if block_given?
29
+ yield _1
30
+ else
31
+ _1
32
+ end
33
+ end
34
+ .then do |new_source|
35
+ restore(new_source)
36
+ end
37
+ end
38
+
39
+ def ruby_comment
40
+ parse_comments.fmap do |result|
41
+ store << result
42
+ "# A#{store.size}Я\n"
43
+ end
44
+ end
45
+
46
+ def ruby_string
47
+ parse_strings.fmap do |result|
48
+ result.each_with_object([]) do |(type, str), acc|
49
+ if type == :literal
50
+ store << str
51
+ acc << "_A#{store.size}Я_"
52
+ else
53
+ acc << str
54
+ end
55
+ acc
56
+ end.join
57
+ end
58
+ end
59
+
60
+ def ruby_code
61
+ any_char
62
+ end
63
+
64
+ def restore(source)
65
+ source.gsub(/(?:\# |_)A(\d+)Я(?:_|\n)/m) do |*args|
66
+ store[$1.to_i - 1]
67
+ end
68
+ end
69
+
70
+ def parse_comments
71
+ memoize { PacoParsers::Comments.new.default }
72
+ end
73
+
74
+ def parse_strings
75
+ memoize { PacoParsers::StringLiterals.new.default }
76
+ end
77
+ end
78
+
79
+ # Base class for rewriting parsers which adds the #track! method
80
+ class PacoParser < PacoParsers::Base
81
+ attr_reader :rewriter, :context
82
+
83
+ def initialize(rewriter, context)
84
+ @rewriter = rewriter
85
+ @context = context
86
+ end
87
+
88
+ def track!
89
+ context.track!(rewriter)
90
+ end
91
+ end
92
+
93
+ class << self
94
+ def parser(&block)
95
+ @paco_parser = Class.new(PacoParser, &block)
96
+ end
97
+
98
+ def paco_parser
99
+ return @paco_parser if @paco_parser
100
+
101
+ superclass.paco_parser if superclass.respond_to?(:paco_parser)
102
+ end
103
+
104
+ def text?
105
+ true
106
+ end
107
+ end
108
+
109
+ # Rewrite source code by ignoring string literals and comments
110
+ def rewrite(source)
111
+ Normalizer.new.normalizing(source) do |normalized|
112
+ safe_rewrite(normalized)
113
+ end
114
+ end
115
+
116
+ def safe_rewrite(source)
117
+ source
118
+ end
119
+
120
+ private
121
+
122
+ def parse(source)
123
+ parser_class = self.class.paco_parser
124
+ raise "No parser defined for #{self.class}" unless parser_class
125
+
126
+ paco_parser = self.class.paco_parser.new(self, context)
127
+ paco_parser.parse(source)
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pathname"
3
+ require "require-hooks/setup"
4
4
 
5
5
  require "ruby-next"
6
- require "ruby-next/utils"
7
6
  require "ruby-next/language"
8
7
  require "ruby-next/language/eval"
9
8
 
@@ -16,102 +15,26 @@ module RubyNext
16
15
  using RubyNext
17
16
 
18
17
  class << self
19
- include Utils
20
-
21
- def load(path, wrap: false)
22
- raise "RubyNext cannot handle `load(smth, wrap: true)`" if wrap
23
-
24
- contents = File.read(path)
18
+ def load(path, contents)
19
+ contents ||= File.read(path)
25
20
  new_contents = transform contents
26
21
 
27
22
  RubyNext.debug_source new_contents, path
28
23
 
29
- evaluate(new_contents, path)
30
- true
24
+ new_contents
31
25
  end
32
26
 
33
27
  def transform(contents, **options)
34
28
  Language.transform(contents, rewriters: Language.current_rewriters, **options)
35
29
  end
36
-
37
- def feature_path(path)
38
- path = resolve_feature_path(path)
39
- return if path.nil?
40
- return if File.extname(path) != ".rb"
41
- return unless Language.transformable?(path)
42
- path
43
- end
44
-
45
- if defined?(JRUBY_VERSION) || defined?(TruffleRuby)
46
- def evaluate(code, filepath)
47
- new_toplevel.eval(code, filepath)
48
- end
49
-
50
- def new_toplevel
51
- # Create new "toplevel" binding to avoid lexical scope re-use
52
- # (aka "leaking refinements")
53
- eval "proc{binding}.call", TOPLEVEL_BINDING, __FILE__, __LINE__
54
- end
55
- else
56
- def evaluate(code, filepath)
57
- # This is workaround to solve the "leaking refinements" problem in MRI
58
- RubyVM::InstructionSequence.compile(code, filepath).then do |iseq|
59
- iseq.eval
60
- end
61
- end
62
- end
63
30
  end
64
31
  end
65
32
  end
66
33
  end
67
34
 
68
- # Patch Kernel to hijack require/require_relative/load/eval
69
- module Kernel
70
- module_function # rubocop:disable Style/ModuleFunction
71
-
72
- alias_method :require_without_ruby_next, :require
73
- def require(path)
74
- realpath = RubyNext::Language::Runtime.feature_path(path)
75
- return require_without_ruby_next(path) unless realpath
76
-
77
- return false if $LOADED_FEATURES.include?(realpath)
78
-
79
- $LOADED_FEATURES << realpath
80
-
81
- RubyNext::Language::Runtime.load(realpath)
82
-
83
- true
84
- rescue => e
85
- $LOADED_FEATURES.delete realpath
86
- RubyNext.warn "RubyNext failed to require '#{path}': #{e.message}"
87
- require_without_ruby_next(path)
88
- end
89
-
90
- alias_method :require_relative_without_ruby_next, :require_relative
91
- def require_relative(path)
92
- loc = caller_locations(1..1).first
93
- from = loc.absolute_path || loc.path || File.join(Dir.pwd, "main")
94
- realpath = File.absolute_path(
95
- File.join(
96
- File.dirname(File.absolute_path(from)),
97
- path
98
- )
99
- )
100
- require(realpath)
101
- rescue => e
102
- RubyNext.warn "RubyNext failed to require relative '#{path}' from #{from}: #{e.message}"
103
- require_relative_without_ruby_next(path)
104
- end
105
-
106
- alias_method :load_without_ruby_next, :load
107
- def load(path, wrap = false)
108
- realpath = RubyNext::Language::Runtime.feature_path(path)
109
-
110
- return load_without_ruby_next(path, wrap) unless realpath
111
-
112
- RubyNext::Language::Runtime.load(realpath, wrap: wrap)
113
- rescue => e
114
- RubyNext.warn "RubyNext failed to load '#{path}': #{e.message}"
115
- load_without_ruby_next(path)
116
- end
35
+ RequireHooks.source_transform(
36
+ patterns: RubyNext::Language.include_patterns,
37
+ exclude_patterns: RubyNext::Language.exclude_patterns
38
+ ) do |path, contents|
39
+ RubyNext::Language::Runtime.load(path, contents)
117
40
  end
@@ -12,7 +12,10 @@ module RubyNext
12
12
  return if File.directory?(target_dir)
13
13
 
14
14
  Dir.chdir(root_dir) do
15
- unless system("bundle exec ruby-next nextify ./#{lib_dir} -o #{target_dir} > /dev/null 2>&1")
15
+ command = "bundle exec ruby-next nextify " \
16
+ "./#{lib_dir} -o #{target_dir} --min-version=#{RubyNext.current_ruby_version}"
17
+
18
+ unless system("#{command} > /dev/null 2>&1")
16
19
  RubyNext.warn "Traspiled files are missing in: #{target_dir}. \n" \
17
20
  "Make sure you have gem 'ruby-next' in your Gemfile to auto-transpile the required files from source on load. " \
18
21
  "Otherwise the code from #{root_dir} may not work correctly."
@@ -43,7 +46,7 @@ module RubyNext
43
46
 
44
47
  dirname = File.realpath(dirname)
45
48
 
46
- return if Language.runtime? && Language.watch_dirs.include?(dirname)
49
+ return if Language.runtime? && Language.target_dir?(dirname)
47
50
 
48
51
  next_dirname = File.join(dirname, rbnext_dir)
49
52
 
@@ -5,6 +5,11 @@ save_verbose, $VERBOSE = $VERBOSE, nil
5
5
  require "parser/current"
6
6
  $VERBOSE = save_verbose
7
7
 
8
+ # For backward compatibility with older Unparser for EOL Rubies
9
+ if !Parser::Lexer.const_defined?(:ESCAPES)
10
+ Parser::Lexer::ESCAPES = Parser::LexerStrings::ESCAPES
11
+ end
12
+
8
13
  require "unparser"
9
14
 
10
15
  # For backward compatibility with older Unparser
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- gem "ruby-next-parser", ">= 2.8.0.3"
4
- gem "unparser", ">= 0.4.7"
3
+ # Checking gem specs doesn't work in ruby.wasm
4
+ unless RUBY_PLATFORM.match?(/wasm/)
5
+ gem "ruby-next-parser", ">= 2.8.0.3"
6
+ gem "unparser", ">= 0.4.7"
7
+ end
5
8
 
6
- require "set"
9
+ require "set" # rubocop:disable Lint/RedundantRequireStatement
7
10
 
8
11
  require "ruby-next"
9
12
 
@@ -62,8 +65,15 @@ module RubyNext
62
65
  end
63
66
 
64
67
  class << self
68
+ attr_reader :include_patterns
69
+ attr_reader :exclude_patterns
70
+
71
+ def watch_dirs
72
+ warn "[DEPRECATED] Use `RubyNext::Language.include_patterns` instead of `RubyNext::Language.watch_dirs`"
73
+ @watch_dirs
74
+ end
75
+
65
76
  attr_accessor :rewriters
66
- attr_reader :watch_dirs
67
77
 
68
78
  attr_accessor :strategy
69
79
 
@@ -95,14 +105,17 @@ module RubyNext
95
105
  end
96
106
 
97
107
  def transform(source, rewriters: self.rewriters, using: RubyNext::Core.refine?, context: TransformContext.new)
108
+ text_rewriters, ast_rewriters = rewriters.partition(&:text?)
109
+
98
110
  retried = 0
99
- new_source = nil
111
+ new_source = text_rewrite(source, rewriters: text_rewriters, using: using, context: context)
112
+
100
113
  begin
101
114
  new_source =
102
115
  if mode == :rewrite
103
- rewrite(source, rewriters: rewriters, using: using, context: context)
116
+ rewrite(new_source, rewriters: ast_rewriters, using: using, context: context)
104
117
  else
105
- regenerate(source, rewriters: rewriters, using: using, context: context)
118
+ regenerate(new_source, rewriters: ast_rewriters, using: using, context: context)
106
119
  end
107
120
  rescue Unparser::UnknownNodeError => err
108
121
  RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since the version of Unparser you use doesn't support some syntax yet: #{err.message}.\n" \
@@ -119,8 +132,17 @@ module RubyNext
119
132
  Core.inject! new_source.dup
120
133
  end
121
134
 
135
+ def target_dir?(dirname)
136
+ # fnmatch? requires a file name, not a folder
137
+ fname = File.join(dirname, "x.rb")
138
+
139
+ include_patterns.any? { |pattern| File.fnmatch?(pattern, fname) } &&
140
+ exclude_patterns.none? { |pattern| File.fnmatch?(pattern, fname) }
141
+ end
142
+
122
143
  def transformable?(path)
123
- watch_dirs.any? { |dir| path.start_with?(dir) }
144
+ include_patterns.any? { |pattern| File.fnmatch?(pattern, path) } &&
145
+ exclude_patterns.none? { |pattern| File.fnmatch?(pattern, path) }
124
146
  end
125
147
 
126
148
  # Rewriters required for the current version
@@ -165,14 +187,36 @@ module RubyNext
165
187
  end
166
188
  end
167
189
 
190
+ def text_rewrite(source, rewriters:, using:, context:)
191
+ rewriters.inject(source) do |src, rewriter|
192
+ rewriter.new(context).rewrite(src)
193
+ end.then do |new_source|
194
+ next source unless context.dirty?
195
+
196
+ new_source
197
+ end
198
+ end
199
+
168
200
  attr_writer :watch_dirs
201
+ attr_writer :include_patterns, :exclude_patterns
169
202
  end
170
203
 
171
204
  self.rewriters = []
172
- self.watch_dirs = %w[app lib spec test].map { |path| File.join(Dir.pwd, path) }
205
+ self.watch_dirs = [].tap do |dirs|
206
+ # For backward compatibility
207
+ dirs.define_singleton_method(:<<) do |dir|
208
+ super(dir)
209
+ RubyNext::Language.include_patterns << File.join(dir, "*.rb")
210
+ end
211
+ end
212
+
213
+ self.include_patterns = %w[app lib spec test].map { |path| File.join(Dir.pwd, path, "*.rb") }
214
+ self.exclude_patterns = %w[vendor/bundle].map { |path| File.join(Dir.pwd, path, "*") }
173
215
  self.mode = ENV.fetch("RUBY_NEXT_TRANSPILE_MODE", "rewrite").to_sym
174
216
 
217
+ require "ruby-next/language/rewriters/abstract"
175
218
  require "ruby-next/language/rewriters/base"
219
+ require "ruby-next/language/rewriters/text"
176
220
 
177
221
  require "ruby-next/language/rewriters/2.1/numeric_literals"
178
222
  rewriters << Rewriters::NumericLiterals
@@ -186,6 +230,9 @@ module RubyNext
186
230
  require "ruby-next/language/rewriters/2.3/safe_navigation"
187
231
  rewriters << Rewriters::SafeNavigation
188
232
 
233
+ require "ruby-next/language/rewriters/2.5/rescue_within_block"
234
+ rewriters << Rewriters::RescueWithinBlock
235
+
189
236
  require "ruby-next/language/rewriters/2.7/args_forward"
190
237
  rewriters << Rewriters::ArgsForward
191
238
 
@@ -209,7 +256,7 @@ module RubyNext
209
256
  rewriters << Rewriters::InPattern
210
257
 
211
258
  require "ruby-next/language/rewriters/3.0/endless_method"
212
- RubyNext::Language.rewriters << RubyNext::Language::Rewriters::EndlessMethod
259
+ rewriters << RubyNext::Language::Rewriters::EndlessMethod
213
260
 
214
261
  require "ruby-next/language/rewriters/3.1/oneline_pattern_parensless"
215
262
  rewriters << Rewriters::OnelinePatternParensless
@@ -229,16 +276,19 @@ module RubyNext
229
276
  require "ruby-next/language/rewriters/3.1/shorthand_hash"
230
277
  rewriters << RubyNext::Language::Rewriters::ShorthandHash
231
278
 
279
+ require "ruby-next/language/rewriters/3.2/anonymous_restargs"
280
+ rewriters << RubyNext::Language::Rewriters::AnonymousRestArgs
281
+
232
282
  # Put endless range in the end, 'cause Parser fails to parse it in
233
283
  # pattern matching
234
284
  require "ruby-next/language/rewriters/2.6/endless_range"
235
285
  rewriters << Rewriters::EndlessRange
236
286
 
237
- if ENV["RUBY_NEXT_EDGE"] == "1"
287
+ if RubyNext.edge_syntax?
238
288
  require "ruby-next/language/rewriters/edge"
239
289
  end
240
290
 
241
- if ENV["RUBY_NEXT_PROPOSED"] == "1"
291
+ if RubyNext.proposed_syntax?
242
292
  require "ruby-next/language/rewriters/proposed"
243
293
  end
244
294
  end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file contains patches for Pry integration.
4
+ # It's supposed to be required inside .pryrc files.
5
+
6
+ require "ruby-next/language/setup"
7
+ require "ruby-next/language/runtime"
8
+
9
+ # Enables refinements by injecting "using RubyNext"
10
+ # before Pry copies and memorizes the TOPLEVEL_BINDING.
11
+ Pry.singleton_class.prepend(Module.new do
12
+ def toplevel_binding
13
+ unless defined?(@_using_injected) && @_using_injected
14
+ orig_binding = super
15
+
16
+ # Copy TOPLEVEL_BINDING without local variables.
17
+ TOPLEVEL_BINDING.eval <<-RUBY
18
+ using RubyNext
19
+
20
+ def self.__pry__
21
+ binding
22
+ end
23
+
24
+ Pry.toplevel_binding = __pry__
25
+
26
+ class << self; undef __pry__; end
27
+ RUBY
28
+
29
+ # Inject local variables from the original binding.
30
+ orig_binding.local_variables.each do |var|
31
+ value = orig_binding.local_variable_get(var)
32
+ @toplevel_binding.local_variable_set(var, value)
33
+ end
34
+
35
+ @_using_injected = true
36
+ end
37
+
38
+ super
39
+ end
40
+ end)
41
+
42
+ # Enables edge Ruby syntax by transpiling the code
43
+ # before it's evaluated in the context of a binding.
44
+ Pry.prepend(Module.new do
45
+ def current_binding
46
+ super.tap do |obj|
47
+ next if obj.respond_to?(:__nextified__)
48
+
49
+ obj.instance_eval do
50
+ def eval(code, *args)
51
+ new_code = ::RubyNext::Language::Runtime.transform(code, using: false)
52
+
53
+ super(new_code, *args)
54
+ end
55
+
56
+ def __nextified__
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end)
62
+
63
+ # Enables edge Ruby syntax for multi-line input.
64
+ Pry::Code.singleton_class.prepend(Module.new do
65
+ def complete_expression?(str)
66
+ silence_stderr do
67
+ ::RubyNext::Language.parser_class.parse(str)
68
+ end
69
+
70
+ true
71
+ rescue Parser::SyntaxError => ex
72
+ case ex.message
73
+ when /unexpected token \$end/
74
+ false
75
+ else
76
+ true
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def silence_stderr
83
+ stderr = StringIO.new
84
+ orig_stderr, $stderr = $stderr, stderr
85
+
86
+ yield
87
+
88
+ $stderr = orig_stderr
89
+ end
90
+ end)
@@ -4,6 +4,7 @@
4
4
  # edge features and fix some bugs with 2.7+ syntax
5
5
 
6
6
  require "parser/ruby-next/version"
7
+ require "ruby-next/config"
7
8
  require "ruby-next/language/parser"
8
9
 
9
10
  module RuboCop
@@ -38,6 +39,7 @@ module RuboCop
38
39
  def parser_class(version)
39
40
  return super unless version == RUBY_NEXT_VERSION
40
41
 
42
+ require "parser/rubynext"
41
43
  Parser::RubyNext
42
44
  end
43
45
  end
@@ -4,28 +4,6 @@ module RubyNext
4
4
  module Utils
5
5
  module_function
6
6
 
7
- if $LOAD_PATH.respond_to?(:resolve_feature_path)
8
- def resolve_feature_path(feature)
9
- $LOAD_PATH.resolve_feature_path(feature)&.last
10
- rescue LoadError
11
- end
12
- else
13
- def resolve_feature_path(path)
14
- if File.file?(relative = File.expand_path(path))
15
- path = relative
16
- end
17
-
18
- path = "#{path}.rb" if File.extname(path).empty?
19
-
20
- return path if Pathname.new(path).absolute?
21
-
22
- $LOAD_PATH.find do |lp|
23
- lpath = File.join(lp, path)
24
- return File.realpath(lpath) if File.file?(lpath)
25
- end
26
- end
27
- end
28
-
29
7
  def source_with_lines(source, path)
30
8
  source.lines.map.with_index do |line, i|
31
9
  "#{(i + 1).to_s.rjust(4)}: #{line}"
@@ -36,6 +14,7 @@ module RubyNext
36
14
 
37
15
  # Returns true if modules refinement is supported in current version
38
16
  def refine_modules?
17
+ save_verbose, $VERBOSE = $VERBOSE, nil
39
18
  @refine_modules ||=
40
19
  begin
41
20
  # Make sure that including modules within refinements works
@@ -61,6 +40,8 @@ module RubyNext
61
40
  true
62
41
  rescue TypeError, NoMethodError
63
42
  false
43
+ ensure
44
+ $VERBOSE = save_verbose
64
45
  end
65
46
  end
66
47
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyNext
4
- VERSION = "0.14.0"
4
+ VERSION = "1.0.1"
5
5
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ruby-next/irb"
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ruby-next/pry"
data/lib/uby-next.rb CHANGED
@@ -9,7 +9,7 @@ require "ruby-next/core/runtime"
9
9
 
10
10
  using RubyNext
11
11
 
12
- RubyNext::Language.watch_dirs << Dir.pwd
12
+ RubyNext::Language.include_patterns << File.join(Dir.pwd, ".rb")
13
13
 
14
14
  require "stringio"
15
15
 
@@ -36,7 +36,7 @@ end
36
36
  at_exit do
37
37
  $stderr = orig_stderr
38
38
 
39
- if NoMethodError === $! || SyntaxError === $!
39
+ if NoMethodError === $! || SyntaxError === $! || NameError === $!
40
40
  if $0 && File.exist?($0)
41
41
  load($0)
42
42
  exit!(0)