prettier 2.0.0.pre.rc1 → 2.0.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: d1015fa9f7c5b4f580afa9c6b24042c8799762e5d13835dbb492abfe33f676b8
4
- data.tar.gz: 53045f82f75561082c6120d836d3abdffb07cccb31e5272442ef2608014f8f6d
3
+ metadata.gz: a8393d82622bcce83298aa8e2833b37bccf9742b0a67e81cd3b730e57e6795b8
4
+ data.tar.gz: a66af4efc73854f143e0faa288fdde112bf87ba45364af3efd862a179734453c
5
5
  SHA512:
6
- metadata.gz: 4f4541af3e4e4047f03c4c34890506b25126d34e052b92023d40e7bb68b5184cfce9c91ba5794478b21b61952e1823d4f7e08d51b52d468a9de61f270f9d61a0
7
- data.tar.gz: 983d6da92e456dae0f081a2ee4b77f4a47d540415f991c51d91006a2847ac38937574e76f82bd376fb9e47401deeb5bd77414c10b3ab80a9d4adaa7a7e66499e
6
+ metadata.gz: f780174b5b038bfd9583c637caefff23e442f4aef626e9e33769811c15afd7c267bb78f20c4eb223ab4b50f3c0b6664123c6ce00d997ff0a571b0d57228f5070
7
+ data.tar.gz: bdfbd3f42b4db020059b511b3176ee7b5393a5a008136dd06a584c26df69afbcfe7d937e6151e22029858d71bad68e8c68eb07241e67771debd802cf733c282d
data/CHANGELOG.md CHANGED
@@ -6,7 +6,43 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- ## [2.0.0-rc1]
9
+ ## [2.0.0] - 2021-10-28
10
+
11
+ ### Changed
12
+
13
+ - [#1018](https://github.com/prettier/plugin-ruby/issues/1018) - rindek, kddnewton - Ensure brackets are used when matching an array pattern with a single element.
14
+ - [#906](https://github.com/prettier/plugin-ruby/issues/906) - Hansenq, kddnewton - Turn off the `Style/MultilineBlockChain` rubocop rule in our shipped configuration because multiple chained method calls with blocks can potentially conflict with rubocop's desired output.
15
+
16
+ ## [2.0.0-rc4] - 2021-10-18
17
+
18
+ ### Added
19
+
20
+ - [#993](https://github.com/prettier/plugin-ruby/pull/993) - kddnewton - Nicer error message if you don't have the necessary JavaScript files to run prettier.
21
+ - [#996](https://github.com/prettier/plugin-ruby/pull/996) - nbudin - Allow `@prettier/plugin-ruby` to run in yarn's plug'n'play mode.
22
+
23
+ ### Changed
24
+
25
+ - [#1000](https://github.com/prettier/plugin-ruby/pull/1000) - nbudin, kddnewton - Fix for rescuing single top-level exceptions in `rescue` clauses.
26
+
27
+ ## [2.0.0-rc3] - 2021-10-01
28
+
29
+ ### Changed
30
+
31
+ - [#987](https://github.com/prettier/plugin-ruby/pull/9870) - valscion - Ignore stderr when checking for node <-> ruby connection clients, restoring the behavior of v1.x
32
+ - [#989](https://github.com/prettier/plugin-ruby/issues/989) - hubertjakubiak, kddnewton - Make sure comments after the keyword/lbrace are not moved inside the body of the statements of do and brace blocks.
33
+
34
+ ## [2.0.0-rc2] - 2021-09-30
35
+
36
+ ### Added
37
+
38
+ - [#979](https://github.com/prettier/plugin-ruby/issues/979) - ronocod, kddnewton - Alignment of `to_not` is explicitly allowed to not indent to better support rspec.
39
+ - [#894](https://github.com/prettier/plugin-ruby/issues/894) - mister-what, kddnewton - Add a warning that this plugin will not function with the plug'n'play filesystem provided by yarn berry.
40
+
41
+ ### Changed
42
+
43
+ - [#943](https://github.com/prettier/plugin-ruby/issues/943) - valscion, kddnewton - Trailing call operators that are followed by comments should stay on the first line.
44
+
45
+ ## [2.0.0-rc1] - 2021-09-30
10
46
 
11
47
  ### Added
12
48
 
@@ -1151,7 +1187,11 @@ would previously result in `array[]`, but now prints properly.
1151
1187
 
1152
1188
  - Initial release 🎉
1153
1189
 
1154
- [unreleased]: https://github.com/prettier/plugin-ruby/compare/v2.0.0-rc1...HEAD
1190
+ [unreleased]: https://github.com/prettier/plugin-ruby/compare/v2.0.0...HEAD
1191
+ [2.0.0]: https://github.com/prettier/plugin-ruby/compare/v2.0.0-rc4...v2.0.0
1192
+ [2.0.0-rc4]: https://github.com/prettier/plugin-ruby/compare/v2.0.0-rc3...v2.0.0-rc4
1193
+ [2.0.0-rc3]: https://github.com/prettier/plugin-ruby/compare/v2.0.0-rc2...v2.0.0-rc3
1194
+ [2.0.0-rc2]: https://github.com/prettier/plugin-ruby/compare/v2.0.0-rc1...v2.0.0-rc2
1155
1195
  [2.0.0-rc1]: https://github.com/prettier/plugin-ruby/compare/v1.6.1...v2.0.0-rc1
1156
1196
  [1.6.1]: https://github.com/prettier/plugin-ruby/compare/v1.6.0...v1.6.1
1157
1197
  [1.6.0]: https://github.com/prettier/plugin-ruby/compare/v1.5.5...v1.6.0
@@ -58,8 +58,53 @@ exports.getInfoFilepath = getInfoFilepath;
58
58
  // will read that information in order to enable us to connect to it in the
59
59
  // spawnSync function.
60
60
  function spawnServer() {
61
+ const tempDir = (0, fs_1.mkdtempSync)(path_1.default.join(os_1.default.tmpdir(), "prettier-plugin-ruby-"));
61
62
  const filepath = getInfoFilepath();
62
- const server = (0, child_process_1.spawn)("ruby", [path_1.default.join(__dirname, "./server.rb"), filepath], {
63
+ let serverRbPath = path_1.default.join(__dirname, "./server.rb");
64
+ let getInfoJsPath = path_1.default.join(__dirname, "./getInfo.js");
65
+ let cleanupTempFiles;
66
+ if (runningInPnPZip()) {
67
+ // If we're running in a Yarn PnP environment inside a ZIP file, it's not possible to run
68
+ // the Ruby server or the getInfo.js script directly. Instead, we need to copy them and all
69
+ // the files they depend on to a temporary directory.
70
+ const sourceFiles = [
71
+ "parser/server.rb",
72
+ "parser/getInfo.js",
73
+ "parser/netcat.js",
74
+ "ruby/parser.rb",
75
+ "rbs/parser.rb",
76
+ "haml/parser.rb"
77
+ ];
78
+ serverRbPath = path_1.default.join(tempDir, "parser", "server.rb");
79
+ getInfoJsPath = path_1.default.join(tempDir, "parser", "getInfo.js");
80
+ sourceFiles.forEach((rubyFile) => {
81
+ const destDir = path_1.default.join(tempDir, path_1.default.dirname(rubyFile));
82
+ if (!(0, fs_1.existsSync)(destDir)) {
83
+ (0, fs_1.mkdirSync)(destDir);
84
+ }
85
+ (0, fs_1.copyFileSync)(path_1.default.join(__dirname, "..", rubyFile), path_1.default.join(tempDir, rubyFile));
86
+ });
87
+ cleanupTempFiles = () => {
88
+ [
89
+ getInfoJsPath,
90
+ ...sourceFiles.map((rubyFile) => path_1.default.join(tempDir, rubyFile))
91
+ ].forEach((tmpFilePath) => {
92
+ if ((0, fs_1.existsSync)(tmpFilePath)) {
93
+ (0, fs_1.unlinkSync)(tmpFilePath);
94
+ }
95
+ });
96
+ sourceFiles.forEach((rubyFile) => {
97
+ const tempSubdir = path_1.default.join(tempDir, path_1.default.dirname(rubyFile));
98
+ if ((0, fs_1.existsSync)(tempSubdir)) {
99
+ (0, fs_1.rmdirSync)(tempSubdir);
100
+ }
101
+ });
102
+ if ((0, fs_1.existsSync)(tempDir)) {
103
+ (0, fs_1.rmdirSync)(tempDir);
104
+ }
105
+ };
106
+ }
107
+ const server = (0, child_process_1.spawn)("ruby", [serverRbPath, filepath], {
63
108
  env: Object.assign({}, process_1.default.env, { LANG: getLang() }),
64
109
  detached: true,
65
110
  stdio: "inherit"
@@ -69,6 +114,9 @@ function spawnServer() {
69
114
  if ((0, fs_1.existsSync)(filepath)) {
70
115
  (0, fs_1.unlinkSync)(filepath);
71
116
  }
117
+ if (cleanupTempFiles != null) {
118
+ cleanupTempFiles();
119
+ }
72
120
  try {
73
121
  if (server.pid) {
74
122
  process_1.default.kill(-server.pid);
@@ -80,10 +128,7 @@ function spawnServer() {
80
128
  }
81
129
  }
82
130
  });
83
- const info = (0, child_process_1.spawnSync)("node", [
84
- path_1.default.join(__dirname, "./getInfo.js"),
85
- filepath
86
- ]);
131
+ const info = (0, child_process_1.spawnSync)("node", [getInfoJsPath, filepath]);
87
132
  if (info.status !== 0) {
88
133
  throw new Error(`
89
134
  We failed to spawn our parser server. Please report this error on GitHub
@@ -95,6 +140,12 @@ function spawnServer() {
95
140
  const [cmd, ...args] = info.stdout.toString().split(" ");
96
141
  return { cmd, args };
97
142
  }
143
+ // If we're in a yarn Plug'n'Play environment, then the relative paths being
144
+ // used by the parser server and the various scripts used to communicate
145
+ // therein are not going to work with its virtual file system.
146
+ function runningInPnPZip() {
147
+ return process_1.default.versions.pnp && __dirname.includes(".zip");
148
+ }
98
149
  // Formats and sends a request to the parser server. We use netcat (or something
99
150
  // like it) here since Prettier requires the results of `parse` to be
100
151
  // synchronous and Node.js does not offer a mechanism for synchronous socket
@@ -112,8 +112,9 @@ candidates.map! do |candidate|
112
112
  Thread.new do
113
113
  Thread.current.report_on_exception = false
114
114
 
115
- stdout, status =
116
- Open3.capture2("#{candidate} #{information}", stdin_data: 'ping')
115
+ # We do not care about stderr here, so throw it away
116
+ stdout, _stderr, status =
117
+ Open3.capture3("#{candidate} #{information}", stdin_data: 'ping')
117
118
 
118
119
  candidate if JSON.parse(stdout) == 'pong' && status.exitstatus == 0
119
120
  rescue StandardError
@@ -17,6 +17,23 @@ const printBlockVar = (path, opts, print) => {
17
17
  return parts;
18
18
  };
19
19
  exports.printBlockVar = printBlockVar;
20
+ // You have to go through the main print function if you could potentially have
21
+ // comments attached. So we're doing this weird reflection on the printed docs
22
+ // to retroactively change the printed keyword depending on if we're using
23
+ // braces or not. Ideally we wouldn't do this, we would instead do this
24
+ // reflection in the child printer, but this keeps the logic to just this file
25
+ // and contains it, so keeping it here for now.
26
+ function printBlockBeging(path, print, useBraces) {
27
+ let docs = print(path);
28
+ const doc = useBraces ? "{" : "do";
29
+ if (Array.isArray(docs)) {
30
+ docs[1] = doc;
31
+ }
32
+ else {
33
+ docs = doc;
34
+ }
35
+ return docs;
36
+ }
20
37
  function printBlock(braces) {
21
38
  return function printBlockWithBraces(path, opts, print) {
22
39
  const [variables, statements] = path.getValue().body;
@@ -34,7 +51,8 @@ function printBlock(braces) {
34
51
  // switch to using braces instead.
35
52
  const useBraces = braces && (0, utils_1.hasAncestor)(path, ["command", "command_call"]);
36
53
  const doBlock = [
37
- useBraces ? " {" : " do",
54
+ " ",
55
+ path.call((begingPath) => printBlockBeging(begingPath, print, useBraces), "beging"),
38
56
  variables ? [" ", path.call(print, "body", 0)] : "",
39
57
  doBlockBody,
40
58
  [softline, useBraces ? "}" : "end"]
@@ -54,7 +72,8 @@ function printBlock(braces) {
54
72
  }
55
73
  const hasBody = stmts.some(({ type }) => type !== "void_stmt");
56
74
  const braceBlock = [
57
- " {",
75
+ " ",
76
+ path.call((begingPath) => printBlockBeging(begingPath, print, true), "beging"),
58
77
  hasBody || variables ? " " : "",
59
78
  variables ? path.call(print, "body", 0) : "",
60
79
  path.call(print, "body", 1),
@@ -9,6 +9,10 @@ const utils_1 = require("../../utils");
9
9
  const toProc_1 = __importDefault(require("../toProc"));
10
10
  const { group, hardline, ifBreak, indent, join, softline } = prettier_1.default;
11
11
  const chained = ["call", "method_add_arg", "method_add_block"];
12
+ function hasLeadingComments(node) {
13
+ var _a;
14
+ return (_a = node.comments) === null || _a === void 0 ? void 0 : _a.some(({ leading }) => leading);
15
+ }
12
16
  const printCall = (path, opts, print) => {
13
17
  const node = path.getValue();
14
18
  const [receiverNode, , messageNode] = node.body;
@@ -18,26 +22,40 @@ const printCall = (path, opts, print) => {
18
22
  // In this case, "call" is returned for the 3rd child node. We don't alter
19
23
  // call syntax so if `call` is implicit, we don't print it out.
20
24
  const messageDoc = messageNode === "call" ? "" : path.call(print, "body", 2);
25
+ // Create some arrays that are going to represent each side of our call.
26
+ let leftSideDoc = [receiverDoc];
27
+ let rightSideDoc = [operatorDoc, messageDoc];
28
+ // If there are leading comments on the right side of the call, then it means
29
+ // we have a structure where there's a receiver and an operator together, then
30
+ // a comment, then the message, as in:
31
+ //
32
+ // foo.
33
+ // # comment
34
+ // baz
35
+ //
36
+ // In the case we need to group the receiver and the operator together or
37
+ // we'll end up with a syntax error.
38
+ const operatorIsTrailing = messageNode !== "call" && hasLeadingComments(messageNode);
39
+ if (operatorIsTrailing) {
40
+ leftSideDoc = [receiverDoc, operatorDoc];
41
+ rightSideDoc = [messageDoc];
42
+ }
21
43
  // For certain left sides of the call nodes, we want to attach directly to
22
44
  // the } or end.
23
45
  if (utils_1.noIndent.includes(receiverNode.type)) {
24
- return [receiverDoc, operatorDoc, messageDoc];
46
+ return [leftSideDoc, rightSideDoc];
25
47
  }
26
- // The right side of the call node, as in everything including the operator
27
- // and beyond.
28
- let rightSideDoc = [
29
- receiverNode.comments ? hardline : softline,
30
- operatorDoc,
31
- messageDoc
32
- ];
33
- // This is very specialized behavior wherein we group .where.not calls
34
- // together because it looks better. For more information, see
35
- // https://github.com/prettier/plugin-ruby/issues/862.
36
48
  if (receiverNode.type === "call" &&
37
49
  receiverNode.body[2] !== "call" &&
38
50
  receiverNode.body[2].body === "where" &&
39
51
  messageDoc === "not") {
40
- rightSideDoc = [operatorDoc, messageDoc];
52
+ // This is very specialized behavior wherein we group .where.not calls
53
+ // together because it looks better. For more information, see
54
+ // https://github.com/prettier/plugin-ruby/issues/862.
55
+ }
56
+ else {
57
+ // Otherwise, we're going to put a line node into the right side doc.
58
+ rightSideDoc.unshift(receiverNode.comments ? hardline : softline);
41
59
  }
42
60
  // Get a reference to the parent node so we can check if we're inside a chain
43
61
  const parentNode = path.getParentNode();
@@ -46,8 +64,30 @@ const printCall = (path, opts, print) => {
46
64
  if (chained.includes(parentNode.type) && !node.comments) {
47
65
  parentNode.chain = (node.chain || 0) + 1;
48
66
  parentNode.callChain = (node.callChain || 0) + 1;
49
- parentNode.breakDoc = (node.breakDoc || [receiverDoc]).concat(rightSideDoc);
50
67
  parentNode.firstReceiverType = node.firstReceiverType || receiverNode.type;
68
+ // Here we're going to determine what doc nodes to send up to the parent
69
+ // node to represent when we're in the multi-line form.
70
+ let breakDocLHS;
71
+ if (node.breakDoc && operatorIsTrailing) {
72
+ // Here we already have a child node that has passed up its
73
+ // representation. In this case node.breakDoc represents the receiver
74
+ // without any lines inserted. With regard to this node, it means it's
75
+ // everything up until the operator. So we're just going to append the
76
+ // operator.
77
+ breakDocLHS = node.breakDoc.concat(operatorDoc);
78
+ }
79
+ else if (node.breakDoc) {
80
+ // Here we don't need a trailing operator, so we're just going to use the
81
+ // existing node.breakDoc. The operator will be a part of the rightSideDoc
82
+ // variable.
83
+ breakDocLHS = node.breakDoc;
84
+ }
85
+ else {
86
+ // Here we're at the bottom of the chain, so there's no representation yet
87
+ // for the receiver. So we're just going to pass up the left side.
88
+ breakDocLHS = leftSideDoc;
89
+ }
90
+ parentNode.breakDoc = breakDocLHS.concat(rightSideDoc);
51
91
  }
52
92
  // If we're at the top of a chain, then we're going to print out a nice
53
93
  // multi-line layout if this doesn't break into multiple lines.
@@ -55,11 +95,11 @@ const printCall = (path, opts, print) => {
55
95
  (node.chain || 0) >= 3 &&
56
96
  node.breakDoc) {
57
97
  return ifBreak(group(indent(node.breakDoc.concat(rightSideDoc))), [
58
- receiverDoc,
98
+ leftSideDoc,
59
99
  group(rightSideDoc)
60
100
  ]);
61
101
  }
62
- return group([receiverDoc, group(indent(rightSideDoc))]);
102
+ return group([leftSideDoc, group(indent(rightSideDoc))]);
63
103
  };
64
104
  exports.printCall = printCall;
65
105
  const printMethodAddArg = (path, opts, print) => {
@@ -62,8 +62,8 @@ function hasDef(node) {
62
62
  //
63
63
  // In this case the arguments are aligned to the left side as opposed to being
64
64
  // aligned with the `receive` call.
65
- function skipArgsAlign(path) {
66
- return ["to", "not_to"].includes(path.getValue().body[2].body);
65
+ function skipArgsAlign(node) {
66
+ return ["to", "not_to", "to_not"].includes(node.body[2].body);
67
67
  }
68
68
  // If there is a ternary argument to a command and it's going to get broken
69
69
  // into multiple lines, then we're going to have to use parentheses around the
@@ -110,7 +110,7 @@ const printCommandCall = (path, opts, print) => {
110
110
  breakDoc = parts.concat("(", indent([softline, argDocs]), softline, ")");
111
111
  parts.push(" ");
112
112
  }
113
- else if (skipArgsAlign(path)) {
113
+ else if (skipArgsAlign(node)) {
114
114
  parts.push(" ");
115
115
  breakDoc = parts.concat(argDocs);
116
116
  }
@@ -19,24 +19,36 @@ const printPatternArg = (path, opts, print) => {
19
19
  };
20
20
  const printAryPtn = (path, opts, print) => {
21
21
  const [constant, preargs, splatarg, postargs] = path.getValue().body;
22
- let args = [];
22
+ let argDocs = [];
23
23
  if (preargs) {
24
- args = args.concat(path.map((argPath) => printPatternArg(argPath, opts, print), "body", 1));
24
+ argDocs = argDocs.concat(path.map((argPath) => printPatternArg(argPath, opts, print), "body", 1));
25
25
  }
26
26
  if (splatarg) {
27
- args.push(["*", path.call(print, "body", 2)]);
27
+ argDocs.push(["*", path.call(print, "body", 2)]);
28
28
  }
29
29
  if (postargs) {
30
- args = args.concat(path.map(print, "body", 3));
30
+ argDocs = argDocs.concat(path.map(print, "body", 3));
31
31
  }
32
- args = group(join([",", line], args));
33
- if (constant || patterns.includes(path.getParentNode().type)) {
34
- args = ["[", args, "]"];
32
+ let argDoc = group(join([",", line], argDocs));
33
+ // There are a couple of cases where we _must_ use brackets. They include:
34
+ //
35
+ // * When the number of arguments inside the array pattern is one 1, then we
36
+ // have to include them, otherwise it matches the whole array. Consider the
37
+ // difference between `in [elem]` and `in elem`.
38
+ // * If we have a wrapping constant, then we definitely need the brackets.
39
+ // Consider the difference between `in Const[elem]` and `in Const elem`
40
+ // * If we're nested inside a parent pattern, then we have to have brackets.
41
+ // Consider the difference between `in key: first, second` and
42
+ // `in key: [first, second]`.
43
+ if (argDocs.length === 1 ||
44
+ constant ||
45
+ patterns.includes(path.getParentNode().type)) {
46
+ argDoc = ["[", argDoc, "]"];
35
47
  }
36
48
  if (constant) {
37
- return [path.call(print, "body", 0), args];
49
+ return [path.call(print, "body", 0), argDoc];
38
50
  }
39
- return args;
51
+ return argDoc;
40
52
  };
41
53
  exports.printAryPtn = printAryPtn;
42
54
  const printFndPtn = (path, opts, print) => {
@@ -86,9 +98,10 @@ const printHshPtn = (path, opts, print) => {
86
98
  };
87
99
  exports.printHshPtn = printHshPtn;
88
100
  const printIn = (path, opts, print) => {
101
+ const keyword = "in ";
89
102
  const parts = [
90
- "in ",
91
- align("in ".length, path.call((valuePath) => printPatternArg(valuePath, opts, print), "body", 0)),
103
+ keyword,
104
+ align(keyword.length, path.call((valuePath) => printPatternArg(valuePath, opts, print), "body", 0)),
92
105
  indent([hardline, path.call(print, "body", 1)])
93
106
  ];
94
107
  if (path.getValue().body[2]) {
@@ -52,10 +52,13 @@ const printRescueEx = (path, opts, print) => {
52
52
  const [exception, variable] = path.getValue().body;
53
53
  const parts = [];
54
54
  if (exception) {
55
+ // If there's just one exception being rescued, then it's just going to be a
56
+ // single doc node.
55
57
  let exceptionDoc = path.call(print, "body", 0);
56
- if (Array.isArray(exceptionDoc)) {
57
- const joiner = [",", line];
58
- exceptionDoc = group(join(joiner, exceptionDoc));
58
+ // If there are multiple exceptions being rescued, then we're going to have
59
+ // multiple doc nodes returned as an array that we need to join together.
60
+ if (["mrhs_add_star", "mrhs_new_from_args"].includes(exception.type)) {
61
+ exceptionDoc = group(join([",", line], exceptionDoc));
59
62
  }
60
63
  parts.push(" ", exceptionDoc);
61
64
  }
data/dist/ruby/parser.rb CHANGED
@@ -136,12 +136,6 @@ class Prettier::Parser < Ripper
136
136
  # keyword.
137
137
  @__end__ = nil
138
138
 
139
- # Magic comments are a certain kind of comment that can impact the way the
140
- # file is parsed (encoding/string frozen default/etc.). These scanner events
141
- # are immediately followed by a comment scanner event, so we only need the
142
- # one variable to set/unset it immediately.
143
- @magic_comment = nil
144
-
145
139
  # Heredocs can actually be nested together if you're using interpolation, so
146
140
  # this is a stack of heredoc nodes that are currently being created. When we
147
141
  # get to the scanner event that finishes off a heredoc node, we pop the top
@@ -799,11 +793,15 @@ class Prettier::Parser < Ripper
799
793
  beging = find_scanner_event(:@lbrace)
800
794
  ending = find_scanner_event(:@rbrace)
801
795
 
802
- stmts.bind((block_var || beging)[:ec], ending[:sc])
796
+ stmts.bind(
797
+ find_next_statement_start((block_var || beging)[:ec]),
798
+ ending[:sc]
799
+ )
803
800
 
804
801
  {
805
802
  type: :brace_block,
806
803
  body: [block_var, stmts],
804
+ beging: beging,
807
805
  sl: beging[:sl],
808
806
  sc: beging[:sc],
809
807
  el: [ending[:el], stmts[:el]].max,
@@ -970,22 +968,6 @@ class Prettier::Parser < Ripper
970
968
  start_line = lineno
971
969
  start_char = char_pos
972
970
 
973
- # If we already had special handling of a magic comment, then we can just
974
- # skip and return the value of that node.
975
- if @magic_comment
976
- comment = @magic_comment
977
- @magic_comment = nil
978
-
979
- # At the moment, merging in the value of the string being passed into
980
- # here. In the next major version I'd like to remove this and just use the
981
- # value of the magic comment. At the moment though that would change
982
- # comments like -*- encoding: UTF-8 -*- into encoding: UTF-8 so need to
983
-
984
- # wait for a major version to do that.
985
- @comments << comment.merge(value: body, ec: start_char + value.length - 1)
986
- return comment
987
- end
988
-
989
971
  @comments << {
990
972
  type: :@comment,
991
973
  value: body,
@@ -1208,11 +1190,15 @@ class Prettier::Parser < Ripper
1208
1190
  beging = find_scanner_event(:@kw, 'do')
1209
1191
  ending = find_scanner_event(:@kw, 'end')
1210
1192
 
1211
- bodystmt.bind((block_var || beging)[:ec], ending[:sc])
1193
+ bodystmt.bind(
1194
+ find_next_statement_start((block_var || beging)[:ec]),
1195
+ ending[:sc]
1196
+ )
1212
1197
 
1213
1198
  {
1214
1199
  type: :do_block,
1215
1200
  body: [block_var, bodystmt],
1201
+ beging: beging,
1216
1202
  sl: beging[:sl],
1217
1203
  sc: beging[:sc],
1218
1204
  el: ending[:el],
@@ -2012,20 +1998,12 @@ class Prettier::Parser < Ripper
2012
1998
  # magic_comment is a scanner event that represents the use of a pragma at the
2013
1999
  # beginning of the file. Usually it will inside something like
2014
2000
  # frozen_string_literal (the key) with a value of true (the value). Both
2015
- # children come is a string literals.
2016
- def on_magic_comment(key, value)
2017
- start_line = lineno
2018
- start_char = char_pos
2019
-
2020
- @magic_comment = {
2021
- type: :@comment,
2022
- value: " #{key}: #{value}",
2023
- sl: start_line,
2024
- el: start_line,
2025
- sc: start_char,
2026
- ec: start_char + @line_counts[start_line][-1]
2027
- }
2028
- end
2001
+ # children come is a string literals. We're going to leave these alone as they
2002
+ # come in all kinds of shapes and sizes.
2003
+ #
2004
+ # def on_magic_comment(key, value)
2005
+ # @magic_comment = { value: " #{key}: #{value}" }
2006
+ # end
2029
2007
 
2030
2008
  # massign is a parser event that is a parent node of any kind of multiple
2031
2009
  # assignment. This includes splitting out variables on the left like:
data/dist/ruby/printer.js CHANGED
@@ -67,6 +67,10 @@ const printer = {
67
67
  }
68
68
  return parts;
69
69
  }
70
+ case "brace_block":
71
+ return [node.body[0], node.body[1], node.beging];
72
+ case "do_block":
73
+ return [node.body[0], node.body[1], node.beging];
70
74
  case "paren":
71
75
  return [node.lparen, node.body[0]];
72
76
  default: {
data/exe/rbprettier CHANGED
@@ -4,5 +4,4 @@
4
4
  $:.unshift(File.expand_path(File.join('..', 'lib'), __dir__))
5
5
  require 'prettier'
6
6
 
7
- Prettier.run(ARGV)
8
- exit($?.exitstatus) if $?.exited?
7
+ exit(Prettier.run(ARGV))
data/lib/prettier.rb CHANGED
@@ -1,18 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json' unless defined?(JSON)
4
+ require 'open3'
4
5
 
5
6
  module Prettier
6
7
  PLUGIN = -File.expand_path('..', __dir__)
7
8
  BINARY = -File.join(PLUGIN, 'node_modules', 'prettier', 'bin-prettier.js')
8
9
  VERSION = -JSON.parse(File.read(File.join(PLUGIN, 'package.json')))['version']
9
10
 
10
- class << self
11
- def run(args)
12
- quoted = args.map { |arg| arg.start_with?('-') ? arg : "\"#{arg}\"" }
13
- command = "node #{BINARY} --plugin \"#{PLUGIN}\" #{quoted.join(' ')}"
11
+ def self.run(args)
12
+ quoted = args.map { |arg| arg.start_with?('-') ? arg : "\"#{arg}\"" }
13
+ command = "node #{BINARY} --plugin \"#{PLUGIN}\" #{quoted.join(' ')}"
14
14
 
15
- system({ 'RBPRETTIER' => '1' }, command)
15
+ stdout, stderr, status = Open3.capture3({ 'RBPRETTIER' => '1' }, command)
16
+ STDOUT.puts(stdout)
17
+
18
+ # If we completed successfully, then just exit out.
19
+ exitstatus = status.exitstatus
20
+ return exitstatus if exitstatus == 0
21
+
22
+ if stderr.match?(%r{Cannot find module '/.+?/bin-prettier.js'})
23
+ # If we're missing bin-prettier.js, then it's possible the user installed
24
+ # the gem through git, which wouldn't have installed the requisite
25
+ # JavaScript files.
26
+ STDERR.puts(<<~MSG)
27
+ Could not find the JavaScript files necessary to run prettier.
28
+
29
+ If you installed this dependency through git instead of from rubygems,
30
+ it does not install the necessary files by default. To fix this you can
31
+ either install them yourself by cd-ing into the directory where this gem
32
+ is located (#{File.expand_path('..', __dir__)}) and running:
33
+
34
+ `yarn && yarn prepublishOnly`
35
+ or
36
+ `npm install && npm run prepublishOnly`
37
+ or
38
+ you can change the source in your Gemfile to point directly to rubygems.
39
+ MSG
40
+ else
41
+ # Otherwise, just print out the same error that prettier emitted, as it's
42
+ # unknown to us.
43
+ STDERR.puts(stderr)
16
44
  end
45
+
46
+ # Make sure we still exit with the same status code the prettier emitted.
47
+ exitstatus
17
48
  end
18
49
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prettier/plugin-ruby",
3
- "version": "2.0.0-rc1",
3
+ "version": "2.0.0",
4
4
  "description": "prettier plugin for the Ruby programming language",
5
5
  "main": "dist/plugin.js",
6
6
  "scripts": {
@@ -26,9 +26,9 @@
26
26
  "@types/jest": "^27.0.1",
27
27
  "@types/node": "^16.9.1",
28
28
  "@types/prettier": "^2.3.2",
29
- "@typescript-eslint/eslint-plugin": "^4.31.2",
30
- "@typescript-eslint/parser": "^4.31.2",
31
- "eslint": "^7.22.0",
29
+ "@typescript-eslint/eslint-plugin": "^5.2.0",
30
+ "@typescript-eslint/parser": "^5.2.0",
31
+ "eslint": "^8.1.0",
32
32
  "eslint-config-prettier": "^8.0.0",
33
33
  "husky": "^7.0.0",
34
34
  "jest": "^27.0.1",
data/rubocop.yml CHANGED
@@ -13,12 +13,16 @@ Layout:
13
13
  Layout/LineLength:
14
14
  Enabled: true
15
15
 
16
- # Disabling all of the following options because they could conflict with a
17
- # prettier configuration setting.
18
-
19
16
  Style/MultilineIfModifier: # rubyModifier
20
17
  Enabled: false
21
18
 
19
+ # When method chains with multiple blocks are chained together, rubocop will let
20
+ # them pass if they're using braces but not if they're using do and end
21
+ # keywords. Because we will break individual blocks down to using keywords if
22
+ # they are multiline, this conflicts with rubocop.
23
+ Style/MultilineBlockChain:
24
+ Enabled: false
25
+
22
26
  Style/SymbolArray: # rubyArrayLiteral
23
27
  Enabled: false
24
28
 
@@ -34,5 +38,7 @@ Style/TrailingCommaInArrayLiteral: # trailingComma
34
38
  Style/TrailingCommaInHashLiteral: # trailingComma
35
39
  Enabled: false
36
40
 
41
+ # lambdas that are constructed with the lambda method call cannot be safely
42
+ # turned into lambda literals without removing a method call.
37
43
  Style/Lambda:
38
44
  Enabled: false
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prettier
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.rc1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Newton
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-30 00:00:00.000000000 Z
11
+ date: 2021-10-28 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -129,9 +129,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
129
  version: '0'
130
130
  required_rubygems_version: !ruby/object:Gem::Requirement
131
131
  requirements:
132
- - - ">"
132
+ - - ">="
133
133
  - !ruby/object:Gem::Version
134
- version: 1.3.1
134
+ version: '0'
135
135
  requirements: []
136
136
  rubygems_version: 3.2.3
137
137
  signing_key: