prism 1.4.0 → 1.6.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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -1
  3. data/Makefile +4 -2
  4. data/README.md +2 -0
  5. data/config.yml +266 -38
  6. data/docs/design.md +2 -2
  7. data/docs/parser_translation.md +8 -23
  8. data/docs/releasing.md +5 -24
  9. data/docs/ripper_translation.md +1 -1
  10. data/ext/prism/api_node.c +2 -0
  11. data/ext/prism/extension.c +25 -3
  12. data/ext/prism/extension.h +1 -1
  13. data/include/prism/ast.h +306 -50
  14. data/include/prism/diagnostic.h +5 -0
  15. data/include/prism/options.h +43 -3
  16. data/include/prism/regexp.h +2 -2
  17. data/include/prism/util/pm_buffer.h +8 -0
  18. data/include/prism/util/pm_integer.h +4 -0
  19. data/include/prism/util/pm_list.h +6 -0
  20. data/include/prism/util/pm_string.h +12 -2
  21. data/include/prism/version.h +2 -2
  22. data/include/prism.h +39 -14
  23. data/lib/prism/compiler.rb +456 -151
  24. data/lib/prism/desugar_compiler.rb +1 -0
  25. data/lib/prism/dispatcher.rb +16 -0
  26. data/lib/prism/dot_visitor.rb +5 -1
  27. data/lib/prism/dsl.rb +3 -0
  28. data/lib/prism/ffi.rb +25 -9
  29. data/lib/prism/inspect_visitor.rb +3 -0
  30. data/lib/prism/lex_compat.rb +1 -0
  31. data/lib/prism/mutation_compiler.rb +3 -0
  32. data/lib/prism/node.rb +507 -336
  33. data/lib/prism/node_ext.rb +4 -1
  34. data/lib/prism/pack.rb +2 -0
  35. data/lib/prism/parse_result/comments.rb +1 -0
  36. data/lib/prism/parse_result/errors.rb +1 -0
  37. data/lib/prism/parse_result/newlines.rb +1 -0
  38. data/lib/prism/parse_result.rb +1 -0
  39. data/lib/prism/pattern.rb +1 -0
  40. data/lib/prism/polyfill/scan_byte.rb +14 -0
  41. data/lib/prism/polyfill/warn.rb +36 -0
  42. data/lib/prism/reflection.rb +3 -0
  43. data/lib/prism/relocation.rb +1 -0
  44. data/lib/prism/serialize.rb +25 -19
  45. data/lib/prism/string_query.rb +1 -0
  46. data/lib/prism/translation/parser/builder.rb +1 -0
  47. data/lib/prism/translation/parser/compiler.rb +47 -25
  48. data/lib/prism/translation/parser/lexer.rb +29 -21
  49. data/lib/prism/translation/parser.rb +21 -2
  50. data/lib/prism/translation/parser33.rb +1 -0
  51. data/lib/prism/translation/parser34.rb +1 -0
  52. data/lib/prism/translation/parser35.rb +1 -0
  53. data/lib/prism/translation/parser_current.rb +24 -0
  54. data/lib/prism/translation/ripper/sexp.rb +1 -0
  55. data/lib/prism/translation/ripper.rb +17 -1
  56. data/lib/prism/translation/ruby_parser.rb +287 -4
  57. data/lib/prism/translation.rb +2 -0
  58. data/lib/prism/visitor.rb +457 -152
  59. data/lib/prism.rb +23 -0
  60. data/prism.gemspec +5 -1
  61. data/rbi/prism/dsl.rbi +3 -3
  62. data/rbi/prism/node.rbi +21 -9
  63. data/sig/prism/dispatcher.rbs +3 -0
  64. data/sig/prism/dsl.rbs +3 -3
  65. data/sig/prism/node.rbs +444 -30
  66. data/sig/prism/node_ext.rbs +84 -17
  67. data/sig/prism/parse_result/comments.rbs +38 -0
  68. data/sig/prism/parse_result.rbs +4 -0
  69. data/sig/prism/reflection.rbs +1 -1
  70. data/sig/prism.rbs +4 -0
  71. data/src/diagnostic.c +9 -1
  72. data/src/node.c +2 -0
  73. data/src/options.c +2 -2
  74. data/src/prettyprint.c +2 -0
  75. data/src/prism.c +324 -147
  76. data/src/serialize.c +2 -0
  77. data/src/token_type.c +36 -34
  78. data/src/util/pm_string.c +6 -8
  79. metadata +7 -3
@@ -6,34 +6,19 @@ Prism ships with the ability to translate its syntax tree into the syntax tree u
6
6
 
7
7
  The `parser` gem provides multiple parsers to support different versions of the Ruby grammar. This includes all of the Ruby versions going back to 1.8, as well as third-party parsers like MacRuby and RubyMotion. The `prism` gem provides another parser that uses the `prism` parser to build the syntax tree.
