prism 0.25.0 → 0.26.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15343c4f2d796d38ab23791193ad8e7caad9c1f53632fc6a6de0b1f842a09202
4
- data.tar.gz: 0ef3cf6a5ed5853439e2854c4142e3f00e2a56b8e77e15c8b77bb759572745ff
3
+ metadata.gz: abad576ba53ce985475eb5d69638557386eef255c8fe625728780ce8ff66844e
4
+ data.tar.gz: a3c5e24f5d1ee0fe04d282a3f40d643cd914a518985a9cadebbb53200e4d3003
5
5
  SHA512:
6
- metadata.gz: 6d6e43bb22ed673caed7fb74e59f027a7781bfa55ff9b9d4fc386a547c615288e9d83b0e35482fa5cb8989365a6cf65b69d9d7b5e98bc42bf1603f557c80f859
7
- data.tar.gz: 174c82145e87749e11e7bdbf99185f8383e51321556158b4a2379c315eee86c1c5de36ab843ef3e2ac153224c6a251bd40fdf613d928aded37b31cc05995d65e
6
+ metadata.gz: d3255b2de64f3154500885ae2bd091389d6ac87c9b88cb8ff83b7d58026066c4e007cb7c486dcc8e8146132aad63a1c58ddd8ad598441d26bec7ad062409f6a9
7
+ data.tar.gz: 3d7563663f013a4dcc633b5e19d0a4605cae18bd0a0f99cc02c142198b25126f915185eef4080625c9a5867093a5bc5717db96ef8a8da6cdc69e849f65fbb7fd
data/CHANGELOG.md CHANGED
@@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.26.0] - 2024-04-18
10
+
11
+ ### Added
12
+
13
+ - Add `Prism::Node::fields`, which returns a list of `Prism::Reflection::Field` objects representing the fields of the node class. This is useful in metaprogramming contexts.
14
+ - `Prism::Location#chop`, for removing the last byte from a location.
15
+ - The void statement warning is now implemented.
16
+ - The unreachable statement warning is now implemented.
17
+ - A syntax error has been added for block arguments on yields, e.g., `yield(&foo)`.
18
+
19
+ ### Changed
20
+
21
+ - Better fidelity to `parser` when translating heredocs with interpolation.
22
+ - Fixed `RBI` and `RBS` types for `Prism::parse_*` signatures.
23
+ - Remove some incorrect warnings about unused local variables.
24
+ - More closely match CRuby error messages for global variables.
25
+ - Fix an issue with `parser` translation when line continuations are found in string literals.
26
+
9
27
  ## [0.25.0] - 2024-04-05
10
28
 
11
29
  ### Added
@@ -440,7 +458,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
440
458
 
441
459
  - 🎉 Initial release! 🎉
442
460
 
443
- [unreleased]: https://github.com/ruby/prism/compare/v0.25.0...HEAD
461
+ [unreleased]: https://github.com/ruby/prism/compare/v0.26.0...HEAD
462
+ [0.26.0]: https://github.com/ruby/prism/compare/v0.25.0...v0.26.0
444
463
  [0.25.0]: https://github.com/ruby/prism/compare/v0.24.0...v0.25.0
445
464
  [0.24.0]: https://github.com/ruby/prism/compare/v0.23.0...v0.24.0
446
465
  [0.23.0]: https://github.com/ruby/prism/compare/v0.22.0...v0.23.0
data/Makefile CHANGED
@@ -6,17 +6,20 @@ Q1 = $(V:1=)
6
6
  Q = $(Q1:0=@)
7
7
  ECHO1 = $(V:1=@ :)
8
8
  ECHO = $(ECHO1:0=@ echo)
9
- FUZZ_OUTPUT_DIR = $(shell pwd)/fuzz/output
9
+ FUZZ_OUTPUT_DIR = $(CURDIR)/fuzz/output
10
10
 
11
- SOEXT := $(shell ruby -e 'puts RbConfig::CONFIG["SOEXT"]')
11
+ SOEXT ?= $(shell ruby -e 'puts RbConfig::CONFIG["SOEXT"]')
12
12
 
