prettier 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b3f385a13ce2aae0cef657abc5d33e5d3d2fbfb59edf1fb39193ded2828cf87
4
- data.tar.gz: 1049cb733eb60e3221a7df64110f5841f39288f8e91cb589f08cc1c23a0ddfbe
3
+ metadata.gz: 0110d43bf561f7af177d93dce16dd6c8802bff3eb5c6603f6b72460903186b43
4
+ data.tar.gz: 48dd261628c7127b3baca0c6934c21993b68831c6d545494967642f5783e3d16
5
5
  SHA512:
6
- metadata.gz: ef14696b55d0dd1a544bba5fd45d88e3ab322ab9d2ae34d89b4b6bf84748ac35100022d5e050ed4ef0e5cf5ad93049c1782243cda27e4bae5b7dc87a2f951614
7
- data.tar.gz: 1bedee0f2b091bc7b7b10ceb645d183271dcea847f8b843c79cd6db5ebf078bb94d7d91fd255127f77c71eb9edd185dcfa166ffe9c442f315f64beb9ba57f4ee
6
+ metadata.gz: 2caa7e2cb715c7a3c1124210b1a2efa064425ef4b2075abd84b7092e28eae67c66fc1aabf93cd6c5493b86c5c735fe9965c9f0f347be4b57f5690f74690d79b4
7
+ data.tar.gz: 16f4abe1b2ca8099660cd22a541bac6a220f661db879bf9742e85645abfe0cbf36146872c6dfe33af30bc5c8b303144720abe5233d4a1748390a7ff587e8c005
@@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.1.0] - 2020-12-20
10
+
11
+ ### Added
12
+
13
+ - [@kddeisz] - Now that the comments are all fixed up, we can support `# prettier-ignore` comments.
14
+
15
+ ### Changed
16
+
17
+ - [@rindek], [@kddeisz] - Do not remove parentheses when receiver looks like a constant.
18
+ - [@rindek], [@kddeisz] - Do not remove parentheses when using the special `call` syntax with no arguments.
19
+ - [@ykpythemind] - Do not change regexp bounds if the body has certain content.
20
+ - [@karanmandal], [@kddeisz] - Correctly print for loops.
21
+ - [@rafbm], [@kddeisz] - If there are method chains with arguments only at the end, we should group the method chain and the method args.
22
+
9
23
  ## [1.0.1] - 2020-12-12
10
24
 
11
25
  ### Changed
@@ -957,7 +971,8 @@ would previously result in `array[]`, but now prints properly.
957
971
 
958
972
  - Initial release 🎉
959
973
 
960
- [unreleased]: https://github.com/prettier/plugin-ruby/compare/v1.0.1...HEAD
974
+ [unreleased]: https://github.com/prettier/plugin-ruby/compare/v1.1.0...HEAD
975
+ [1.1.0]: https://github.com/prettier/plugin-ruby/compare/v1.0.1...v1.1.0
961
976
  [1.0.1]: https://github.com/prettier/plugin-ruby/compare/v1.0.0...v1.0.1
962
977
  [1.0.0]: https://github.com/prettier/plugin-ruby/compare/v1.0.0-rc2...v1.0.0
963
978
  [1.0.0-rc2]: https://github.com/prettier/plugin-ruby/compare/v1.0.0-rc1...v1.0.0-rc2
@@ -1045,6 +1060,7 @@ would previously result in `array[]`, but now prints properly.
1045
1060
  [@jpickwell]: https://github.com/jpickwell
1046
1061
  [@jrdioko]: https://github.com/jrdioko
1047
1062
  [@jviney]: https://github.com/jviney
1063
+ [@karanmandal]: https://github.com/karanmandal
1048
1064
  [@kddeisz]: https://github.com/kddeisz
1049
1065
  [@kmcq]: https://github.com/kmcq
1050
1066
  [@krachtstefan]: https://github.com/krachtstefan
@@ -1059,6 +1075,8 @@ would previously result in `array[]`, but now prints properly.
1059
1075
  [@overload119]: https://github.com/Overload119
1060
1076
  [@petevk]: https://github.com/petevk
1061
1077
  [@pje]: https://github.com/pje
1078
+ [@rafbm]: https://github.com/rafbm
1079
+ [@rindek]: https://github.com/rindek
1062
1080
  [@rosskinsella]: https://github.com/RossKinsella
1063
1081
  [@rsullivan00]: https://github.com/Rsullivan00