8
8
 
9
- You can use the `prism` parser like you would any other. After requiring the parser, you should be able to call any of the regular `Parser::Base` APIs that you would normally use.
9
+ You can use the `prism` parser like you would any other. After requiring `prism`, you should be able to call any of the regular `Parser::Base` APIs that you would normally use.
10
10
 
11
11
  ```ruby
12
12
  require "prism"
13
13
 
14
- Prism::Translation::Parser.parse_file("path/to/file.rb")
15
- ```
16
-
17
- ### RuboCop
18
-
19
- Prism as a parser engine is directly supported since RuboCop 1.62. The class used for parsing is `Prism::Translation::Parser`.
20
-
21
- First, specify `prism` in your Gemfile:
22
-
23
- ```ruby
24
- gem "prism"
25
- ```
26
-
27
- To use Prism with RuboCop, specify `ParserEngine` and `TargetRubyVersion` in your RuboCop configuration file:
14
+ # Same as `Parser::Ruby34`
15
+ Prism::Translation::Parser34.parse_file("path/to/file.rb")
28
16
 
29
- ```yaml
30
- AllCops:
31
- ParserEngine: parser_prism
32
- TargetRubyVersion: 3.3
17
+ # Same as `Parser::CurrentRuby`
18
+ Prism::Translation::ParserCurrent.parse("puts 'Hello World!'")
33
19
  ```
34
20
 
35
- The default value for `ParserEngine` is `parser_whitequark`, which indicates the Parser gem. You need to explicitly switch it to `parser_prism` to indicate Prism. Additionally, the value for `TargetRubyVersion` must be specified as `3.3` or higher, as Prism supports parsing versions of Ruby 3.3 and higher.
36
- The parser class is determined by the combination of values for `ParserEngine` and `TargetRubyVersion`. For example, if `TargetRubyVersion: 3.3`, parsing is performed by `Prism::Translation::Parser33`, and for `TargetRubyVersion 3.4`, parsing is performed by `Prism::Translation::Parser34`.
21
+ All the parsers are autoloaded, so you don't have to worry about requiring them yourself.
37
22
 
38
- For further information, please refer to the RuboCop documentation:
39
- https://docs.rubocop.org/rubocop/configuration.html#setting-the-parser-engine
23
+ If you also need to parse Ruby versions below 3.3 (for which the `prism` translation layer does not have explicit support), check out
24
+ [this guide](https://github.com/whitequark/parser/blob/master/doc/PRISM_TRANSLATION.md) from the `parser` gem on how to use both in conjunction.
data/docs/releasing.md CHANGED
@@ -47,7 +47,10 @@ bundle install
47
47
  * Update the version-specific lockfiles:
48
48
 
49
49
  ```sh
50
- bin/prism bundle install
50
+ for VERSION in "2.7" "3.0" "3.1" "3.2" "3.3" "3.4"; do docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/$VERSION/Gemfile" "ruby:$VERSION" bundle update; done
51
+ docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/3.5/Gemfile" ruby:3.5.0-preview1 bundle update
52
+ docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/jruby/Gemfile" jruby:latest bundle update
53
+ BUNDLE_GEMFILE=gemfiles/truffleruby/Gemfile chruby-exec truffleruby -- bundle update
51
54
  ```
52
55
 
53
56
  * Update the cargo lockfiles:
@@ -71,26 +74,4 @@ git push
71
74
  ## Publishing
72
75
 
73
76
  * Update the GitHub release page with a copy of the latest entry in the `CHANGELOG.md` file.
74
- * Publish the gem to [rubygems.org](rubygems.org). Note that you must have access to the `prism` gem to do this.
75
-
76
- ```sh
77
- bundle exec rake release
78
- ```
79
-
80
- * Generate the `wasm` artifact (or download it from GitHub actions and put it in `javascript/src/prism.wasm`).
81
-
82
- ```sh
83
- make wasm
84
- ```
85
-
86
- * Publish the JavaScript package to [npmjs.com](npmjs.com). Note that you must have access to the `@ruby/prism` package to do this.
87
-
88
- ```sh
89
- npm publish
90
- ```
91
-
92
- * Publish the rust crate to [crates.io](crates.io). Note that you must have access to the `ruby-prism-sys` and `ruby-prism` crates to do this.
93
-
94
- ```sh
95
- bundle exec rake cargo:publish:real
96
- ```
77
+ * Push a new tag to the GitHub repository, following the `vX.Y.Z` format.
@@ -55,7 +55,7 @@ It is helpful to understand the differences between the `Ripper` library and the
55
55
 
56
56
  ### Design
57
57
 
58
- `Ripper` is a streaming parser. This means as it is parsing Ruby code, it dispatches events back to the consumer. This allows quite a bit of flexibility. You can use it to build your own syntax tree or to find specific patterns in the code. `Prism` on the other hand returns to your the completed syntax tree _before_ it allows you to manipulate it. This means the tree that you get back is the only representation that can be generated by the parser _at parse time_ (but of course can be manipulated later).
58
+ `Ripper` is a streaming parser. This means as it is parsing Ruby code, it dispatches events back to the consumer. This allows quite a bit of flexibility. You can use it to build your own syntax tree or to find specific patterns in the code. `Prism` on the other hand returns to you the completed syntax tree _before_ it allows you to manipulate it. This means the tree that you get back is the only representation that can be generated by the parser _at parse time_ (but of course can be manipulated later).
59
59
 
60
60
  ### Fields
61
61
 
data/ext/prism/api_node.c CHANGED
@@ -1,3 +1,5 @@
1
+ /* :markup: markdown */
2
+
1
3
  /*----------------------------------------------------------------------------*/
2
4
  /* This file is generated by the templates/template.rb script and should not */
3
5
  /* be modified manually. See */
@@ -25,6 +25,7 @@ VALUE rb_cPrismLexResult;
25
25
  VALUE rb_cPrismParseLexResult;
26
26
  VALUE rb_cPrismStringQuery;
27
27
  VALUE rb_cPrismScope;
28
+ VALUE rb_cPrismCurrentVersionError;
28
29
 
29
30
  VALUE rb_cPrismDebugEncoding;
30
31
 
@@ -199,7 +200,13 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
199
200
  if (!NIL_P(value)) {
200
201
  const char *version = check_string(value);
201
202
 
202
- if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
203
+ if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) {
204
+ VALUE current_ruby_value = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION"));
205
+ const char *current_version = RSTRING_PTR(current_ruby_value);
206
+ if (!pm_options_version_set(options, current_version, 3)) {
207
+ rb_exc_raise(rb_exc_new_str(rb_cPrismCurrentVersionError, current_ruby_value));
208
+ }
209
+ } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
203
210
  rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
204
211
  }