13
13
  CPPFLAGS := -Iinclude $(CPPFLAGS)
14
14
  CFLAGS := -g -O2 -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fPIC -fvisibility=hidden $(CFLAGS)
15
- CC := cc
15
+ CC ?= cc
16
16
  WASI_SDK_PATH := /opt/wasi-sdk
17
17
 
18
- HEADERS := $(shell find include -name '*.h')
19
- SOURCES := $(shell find src -name '*.c')
18
+ MAKEDIRS ?= mkdir -p
19
+ RMALL ?= rm -f -r
20
+
21
+ HEADERS := $(wildcard include/*.h include/*/*.h include/*/*/*.h')
22
+ SOURCES := $(wildcard src/*.c src/*/*.c)
20
23
  SHARED_OBJECTS := $(subst src/,build/shared/,$(SOURCES:.c=.o))
21
24
  STATIC_OBJECTS := $(subst src/,build/static/,$(SOURCES:.c=.o))
22
25
 
@@ -45,17 +48,17 @@ java-wasm/src/test/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS)
45
48
 
46
49
  build/shared/%.o: src/%.c Makefile $(HEADERS)
47
50
  $(ECHO) "compiling $@"
48
- $(Q) mkdir -p $(@D)
51
+ $(Q) $(MAKEDIRS) $(@D)
49
52
  $(Q) $(CC) $(DEBUG_FLAGS) -DPRISM_EXPORT_SYMBOLS $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
50
53
 
51
54
  build/static/%.o: src/%.c Makefile $(HEADERS)
52
55
  $(ECHO) "compiling $@"
53
- $(Q) mkdir -p $(@D)
56
+ $(Q) $(MAKEDIRS) $(@D)
54
57
  $(Q) $(CC) $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
55
58
 
56
59
  build/fuzz.%: $(SOURCES) fuzz/%.c fuzz/fuzz.c
57
60
  $(ECHO) "building $* fuzzer"
58
- $(Q) mkdir -p $(@D)
61
+ $(Q) $(MAKEDIRS) $(@D)
59
62
  $(ECHO) "building main fuzz binary"
60
63
  $(Q) AFL_HARDEN=1 afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize-ignorelist=fuzz/asan.ignore -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@ $^
61
64
  $(ECHO) "building cmplog binary"
@@ -66,7 +69,7 @@ build/fuzz.heisenbug.%: $(SOURCES) fuzz/%.c fuzz/heisenbug.c
66
69
 
67
70
  fuzz-debug:
68
71
  $(ECHO) "entering debug shell"
69
- $(Q) docker run -it --rm -e HISTFILE=/prism/fuzz/output/.bash_history -v $(shell pwd):/prism -v $(FUZZ_OUTPUT_DIR):/fuzz_output prism/fuzz
72
+ $(Q) docker run -it --rm -e HISTFILE=/prism/fuzz/output/.bash_history -v $(CURDIR):/prism -v $(FUZZ_OUTPUT_DIR):/fuzz_output prism/fuzz
70
73
 
71
74
  fuzz-docker-build: fuzz/docker/Dockerfile
72
75
  $(ECHO) "building docker image"
@@ -76,17 +79,17 @@ fuzz-run-%: FORCE fuzz-docker-build
76
79
  $(ECHO) "generating templates"
77
80
  $(Q) bundle exec rake templates
78
81
  $(ECHO) "running $* fuzzer"
79
- $(Q) docker run --rm -v $(shell pwd):/prism prism/fuzz /bin/bash -c "FUZZ_FLAGS=\"$(FUZZ_FLAGS)\" make build/fuzz.$*"
82
+ $(Q) docker run --rm -v $(CURDIR):/prism prism/fuzz /bin/bash -c "FUZZ_FLAGS=\"$(FUZZ_FLAGS)\" make build/fuzz.$*"
80
83
  $(ECHO) "starting AFL++ run"
81
- $(Q) mkdir -p $(FUZZ_OUTPUT_DIR)/$*
82
- $(Q) docker run -it --rm -v $(shell pwd):/prism -v $(FUZZ_OUTPUT_DIR):/fuzz_output prism/fuzz /bin/bash -c "./fuzz/$*.sh /fuzz_output/$*"
84
+ $(Q) $(MAKEDIRS) $(FUZZ_OUTPUT_DIR)/$*
85
+ $(Q) docker run -it --rm -v $(CURDIR):/prism -v $(FUZZ_OUTPUT_DIR):/fuzz_output prism/fuzz /bin/bash -c "./fuzz/$*.sh /fuzz_output/$*"
83
86
  FORCE:
84
87
 
85
88
  fuzz-clean:
86
- $(Q) rm -f -r fuzz/output
89
+ $(Q) $(RMALL) fuzz/output
87
90
 
88
91
  clean:
89
- $(Q) rm -f -r build
92
+ $(Q) $(RMALL) build
90
93
 
91
94
  .PHONY: clean fuzz-clean
92
95
 
data/config.yml CHANGED
@@ -60,7 +60,6 @@ errors:
60
60
  - DEF_ENDLESS
61
61
  - DEF_ENDLESS_SETTER
62
62
  - DEF_NAME
63
- - DEF_NAME_AFTER_RECEIVER
64
63
  - DEF_PARAMS_TERM
65
64
  - DEF_PARAMS_TERM_PAREN
66
65
  - DEF_RECEIVER
@@ -97,6 +96,7 @@ errors:
97
96
  - EXPECT_EXPRESSION_AFTER_STAR
98
97
  - EXPECT_IDENT_REQ_PARAMETER
99
98
  - EXPECT_LPAREN_REQ_PARAMETER
99
+ - EXPECT_MESSAGE
100
100
  - EXPECT_RBRACKET
101
101
  - EXPECT_RPAREN
102
102
  - EXPECT_RPAREN_AFTER_MULTI
@@ -104,6 +104,14 @@ errors:
104
104
  - EXPECT_STRING_CONTENT
105
105
  - EXPECT_WHEN_DELIMITER
106
106
  - EXPRESSION_BARE_HASH
107
+ - EXPRESSION_NOT_WRITABLE
108
+ - EXPRESSION_NOT_WRITABLE_ENCODING
109
+ - EXPRESSION_NOT_WRITABLE_FALSE
110
+ - EXPRESSION_NOT_WRITABLE_FILE
111
+ - EXPRESSION_NOT_WRITABLE_LINE
112
+ - EXPRESSION_NOT_WRITABLE_NIL
113
+ - EXPRESSION_NOT_WRITABLE_SELF
114
+ - EXPRESSION_NOT_WRITABLE_TRUE
107
115
  - FLOAT_PARSE
108
116
  - FOR_COLLECTION
109
117
  - FOR_IN
@@ -235,6 +243,7 @@ errors:
235
243
  - TERNARY_EXPRESSION_TRUE
236
244
  - UNARY_RECEIVER
237
245
  - UNDEF_ARGUMENT
246
+ - UNEXPECTED_BLOCK_ARGUMENT
238
247
  - UNEXPECTED_TOKEN_CLOSE_CONTEXT
239
248
  - UNEXPECTED_TOKEN_IGNORE
240
249
  - UNTIL_TERM
@@ -269,7 +278,9 @@ warnings:
269
278
  - LITERAL_IN_CONDITION_VERBOSE
270
279
  - SHEBANG_CARRIAGE_RETURN
271
280
  - UNEXPECTED_CARRIAGE_RETURN
281
+ - UNREACHABLE_STATEMENT
272
282
  - UNUSED_LOCAL_VARIABLE
283
+ - VOID_STATEMENT
273
284
  tokens:
274
285
  - name: EOF
275
286
  value: 1
@@ -16,6 +16,7 @@ A lot of code in prism's repository is templated from a single configuration fil
16
16
  * `lib/prism/dsl.rb` - for defining the DSL for the nodes in Ruby
17
17
  * `lib/prism/mutation_compiler.rb` - for defining the mutation compiler for the nodes in Ruby
18
18
  * `lib/prism/node.rb` - for defining the nodes in Ruby
19
+ * `lib/prism/reflection.rb` - for defining the reflection API in Ruby
19
20
  * `lib/prism/serialize.rb` - for defining how to deserialize the nodes in Ruby
20
21
  * `lib/prism/visitor.rb` - for defining the visitor interface for the nodes in Ruby
21
22
  * `src/diagnostic.c` - for defining how to build diagnostics
data/docs/releasing.md CHANGED
@@ -47,15 +47,7 @@ bundle install
47
47
  * Update the version-specific lockfiles:
48
48
 
49
49
  ```sh
50
- chruby ruby-2.7.8 && BUNDLE_GEMFILE=gemfiles/2.7/Gemfile bundle install
51
- chruby ruby-3.0.6 && BUNDLE_GEMFILE=gemfiles/3.0/Gemfile bundle install
52
- chruby ruby-3.1.4 && BUNDLE_GEMFILE=gemfiles/3.1/Gemfile bundle install
53
- chruby ruby-3.2.3 && BUNDLE_GEMFILE=gemfiles/3.2/Gemfile bundle install
54
- chruby ruby-3.3.0 && BUNDLE_GEMFILE=gemfiles/3.3/Gemfile bundle install
55
- chruby ruby-3.4.0-dev && BUNDLE_GEMFILE=gemfiles/3.4/Gemfile bundle install
56
- chruby jruby-9.4.5.0 && BUNDLE_GEMFILE=gemfiles/jruby/Gemfile bundle install
57
- chruby truffleruby-24.0.0 && BUNDLE_GEMFILE=gemfiles/truffleruby/Gemfile bundle install
58
- chruby ruby-3.4.0-dev && BUNDLE_GEMFILE=gemfiles/typecheck/Gemfile bundle install
50
+ bin/prism bundle install
59
51
  ```
60
52
 
61
53
  * Update the cargo lockfiles:
@@ -70,6 +62,12 @@ bundle exec rake cargo:build
70
62
  git commit -am "Bump to v$PRISM_VERSION"
71
63
  ```
72
64
 
65
+ * Push up the changes:
66
+
67
+ ```sh
68
+ git push
69
+ ```
70
+
73
71
  ## Publishing
74
72
 
75
73
  * Update the GitHub release page with a copy of the latest entry in the `CHANGELOG.md` file.
data/ext/prism/extconf.rb CHANGED
@@ -40,17 +40,22 @@ def generate_templates
40
40
  end
41
41
  end
42
42
 
43
+ require "rbconfig"
44
+
43
45
  # Runs `make` in the root directory of the project. Note that this is the
44
46
  # `Makefile` for the overall project, not the `Makefile` that is being generated
45
47
  # by this script.`
46
48
  def make(target)
47
49
  Dir.chdir(File.expand_path("../..", __dir__)) do
48
- system(RUBY_PLATFORM.include?("openbsd") ? "gmake" : "make", target, exception: true)
50
+ system(
51
+ RbConfig::CONFIG.slice(*%w[SOEXT CPPFLAGS CFLAGS CC AR ARFLAGS MAKEDIRS RMALL]), # env
52
+ RUBY_PLATFORM.include?("openbsd") ? "gmake" : "make",
53
+ target,
54
+ exception: true
55
+ )
49
56
  end
50
57
  end
51
58
 
52
- require "rbconfig"
53
-
54
59
  # On non-CRuby we only need the shared library since we'll interface with it
55
60
  # through FFI, so we'll build only that and not the C extension. We also avoid
56
61
  # `require "mkmf"` as that prepends the LLVM toolchain to PATH on TruffleRuby,
@@ -969,7 +969,7 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) {
969
969
 
970
970
  /**
971
971
  * call-seq:
972
- * Prism::parse_success?(source, **options) -> Array
972
+ * Prism::parse_success?(source, **options) -> bool
973
973
  *
974
974
  * Parse the given string and return true if it parses without errors. For
975
975
  * supported options, see Prism::parse.
@@ -989,7 +989,19 @@ parse_success_p(int argc, VALUE *argv, VALUE self) {
989
989
 
990
990
  /**
991
991
  * call-seq:
992
- * Prism::parse_file_success?(filepath, **options) -> Array
992
+ * Prism::parse_failure?(source, **options) -> bool
993
+ *
994
+ * Parse the given string and return true if it parses with errors. For
995
+ * supported options, see Prism::parse.
996
+ */
997
+ static VALUE
998
+ parse_failure_p(int argc, VALUE *argv, VALUE self) {
999
+ return RTEST(parse_success_p(argc, argv, self)) ? Qfalse : Qtrue;
1000
+ }
1001
+
1002
+ /**
1003
+ * call-seq:
1004
+ * Prism::parse_file_success?(filepath, **options) -> bool
993
1005
  *
994
1006
  * Parse the given file and return true if it parses without errors. For
995
1007
  * supported options, see Prism::parse.
@@ -1008,6 +1020,18 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) {
1008
1020
  return result;
1009
1021
  }
1010
1022
 
1023
+ /**
1024
+ * call-seq:
1025
+ * Prism::parse_file_failure?(filepath, **options) -> bool
1026
+ *
1027
+ * Parse the given file and return true if it parses with errors. For
1028
+ * supported options, see Prism::parse.
1029
+ */
1030
+ static VALUE
1031
+ parse_file_failure_p(int argc, VALUE *argv, VALUE self) {
1032
+ return RTEST(parse_file_success_p(argc, argv, self)) ? Qfalse : Qtrue;
1033
+ }
1034
+
1011
1035
  /******************************************************************************/
1012
1036
  /* Utility functions exposed to make testing easier */
1013
1037
  /******************************************************************************/
@@ -1366,7 +1390,9 @@ Init_prism(void) {
1366
1390
  rb_define_singleton_method(rb_cPrism, "parse_lex", parse_lex, -1);
1367
1391
  rb_define_singleton_method(rb_cPrism, "parse_lex_file", parse_lex_file, -1);
1368
1392
  rb_define_singleton_method(rb_cPrism, "parse_success?", parse_success_p, -1);
1393
+ rb_define_singleton_method(rb_cPrism, "parse_failure?", parse_failure_p, -1);
1369
1394
  rb_define_singleton_method(rb_cPrism, "parse_file_success?", parse_file_success_p, -1);
1395
+ rb_define_singleton_method(rb_cPrism, "parse_file_failure?", parse_file_failure_p, -1);
1370
1396
 
1371
1397
  #ifndef PRISM_EXCLUDE_SERIALIZATION
1372
1398
  rb_define_singleton_method(rb_cPrism, "dump", dump, -1);
@@ -1,7 +1,7 @@
1
1
  #ifndef PRISM_EXT_NODE_H
2
2
  #define PRISM_EXT_NODE_H
3
3
 
4
- #define EXPECTED_PRISM_VERSION "0.25.0"
4
+ #define EXPECTED_PRISM_VERSION "0.26.0"
5
5
 
6
6
  #include <ruby.h>
7
7
  #include <ruby/encoding.h>
@@ -89,7 +89,6 @@ typedef enum {
89
89
  PM_ERR_DEF_ENDLESS,
90
90
  PM_ERR_DEF_ENDLESS_SETTER,
91
91
  PM_ERR_DEF_NAME,
92
- PM_ERR_DEF_NAME_AFTER_RECEIVER,
93
92
  PM_ERR_DEF_PARAMS_TERM,
94
93
  PM_ERR_DEF_PARAMS_TERM_PAREN,
95
94
  PM_ERR_DEF_RECEIVER,
@@ -126,6 +125,7 @@ typedef enum {
126
125
  PM_ERR_EXPECT_EXPRESSION_AFTER_STAR,
127
126
  PM_ERR_EXPECT_IDENT_REQ_PARAMETER,
128
127
  PM_ERR_EXPECT_LPAREN_REQ_PARAMETER,
128
+ PM_ERR_EXPECT_MESSAGE,
129
129
  PM_ERR_EXPECT_RBRACKET,
130
130
  PM_ERR_EXPECT_RPAREN,
131
131
  PM_ERR_EXPECT_RPAREN_AFTER_MULTI,
@@ -133,6 +133,14 @@ typedef enum {
133
133
  PM_ERR_EXPECT_STRING_CONTENT,
134
134
  PM_ERR_EXPECT_WHEN_DELIMITER,
135
135
  PM_ERR_EXPRESSION_BARE_HASH,
136
+ PM_ERR_EXPRESSION_NOT_WRITABLE,
137
+ PM_ERR_EXPRESSION_NOT_WRITABLE_ENCODING,
138
+ PM_ERR_EXPRESSION_NOT_WRITABLE_FALSE,
139
+ PM_ERR_EXPRESSION_NOT_WRITABLE_FILE,
140
+ PM_ERR_EXPRESSION_NOT_WRITABLE_LINE,
141
+ PM_ERR_EXPRESSION_NOT_WRITABLE_NIL,
142
+ PM_ERR_EXPRESSION_NOT_WRITABLE_SELF,
143
+ PM_ERR_EXPRESSION_NOT_WRITABLE_TRUE,
136
144
  PM_ERR_FLOAT_PARSE,
137
145
  PM_ERR_FOR_COLLECTION,
138
146
  PM_ERR_FOR_IN,
@@ -264,6 +272,7 @@ typedef enum {
264
272
  PM_ERR_TERNARY_EXPRESSION_TRUE,
265
273
  PM_ERR_UNARY_RECEIVER,
266
274
  PM_ERR_UNDEF_ARGUMENT,
275
+ PM_ERR_UNEXPECTED_BLOCK_ARGUMENT,
267
276
  PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT,
268
277
  PM_ERR_UNEXPECTED_TOKEN_IGNORE,
269
278
  PM_ERR_UNTIL_TERM,
@@ -299,7 +308,9 @@ typedef enum {
299
308
  PM_WARN_LITERAL_IN_CONDITION_VERBOSE,
300
309
  PM_WARN_SHEBANG_CARRIAGE_RETURN,
301
310
  PM_WARN_UNEXPECTED_CARRIAGE_RETURN,
311
+ PM_WARN_UNREACHABLE_STATEMENT,
302
312
  PM_WARN_UNUSED_LOCAL_VARIABLE,
313
+ PM_WARN_VOID_STATEMENT,
303
314
  } pm_diagnostic_id_t;
304
315
 
305
316
  /**
@@ -13,7 +13,6 @@
13
13
  #include "prism/util/pm_constant_pool.h"
14
14
  #include "prism/util/pm_list.h"
15
15
  #include "prism/util/pm_newline_list.h"
16
- #include "prism/util/pm_state_stack.h"
17
16
  #include "prism/util/pm_string.h"
18
17
 
19
18
  #include <stdbool.h>
@@ -612,6 +611,11 @@ static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_ALL = 0x40;
612
611
  static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED = -1;
613
612
  static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_NONE = 0;
614
613
 
614
+ /**
615
+ * A struct that represents a stack of boolean values.
616
+ */
617
+ typedef uint32_t pm_state_stack_t;
618
+
615
619
  /**
616
620
  * This struct represents the overall parser. It contains a reference to the
617
621
  * source file, as well as pointers that indicate where in the source it's
@@ -14,7 +14,7 @@
14
14
  /**
15
15
  * The minor version of the Prism library as an int.
16
16
  */
17
- #define PRISM_VERSION_MINOR 25
17
+ #define PRISM_VERSION_MINOR 26
18
18
 
19
19
  /**
20
20
  * The patch version of the Prism library as an int.
@@ -24,6 +24,6 @@
24
24
  /**
25
25
  * The version of the Prism library as a constant string.
26
26
  */
27
- #define PRISM_VERSION "0.25.0"
27
+ #define PRISM_VERSION "0.26.0"
28
28
 
29
29
  #endif
@@ -73,6 +73,8 @@ module Prism
73
73
 
74
74
  # Desugar `x += y` to `x = x + y`
75
75
  def compile
76
+ operator_loc = node.operator_loc.chop
77
+
76
78
  write_class.new(
77
79
  source,
78
80
  *arguments,
@@ -82,8 +84,8 @@ module Prism
82
84
  0,
83
85
  read_class.new(source, *arguments, node.name_loc),
84
86
  nil,
85
- node.operator_loc.slice.chomp("=").to_sym,
86
- node.operator_loc.copy(length: node.operator_loc.length - 1),
87
+ operator_loc.slice.to_sym,
88
+ operator_loc,
87
89
  nil,
88
90
  ArgumentsNode.new(source, 0, [node.value], node.value.location),
89
91
  nil,
data/lib/prism/ffi.rb CHANGED
@@ -286,12 +286,22 @@ module Prism
286
286
  LibRubyParser::PrismString.with_string(code) { |string| parse_file_success_common(string, options) }
287
287
  end
288
288
 
289
+ # Mirror the Prism.parse_failure? API by using the serialization API.
290
+ def parse_failure?(code, **options)
291
+ !parse_success?(code, **options)
292
+ end
293
+
289
294
  # Mirror the Prism.parse_file_success? API by using the serialization API.
290
295
  def parse_file_success?(filepath, **options)
291
296
  options[:filepath] = filepath
292
297
  LibRubyParser::PrismString.with_file(filepath) { |string| parse_file_success_common(string, options) }
293
298
  end
294
299
 
300
+ # Mirror the Prism.parse_file_failure? API by using the serialization API.
301
+ def parse_file_failure?(filepath, **options)
302
+ !parse_file_success?(filepath, **options)
303
+ end
304
+
295
305
  private
296
306
 
297
307
  def dump_common(string, options) # :nodoc:
data/lib/prism/node.rb CHANGED
@@ -68,6 +68,17 @@ module Prism
68
68
  DotVisitor.new.tap { |visitor| accept(visitor) }.to_dot
69
69
  end
70
70
 
71
+ # Returns a list of the fields that exist for this node class. Fields
72
+ # describe the structure of the node. This kind of reflection is useful for
73
+ # things like recursively visiting each node _and_ field in the tree.
74
+ def self.fields
75
+ # This method should only be called on subclasses of Node, not Node
76
+ # itself.
77
+ raise NoMethodError, "undefined method `fields' for #{inspect}" if self == Node
78
+
79
+ Reflection.fields_for(self)
80
+ end
81
+
71
82
  # --------------------------------------------------------------------------
72
83
  # :section: Node interface
73
84
  # These methods are effectively abstract methods that must be implemented by
@@ -110,6 +121,11 @@ module Prism
110
121
  def inspect(inspector = NodeInspector.new)
111
122
  raise NoMethodError, "undefined method `inspect' for #{inspect}"
112
123
  end
124
+
125
+ # Returns the type of the node as a symbol.
126
+ def self.type
127
+ raise NoMethodError, "undefined method `type' for #{inspect}"
128
+ end
113
129
  end
114
130
 
115
131
  # Represents the use of the `alias` keyword to alias a global variable.
@@ -161,6 +161,11 @@ module Prism
161
161
  Location.new(source, start_offset, length)
162
162
  end
163
163
 
164
+ # Returns a new location that is the result of chopping off the last byte.
165
+ def chop
166
+ copy(length: length == 0 ? length : length - 1)
167
+ end
168
+
164
169
  # Returns a string representation of this location.
165
170
  def inspect
166
171
  "#<Prism::Location @start_offset=#{@start_offset} @length=#{@length} start_line=#{start_line}>"