1064
1082
  [@ryan-hunter-pc]: https://github.com/ryan-hunter-pc
@@ -1068,4 +1086,5 @@ would previously result in `array[]`, but now prints properly.
1068
1086
  [@tobyndockerill]: https://github.com/tobyndockerill
1069
1087
  [@uri]: https://github.com/uri
1070
1088
  [@xipgroc]: https://github.com/xipgroc
1089
+ [@ykpythemind]: https://github.com/ykpythemind
1071
1090
  [@yuki24]: https://github.com/yuki24
data/README.md CHANGED
@@ -227,6 +227,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
227
227
  <tr>
228
228
  <td align="center"><a href="https://github.com/mmcnl"><img src="https://avatars2.githubusercontent.com/u/1498727?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matt McNeil</b></sub></a><br /><a href="https://github.com/prettier/plugin-ruby/issues?q=author%3Ammcnl" title="Bug reports">🐛</a></td>
229
229
  <td align="center"><a href="https://github.com/johncsnyder"><img src="https://avatars2.githubusercontent.com/u/9882099?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Snyder</b></sub></a><br /><a href="https://github.com/prettier/plugin-ruby/issues?q=author%3Ajohncsnyder" title="Bug reports">🐛</a></td>
230
+ <td align="center"><a href="https://github.com/rindek"><img src="https://avatars1.githubusercontent.com/u/881209?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jacek Jakubik</b></sub></a><br /><a href="https://github.com/prettier/plugin-ruby/issues?q=author%3Arindek" title="Bug reports">🐛</a></td>
231
+ <td align="center"><a href="https://twitter.com/ykpythemind"><img src="https://avatars2.githubusercontent.com/u/22209702?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yukito Ito</b></sub></a><br /><a href="https://github.com/prettier/plugin-ruby/issues?q=author%3Aykpythemind" title="Bug reports">🐛</a> <a href="https://github.com/prettier/plugin-ruby/commits?author=ykpythemind" title="Code">💻</a></td>
232
+ <td align="center"><a href="https://studyfied.com/"><img src="https://avatars2.githubusercontent.com/u/45869605?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Karan Mandal</b></sub></a><br /><a href="https://github.com/prettier/plugin-ruby/issues?q=author%3Akaranmandal" title="Bug reports">🐛</a></td>
230
233
  </tr>
231
234
  </table>
232
235
 
@@ -5249,19 +5249,19 @@ var errors = {
5249
5249
  UndefinedParserError
5250
5250
  };
5251
5251
 
5252
- /*! *****************************************************************************
5253
- Copyright (c) Microsoft Corporation.
5254
-
5255
- Permission to use, copy, modify, and/or distribute this software for any
5256
- purpose with or without fee is hereby granted.
5257
-
5258
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
5259
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
5260
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
5261
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
5262
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
5263
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
5264
- PERFORMANCE OF THIS SOFTWARE.
5252
+ /*! *****************************************************************************
5253
+ Copyright (c) Microsoft Corporation.
5254
+
5255
+ Permission to use, copy, modify, and/or distribute this software for any
5256
+ purpose with or without fee is hereby granted.
5257
+
5258
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
5259
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
5260
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
5261
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
5262
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
5263
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
5264
+ PERFORMANCE OF THIS SOFTWARE.
5265
5265
  ***************************************************************************** */
5266
5266
 
5267
5267
  /* global Reflect, Promise */
@@ -14638,7 +14638,6 @@ function printAstToDoc(ast, options, alignmentSize = 0) {
14638
14638
  } // We let JSXElement print its comments itself because it adds () around
14639
14639
  // UnionTypeAnnotation has to align the child without the comments
14640
14640
 
14641
-
14642
14641
  let res;
14643
14642
 