205
212
  }
@@ -888,7 +895,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
888
895
  * version of Ruby syntax (which you can trigger with `nil` or
889
896
  * `"latest"`). You may also restrict the syntax to a specific version of
890
897
  * Ruby, e.g., with `"3.3.0"`. To parse with the same syntax version that
891
- * the current Ruby is running use `version: RUBY_VERSION`. Raises
898
+ * the current Ruby is running use `version: "current"`. Raises
892
899
  * ArgumentError if the version is not currently supported by Prism.
893
900
  */
894
901
  static VALUE
@@ -994,6 +1001,14 @@ profile_file(int argc, VALUE *argv, VALUE self) {
994
1001
  return Qnil;
995
1002
  }
996
1003
 
1004
+ static int
1005
+ parse_stream_eof(void *stream) {
1006
+ if (rb_funcall((VALUE) stream, rb_intern("eof?"), 0)) {
1007
+ return 1;
1008
+ }
1009
+ return 0;
1010
+ }
1011
+
997
1012
  /**
998
1013
  * An implementation of fgets that is suitable for use with Ruby IO objects.
999
1014
  */
@@ -1034,7 +1049,7 @@ parse_stream(int argc, VALUE *argv, VALUE self) {
1034
1049
  pm_parser_t parser;
1035
1050
  pm_buffer_t buffer;
1036
1051
 
1037
- pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, &options);
1052
+ pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options);
1038
1053
  rb_encoding *encoding = rb_enc_find(parser.encoding->name);
1039
1054
 
1040
1055
  VALUE source = pm_source_new(&parser, encoding, options.freeze);
@@ -1331,6 +1346,11 @@ Init_prism(void) {
1331
1346
  );
1332
1347
  }
1333
1348
 
1349
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
1350
+ // Mark this extension as Ractor-safe.
1351
+ rb_ext_ractor_safe(true);
1352
+ #endif
1353
+
1334
1354
  // Grab up references to all of the constants that we're going to need to
1335
1355
  // reference throughout this extension.
1336
1356
  rb_cPrism = rb_define_module("Prism");
@@ -1351,6 +1371,8 @@ Init_prism(void) {
1351
1371
  rb_cPrismStringQuery = rb_define_class_under(rb_cPrism, "StringQuery", rb_cObject);
1352
1372
  rb_cPrismScope = rb_define_class_under(rb_cPrism, "Scope", rb_cObject);
1353
1373
 
1374
+ rb_cPrismCurrentVersionError = rb_const_get(rb_cPrism, rb_intern("CurrentVersionError"));
1375
+
1354
1376
  // Intern all of the IDs eagerly that we support so that we don't have to do
1355
1377
  // it every time we parse.
1356
1378
  rb_id_option_command_line = rb_intern_const("command_line");
@@ -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 "1.4.0"
4
+ #define EXPECTED_PRISM_VERSION "1.6.0"
5
5
 
6
6
  #include <ruby.h>
7
7
  #include <ruby/encoding.h>