14644
14643
  if (printer.willPrintOwnComments && printer.willPrintOwnComments(path, options)) {
@@ -14675,6 +14674,7 @@ function printPrettierIgnoredNode(node, options) {
14675
14674
  locStart,
14676
14675
  locEnd
14677
14676
  } = options;
14677
+
14678
14678
  const start = locStart(node);
14679
14679
  const end = locEnd(node);
14680
14680
 
@@ -24808,11 +24808,11 @@ var ini = createCommonjsModule(function (module, exports) {
24808
24808
  });
24809
24809
 
24810
24810
  var fs = __importStar(fs__default['default']);
24811
- /**
24812
- * define the possible values:
24813
- * section: [section]
24814
- * param: key=value
24815
- * comment: ;this is a comment
24811
+ /**
24812
+ * define the possible values:
24813
+ * section: [section]
24814
+ * param: key=value
24815
+ * comment: ;this is a comment
24816
24816
  */
24817
24817
 
24818
24818
 
@@ -24821,9 +24821,9 @@ var ini = createCommonjsModule(function (module, exports) {
24821
24821
  param: /^\s*([\w\.\-\_]+)\s*[=:]\s*(.*?)\s*([#;].*)?$/,
24822
24822
  comment: /^\s*[#;].*$/
24823
24823
  };
24824
- /**
24825
- * Parses an .ini file
24826
- * @param file The location of the .ini file
24824
+ /**
24825
+ * Parses an .ini file
24826
+ * @param file The location of the .ini file
24827
24827
  */
24828
24828
 
24829
24829
  function parse(file) {
@@ -29644,8 +29644,8 @@ var path_1 = createCommonjsModule(function (module, exports) {
29644
29644
  const LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2; // ./ or .\\
29645
29645
 
29646
29646
  const UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\())/g;
29647
- /**
29648
- * Designed to work only with simple paths: `dir\\file`.
29647
+ /**
29648
+ * Designed to work only with simple paths: `dir\\file`.
29649
29649
  */
29650
29650
 
29651
29651
  function unixify(filepath) {
@@ -34268,17 +34268,17 @@ var pattern = createCommonjsModule(function (module, exports) {
34268
34268
  exports.isStaticPattern = isStaticPattern;
34269
34269
 
34270
34270
  function isDynamicPattern(pattern, options = {}) {
34271
- /**
34272
- * A special case with an empty string is necessary for matching patterns that start with a forward slash.
34273
- * An empty string cannot be a dynamic pattern.
34274
- * For example, the pattern `/lib/*` will be spread into parts: '', 'lib', '*'.
34271
+ /**
34272
+ * A special case with an empty string is necessary for matching patterns that start with a forward slash.
34273
+ * An empty string cannot be a dynamic pattern.
34274
+ * For example, the pattern `/lib/*` will be spread into parts: '', 'lib', '*'.
34275
34275
  */
34276
34276
  if (pattern === '') {
34277
34277
  return false;
34278
34278
  }
34279
- /**
34280
- * When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check
34281
- * filepath directly (without read directory).
34279
+ /**
34280
+ * When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check
34281
+ * filepath directly (without read directory).
34282
34282
  */
34283
34283
 
34284
34284
 
@@ -34389,17 +34389,17 @@ var pattern = createCommonjsModule(function (module, exports) {
34389
34389
  } = picomatch$1.scan(pattern, Object.assign(Object.assign({}, options), {
34390
34390
  parts: true
34391
34391
  }));
34392
- /**
34393
- * The scan method returns an empty array in some cases.
34394
- * See micromatch/picomatch#58 for more details.
34392
+ /**
34393
+ * The scan method returns an empty array in some cases.
34394
+ * See micromatch/picomatch#58 for more details.
34395
34395
  */
34396
34396
 
34397
34397
  if (parts.length === 0) {
34398
34398
  parts = [pattern];
34399
34399
  }
34400
- /**
34401
- * The scan method does not return an empty part for the pattern with a forward slash.
34402
- * This is another part of micromatch/picomatch#58.
34400
+ /**
34401
+ * The scan method does not return an empty part for the pattern with a forward slash.
34402
+ * This is another part of micromatch/picomatch#58.
34403
34403
  */
34404
34404
 
34405
34405
 
@@ -34804,8 +34804,8 @@ var constants$5 = createCommonjsModule(function (module, exports) {
34804
34804
  const SUPPORTED_MINOR_VERSION = 10;
34805
34805
  const IS_MATCHED_BY_MAJOR = MAJOR_VERSION > SUPPORTED_MAJOR_VERSION;
34806
34806
  const IS_MATCHED_BY_MAJOR_AND_MINOR = MAJOR_VERSION === SUPPORTED_MAJOR_VERSION && MINOR_VERSION >= SUPPORTED_MINOR_VERSION;
34807
- /**
34808
- * IS `true` for Node.js 10.10 and greater.
34807
+ /**
34808
+ * IS `true` for Node.js 10.10 and greater.
34809
34809
  */
34810
34810
 
34811
34811
  exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_BY_MAJOR_AND_MINOR;
@@ -35894,9 +35894,9 @@ var matcher = createCommonjsModule(function (module, exports) {
35894
35894
  }
35895
35895
 
35896
35896
  _fillStorage() {
35897
- /**
35898
- * The original pattern may include `{,*,**,a/*}`, which will lead to problems with matching (unresolved level).
35899
- * So, before expand patterns with brace expansion into separated patterns.
35897
+ /**
35898
+ * The original pattern may include `{,*,**,a/*}`, which will lead to problems with matching (unresolved level).
35899
+ * So, before expand patterns with brace expansion into separated patterns.
35900
35900
  */
35901
35901
  const patterns = utils$3.pattern.expandPatternsWithBraceExpansion(this._patterns);
35902
35902
 
@@ -35958,12 +35958,12 @@ var partial = createCommonjsModule(function (module, exports) {
35958
35958
 
35959
35959
  for (const pattern of patterns) {
35960
35960
  const section = pattern.sections[0];
35961
- /**
35962
- * In this case, the pattern has a globstar and we must read all directories unconditionally,
35963
- * but only if the level has reached the end of the first group.
35964
- *
35965
- * fixtures/{a,b}/**
35966
- * ^ true/false ^ always true
35961
+ /**
35962
+ * In this case, the pattern has a globstar and we must read all directories unconditionally,
35963
+ * but only if the level has reached the end of the first group.
35964
+ *
35965
+ * fixtures/{a,b}/**
35966
+ * ^ true/false ^ always true
35967
35967
  */
35968
35968
 
35969
35969
  if (!pattern.complete && levels > section.length) {
@@ -36045,8 +36045,8 @@ var deep = createCommonjsModule(function (module, exports) {
36045
36045
  }
36046
36046
 
36047
36047
  _isSkippedByDeep(basePath, entryPath) {
36048
- /**
36049
- * Avoid unnecessary depth calculations when it doesn't matter.
36048
+ /**
36049
+ * Avoid unnecessary depth calculations when it doesn't matter.
36050
36050
  */
36051
36051
  if (this._settings.deep === Infinity) {
36052
36052
  return false;
@@ -36534,10 +36534,10 @@ async function FastGlob(source, options) {
36534
36534
  function stream(source, options) {
36535
36535
  assertPatternsInput(source);
36536
36536
  const works = getWorks(source, stream$5.default, options);
36537
- /**
36538
- * The stream returned by the provider cannot work with an asynchronous iterator.
36539
- * To support asynchronous iterators, regardless of the number of tasks, we always multiplex streams.
36540
- * This affects performance (+25%). I don't see best solution right now.
36537
+ /**
36538
+ * The stream returned by the provider cannot work with an asynchronous iterator.
36539
+ * To support asynchronous iterators, regardless of the number of tasks, we always multiplex streams.
36540
+ * This affects performance (+25%). I don't see best solution right now.
36541
36541
  */
36542
36542
 
36543
36543
  return utils$3.stream.merge(works);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prettier/plugin-ruby",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "prettier plugin for the Ruby programming language",
5
5
  "main": "src/ruby.js",
6
6
  "scripts": {
@@ -50,6 +50,8 @@
50
50
  }
51
51
  },
52
52
  "jest": {
53
+ "globalSetup": "./test/js/globalSetup.js",
54
+ "globalTeardown": "./test/js/globalTeardown.js",
53
55
  "setupFilesAfterEnv": [
54
56
  "./test/js/setupTests.js"
55
57
  ],
@@ -39,6 +39,7 @@ function printCall(path, opts, print) {
39
39
  // right side of the expression, as we want to have a nice multi-line layout.
40
40
  if (chained.includes(parentNode.type)) {
41
41
  parentNode.chain = (node.chain || 0) + 1;
42
+ parentNode.callChain = (node.callChain || 0) + 1;
42
43
  parentNode.breakDoc = (node.breakDoc || [receiverDoc]).concat(rightSideDoc);
43
44
  }
44
45
 
@@ -62,13 +63,31 @@ function printCall(path, opts, print) {
62
63
 
63
64
  function printMethodAddArg(path, opts, print) {
64
65
  const node = path.getValue();
65
- const argNode = node.body[1];
66
66
 
67
+ const [methodNode, argNode] = node.body;
67
68
  const [methodDoc, argsDoc] = path.map(print, "body");
68
69
 
69
70
  // You can end up here if you have a method with a ? ending, presumably
70
- // because the parser knows that it cannot be a local variable.
71
+ // because the parser knows that it cannot be a local variable. You can also
72
+ // end up here if you are explicitly using an empty set of parentheses.
71
73
  if (argsDoc.length === 0) {
74
+ // If you're using an explicit set of parentheses on something that looks
75
+ // like a constant, then we need to match that in order to maintain valid
76
+ // Ruby. For example, you could do something like Foo(), on which we would
77
+ // need to keep the parentheses to make it look like a method call.
78
+ if (methodNode.type === "fcall" && methodNode.body[0].type === "@const") {
79
+ return concat([methodDoc, "()"]);
80
+ }
81
+
82
+ // If you're using an explicit set parentheses with the special call syntax,
83
+ // then we need to explicitly print out an extra set of parentheses. For
84
+ // example, if you call something like Foo.new.() (implicitly calling the
85
+ // #call method on a new instance of the Foo class), then we have to print
86
+ // out those parentheses, otherwise we'll end up with Foo.new.
87
+ if (methodNode.type === "call" && methodNode.body[2] === "call") {
88
+ return concat([methodDoc, "()"]);
89
+ }
90
+
72
91
  return methodDoc;
73
92
  }
74
93
 
@@ -91,6 +110,21 @@ function printMethodAddArg(path, opts, print) {
91
110
  // If we're at the top of a chain, then we're going to print out a nice
92
111
  // multi-line layout if this doesn't break into multiple lines.
93
112
  if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
113
+ // This is pretty specialized behavior. Basically if we're at the top of a
114
+ // chain but we've only had method calls without arguments and now we have
115
+ // arguments, then we're effectively trying to call a method with arguments
116
+ // that is nested under a bunch of stuff. So we group together to first part
117
+ // to make it so just the arguments break. This looks like, for example:
118
+ //
119
+ // config.action_dispatch.rescue_responses.merge!(
120
+ // 'ActiveRecord::ConnectionTimeoutError' => :service_unavailable,
121
+ // 'ActiveRecord::QueryCanceled' => :service_unavailable
122
+ // )
123
+ //
124
+ if (node.callChain === node.chain) {
125
+ return concat([group(indent(concat(node.breakDoc))), group(argsDoc)]);
126
+ }
127
+
94
128
  return ifBreak(
95
129
  group(indent(concat(node.breakDoc.concat(argsDoc)))),
96
130
  concat([methodDoc, argsDoc])
@@ -12,85 +12,85 @@ const {
12
12
  const { containsAssignment } = require("../utils");
13
13
  const inlineEnsureParens = require("../utils/inlineEnsureParens");
14
14
 
15
- const printLoop = (keyword, modifier) => (path, { rubyModifier }, print) => {
16
- const [_predicate, stmts] = path.getValue().body;
15
+ function printLoop(keyword, modifier) {
16
+ return function printLoopWithOptions(path, { rubyModifier }, print) {
17
+ const [_predicate, stmts] = path.getValue().body;
17
18
 
18
- // If the only statement inside this while loop is a void statement, then we
19
- // can shorten to just displaying the predicate and then a semicolon.
20
- if (
21
- stmts.body.length === 1 &&
22
- stmts.body[0].type === "void_stmt" &&
23
- !stmts.body[0].comments
24
- ) {
25
- return group(
26
- concat([
27
- keyword,
28
- " ",
29
- path.call(print, "body", 0),
30
- ifBreak(softline, "; "),
31
- "end"
19
+ // If the only statement inside this while loop is a void statement, then we
20
+ // can shorten to just displaying the predicate and then a semicolon.
21
+ if (
22
+ stmts.body.length === 1 &&
23
+ stmts.body[0].type === "void_stmt" &&
24
+ !stmts.body[0].comments
25
+ ) {
26
+ return group(
27
+ concat([
28
+ keyword,
29
+ " ",
30
+ path.call(print, "body", 0),
31
+ ifBreak(softline, "; "),
32
+ "end"
33
+ ])
34
+ );
35
+ }
36
+
37
+ const inlineLoop = concat(
38
+ inlineEnsureParens(path, [
39
+ path.call(print, "body", 1),
40
+ ` ${keyword} `,
41
+ path.call(print, "body", 0)
32
42
  ])
33
43
  );
34
- }
35
44
 
36
- const inlineLoop = concat(
37
- inlineEnsureParens(path, [
38
- path.call(print, "body", 1),
39
- ` ${keyword} `,
40
- path.call(print, "body", 0)
41
- ])
42
- );
45
+ // If we're in the modifier form and we're modifying a `begin`, then this is
46
+ // a special case where we need to explicitly use the modifier form because
47
+ // otherwise the semantic meaning changes. This looks like:
48
+ //
49
+ // begin
50
+ // foo
51
+ // end while bar
52
+ //
53
+ // The above is effectively a `do...while` loop (which we don't have in
54
+ // ruby).
55
+ if (modifier && path.getValue().body[1].type === "begin") {
56
+ return inlineLoop;
57
+ }
43
58
 
44
- // If we're in the modifier form and we're modifying a `begin`, then this is a
45
- // special case where we need to explicitly use the modifier form because
46
- // otherwise the semantic meaning changes. This looks like:
47
- //
48
- // begin
49
- // foo
50
- // end while bar
51
- //
52
- // The above is effectively a `do...while` loop (which we don't have in ruby).
53
- if (modifier && path.getValue().body[1].type === "begin") {
54
- return inlineLoop;
55
- }
59
+ const blockLoop = concat([
60
+ concat([
61
+ `${keyword} `,
62
+ align(keyword.length + 1, path.call(print, "body", 0))
63
+ ]),
64
+ indent(concat([softline, path.call(print, "body", 1)])),
65
+ concat([softline, "end"])
66
+ ]);
56
67
 
57
- const blockLoop = concat([
58
- concat([
59
- `${keyword} `,
60
- align(keyword.length + 1, path.call(print, "body", 0))
61
- ]),
62
- indent(concat([softline, path.call(print, "body", 1)])),
63
- concat([softline, "end"])
64
- ]);
68
+ // If we're disallowing inline loops or if the predicate of the loop
69
+ // contains an assignment (in which case we can't know for certain that that
70
+ // assignment doesn't impact the statements inside the loop) then we can't
71
+ // use the modifier form and we must use the block form.
72
+ if (!rubyModifier || containsAssignment(path.getValue().body[0])) {
73
+ return concat([breakParent, blockLoop]);
74
+ }
65
75
 
66
- // If we're disallowing inline loops or if the predicate of the loop contains
67
- // an assignment (in which case we can't know for certain that that
68
- // assignment doesn't impact the statements inside the loop) then we can't
69
- // use the modifier form and we must use the block form.
70
- if (!rubyModifier || containsAssignment(path.getValue().body[0])) {
71
- return concat([breakParent, blockLoop]);
72
- }
76
+ return group(ifBreak(blockLoop, inlineLoop));
77
+ };
78
+ }
73
79
 
74
- return group(ifBreak(blockLoop, inlineLoop));
75
- };
80
+ function printFor(path, opts, print) {
81
+ const [variable, range, stmts] = path.map(print, "body");
76
82
 
77
- // Technically this is incorrect. A `for` loop actually introduces and modifies
78
- // a local variable that then remains in the outer scope. Additionally, if the
79
- // `each` method was somehow missing from the enumerable (it's possible...),
80
- // then this transformation would fail. However - I've never actually seen a
81
- // `for` loop used in production. If someone actually calls me on it, I'll fix
82
- // this, but for now I'm leaving it.
83
- const printFor = (path, opts, print) =>
84
- group(
83
+ return group(
85
84
  concat([
86
- path.call(print, "body", 1),
87
- ".each do |",
88
- path.call(print, "body", 0),
89
- "|",
90
- indent(concat([hardline, path.call(print, "body", 2)])),
85
+ "for ",
86
+ variable,
87
+ " in ",
88
+ range,
89
+ indent(concat([hardline, stmts])),
91
90
  concat([hardline, "end"])
92
91
  ])
93
92
  );
93
+ }
94
94
 
95
95
  module.exports = {
96
96
  while: printLoop("while", false),
@@ -1,28 +1,25 @@
1
1
  const { concat } = require("../prettier");
2
2
  const { hasAncestor } = require("../utils");
3
3
 
4
- function isStringContent(node) {
5
- return node.type === "@tstring_content";
4
+ function hasContent(node, pattern) {
5
+ return node.body.some(
6
+ (child) => child.type === "@tstring_content" && pattern.test(child.body)
7
+ );
6
8
  }
7
9
 
8
- function shouldUseBraces(path) {
10
+ // If the first part of this regex is plain string content, we have a space
11
+ // or an =, and we're contained within a command or command_call node, then we
12
+ // want to use braces because otherwise we could end up with an ambiguous
13
+ // operator, e.g. foo / bar/ or foo /=bar/
14
+ function forwardSlashIsAmbiguous(path) {
9
15
  const node = path.getValue();
10
- const first = node.body[0];
11
-
12
- // If the first part of this regex is plain string content and we have a
13
- // space or an =, then we want to use braces because otherwise we could end up
14
- // with an ambiguous operator, e.g. foo / bar/ or foo /=bar/
15
- if (
16
- first &&
17
- isStringContent(first) &&
18
- [" ", "="].includes(first.body[0]) &&
19
- hasAncestor(path, ["command", "command_call"])
20
- ) {
21
- return true;
22
- }
16
+ const firstChildNode = node.body[0];
23
17
 
24
- return node.body.some(
25
- (child) => isStringContent(child) && child.body.includes("/")
18
+ return (
19
+ firstChildNode &&
20
+ firstChildNode.type === "@tstring_content" &&
21
+ [" ", "="].includes(firstChildNode.body[0]) &&
22
+ hasAncestor(path, ["command", "command_call"])
26
23
  );
27
24
  }
28
25
 
@@ -35,13 +32,23 @@ function shouldUseBraces(path) {
35
32
  // itself. In that case we switch over to using %r with braces.
36
33
  function printRegexpLiteral(path, opts, print) {
37
34
  const node = path.getValue();
38
- const useBraces = shouldUseBraces(path);
35
+ const docs = path.map(print, "body");
36
+
37
+ // We should use braces if using a forward slash would be ambiguous in the
38
+ // current context or if there's a forward slash in the content of the regexp.
39
+ const useBraces = forwardSlashIsAmbiguous(path) || hasContent(node, /\//);
39
40
 
40
- const parts = [useBraces ? "%r{" : "/"]
41
- .concat(path.map(print, "body"))
42
- .concat([useBraces ? "}" : "/", node.ending.slice(1)]);
41
+ // If we should be using braces but we have braces in the body of the regexp,
42
+ // then we're just going to resort to using whatever the original content was.
43
+ if (useBraces && hasContent(node, /[{}]/)) {
44
+ return concat([node.beging].concat(docs).concat(node.ending));
45
+ }
43
46
 
44
- return concat(parts);
47
+ return concat(
48
+ [useBraces ? "%r{" : "/"]
49
+ .concat(docs)
50
+ .concat(useBraces ? "}" : "/", node.ending.slice(1))
51
+ );
45
52
  }
46
53
 
47
54
  module.exports = {
@@ -1719,7 +1719,8 @@ class Prettier::Parser < Ripper
1719
1719
  # expression literal, like /foo/. It can be followed by any number of
1720
1720
  # regexp_add events, which we'll append onto an array body.
1721
1721
  def on_regexp_new
1722
- find_scanner_event(:@regexp_beg).merge!(type: :regexp, body: [])
1722
+ beging = find_scanner_event(:@regexp_beg)
1723
+ beging.merge!(type: :regexp, body: [], beging: beging[:body])
1723
1724
  end
1724
1725
 
1725
1726
  # regexp_add is a parser event that represents a piece of a regular
@@ -20,6 +20,18 @@ function printNode(path, opts, print) {
20
20
  throw new Error(`Unsupported node encountered: ${type}\n${ast}`);
21
21
  }
22
22
 
23
+ // This is an escape-hatch to ignore nodes in the tree. If you have a comment
24
+ // that includes this pattern, then the entire node will be ignored and just the
25
+ // original source will be printed out.
26
+ function hasPrettierIgnore(path) {
27
+ const node = path.getValue();
28
+
29
+ return (
30
+ node.comments &&
31
+ node.comments.some((comment) => comment.value.includes("prettier-ignore"))
32
+ );
33
+ }
34
+
23
35
  const noComments = [
24
36
  "args",
25
37
  "args_add_block",
@@ -83,6 +95,7 @@ function isBlockComment(comment) {
83
95
  module.exports = {
84
96
  embed,
85
97
  print: printNode,
98
+ hasPrettierIgnore,
86
99
  canAttachComment,
87
100
  getCommentChildNodes,
88
101
  printComment,
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: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Deisz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-12 00:00:00.000000000 Z
11
+ date: 2020-12-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: