prettier 1.0.0.pre.rc2 → 1.2.1

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: 305f0248dc0f0b4ab56d698f04858e3d25df0f91888a203f75740ae5a06a7e0d
4
- data.tar.gz: 192eaf1d3cd95a9dc3693c0346f636f53ae2baede4cd3de5d827bd671571daf3
3
+ metadata.gz: 3abef3acea4e49130ba81afdb9bc00e73277c69e0254a1087b2c5e47feb5b104
4
+ data.tar.gz: e851f061fc14352b7797ac0e2aca10c43f052b8bd19aa817473cfb6b75bde44c
5
5
  SHA512:
6
- metadata.gz: 33a09aa76044b30dde5aa1555bfabc8f178607335ca0af9e4709d0f9fbfdc437c986097da85cc2d0c411326cb25d0672587a0253016bc89e71ca1245a5cfd652
7
- data.tar.gz: b293f495c164808c4372dc79cfa801fd1603fe4907eafb374b61ba171cffbf1aaa09b6e0b1a427bc949099091db790a79d74d56c50f72c3ba006acc718b0065c
6
+ metadata.gz: 6fd8aba1071ff34709e7f3ad3ddd256cfbdc890ffb02fdef3d3567331a53d9b1974d02fd943ce03cab565822d750288bbe5582bc3c4a2d26bf0f170d2c3d15c6
7
+ data.tar.gz: 8e66f396c113f162fb6c8c747a60d45dd38a554c13cab3ac1ae12456ff15fc49d2945ce69c1db53d89f1f82a69d0b30017ebfdcd99fbb2cb2fbbc29c4dbf398b
@@ -6,6 +6,53 @@ 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.2.1] - 2020-12-27
10
+
11
+ ### Changed
12
+
13
+ - [@kddeisz] - Handle single-line method definitions with parameters.
14
+ - [@kddeisz] - Handle hash and array patterns nested within find patterns.
15
+ - [@kddeisz] - Handle rightward assignment.
16
+ - [@kddeisz] - Handle find patterns with named boundaries.
17
+ - [@kddeisz] - Handle rightward assignment in conditionals.
18
+
19
+ ## [1.2.0] - 2020-12-26
20
+
21
+ ### Added
22
+
23
+ - [@kddeisz] - Support for the `fndptn` node for Ruby 3.0 pattern matching.
24
+ - [@kddeisz] - Support for Ruby 3.0+ single-line method definitions.
25
+
26
+ ## [1.1.0] - 2020-12-20
27
+
28
+ ### Added
29
+
30
+ - [@kddeisz] - Now that the comments are all fixed up, we can support `# prettier-ignore` comments.
31
+
32
+ ### Changed
33
+
34
+ - [@rindek], [@kddeisz] - Do not remove parentheses when receiver looks like a constant.
35
+ - [@rindek], [@kddeisz] - Do not remove parentheses when using the special `call` syntax with no arguments.
36
+ - [@ykpythemind] - Do not change regexp bounds if the body has certain content.
37
+ - [@karanmandal], [@kddeisz] - Correctly print for loops.
38
+ - [@rafbm], [@kddeisz] - If there are method chains with arguments only at the end, we should group the method chain and the method args.
39
+
40
+ ## [1.0.1] - 2020-12-12
41
+
42
+ ### Changed
43
+
44
+ - [@steobrien], [@kddeisz] - Ensure leading comments in empty array and hash literals do not duplicate.
45
+
46
+ ## [1.0.0] - 2020-12-11
47
+
48
+ ### Changed
49
+
50
+ - [@kddeisz] - Do not unescape double quotes in a single quote string.
51
+ - [@kddeisz] - Only force braces on regexp for spaces and equals if it's inside a command or command_call.
52
+ - [@kddeisz] - Leave Sorbet type annotations in place.
53
+ - [@kddeisz] - Don't group hash contents, just allow them to break with their parent node.
54
+ - [@kddeisz] - Honor the UTF-8 lang passed in through ENV vars.
55
+
9
56
  ## [1.0.0-rc2] - 2020-12-10
10
57
 
11
58
  ### Changed
@@ -252,7 +299,8 @@ will now be printed as:
252
299
  ```ruby
253
300
  Config::Download.new(
254
301
  'prettier',
255
- filename: 'prettier.yml', url: 'https://raw.githubusercontent.com/...'
302
+ filename: 'prettier.yml',
303
+ url: 'https://raw.githubusercontent.com/...'
256
304
  ).perform
257
305
  ```
258
306
 
@@ -940,7 +988,10 @@ would previously result in `array[]`, but now prints properly.
940
988
 
941
989
  - Initial release 🎉
942
990
 
943
- [unreleased]: https://github.com/prettier/plugin-ruby/compare/v1.0.0-rc2...HEAD
991
+ [unreleased]: https://github.com/prettier/plugin-ruby/compare/v1.1.0...HEAD
992
+ [1.1.0]: https://github.com/prettier/plugin-ruby/compare/v1.0.1...v1.1.0
993
+ [1.0.1]: https://github.com/prettier/plugin-ruby/compare/v1.0.0...v1.0.1
994
+ [1.0.0]: https://github.com/prettier/plugin-ruby/compare/v1.0.0-rc2...v1.0.0
944
995
  [1.0.0-rc2]: https://github.com/prettier/plugin-ruby/compare/v1.0.0-rc1...v1.0.0-rc2
945
996
  [1.0.0-rc1]: https://github.com/prettier/plugin-ruby/compare/v0.22.0...v1.0.0-rc1
946
997
  [0.22.0]: https://github.com/prettier/plugin-ruby/compare/v0.21.0...v0.22.0
@@ -1026,6 +1077,7 @@ would previously result in `array[]`, but now prints properly.
1026
1077
  [@jpickwell]: https://github.com/jpickwell
1027
1078
  [@jrdioko]: https://github.com/jrdioko
1028
1079
  [@jviney]: https://github.com/jviney
1080
+ [@karanmandal]: https://github.com/karanmandal
1029
1081
  [@kddeisz]: https://github.com/kddeisz
1030
1082
  [@kmcq]: https://github.com/kmcq
1031
1083
  [@krachtstefan]: https://github.com/krachtstefan
@@ -1040,6 +1092,8 @@ would previously result in `array[]`, but now prints properly.
1040
1092
  [@overload119]: https://github.com/Overload119
1041
1093
  [@petevk]: https://github.com/petevk
1042
1094
  [@pje]: https://github.com/pje
1095
+ [@rafbm]: https://github.com/rafbm
1096
+ [@rindek]: https://github.com/rindek
1043
1097
  [@rosskinsella]: https://github.com/RossKinsella
1044
1098
  [@rsullivan00]: https://github.com/Rsullivan00
1045
1099
  [@ryan-hunter-pc]: https://github.com/ryan-hunter-pc
@@ -1049,4 +1103,5 @@ would previously result in `array[]`, but now prints properly.
1049
1103
  [@tobyndockerill]: https://github.com/tobyndockerill
1050
1104
  [@uri]: https://github.com/uri
1051
1105
  [@xipgroc]: https://github.com/xipgroc
1106
+ [@ykpythemind]: https://github.com/ykpythemind
1052
1107
  [@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,11 +1,11 @@
1
1
  {
2
2
  "name": "@prettier/plugin-ruby",
3
- "version": "1.0.0-rc2",
3
+ "version": "1.2.1",
4
4
  "description": "prettier plugin for the Ruby programming language",
5
5
  "main": "src/ruby.js",
6
6
  "scripts": {
7
+ "check-format": "prettier --check '**/*'",
7
8
  "lint": "eslint --cache .",
8
- "print": "prettier --plugin=.",
9
9
  "test": "jest"
10
10
  },
11
11
  "repository": {
@@ -25,9 +25,9 @@
25
25
  "all-contributors-cli": "^6.14.1",
26
26
  "eslint": "^7.8.1",
27
27
  "eslint-config-prettier": "^7.0.0",
28
- "husky": "^5.0.4",
28
+ "husky": "^4.3.5",
29
29
  "jest": "^26.0.0",
30
- "pretty-quick": "^3.0.0"
30
+ "pretty-quick": "^3.1.0"
31
31
  },
32
32
  "eslintConfig": {
33
33
  "extends": [
@@ -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
  ],
@@ -61,6 +63,9 @@
61
63
  }
62
64
  },
63
65
  "prettier": {
64
- "trailingComma": "none"
66
+ "trailingComma": "none",
67
+ "plugins": [
68
+ "."
69
+ ]
65
70
  }
66
71
  }
@@ -1,7 +1,6 @@
1
1
  const {
2
2
  concat,
3
3
  group,
4
- hardline,
5
4
  ifBreak,
6
5
  indent,
7
6
  join,
@@ -9,7 +8,7 @@ const {
9
8
  softline
10
9
  } = require("../prettier");
11
10
 
12
- const { getTrailingComma } = require("../utils");
11
+ const { getTrailingComma, printEmptyCollection } = require("../utils");
13
12
 
14
13
  // Checks that every argument within this args node is a string_literal node
15
14
  // that has no spaces or interpolations. This means we're dealing with an array
@@ -93,24 +92,6 @@ function printSpecialArray(start) {
93
92
  };
94
93
  }
95
94
 
96
- function printEmptyArrayWithComments(path, opts) {
97
- const arrayNode = path.getValue();
98
-
99
- const printComment = (commentPath, index) => {
100
- arrayNode.comments[index].printed = true;
101
- return opts.printer.printComment(commentPath);
102
- };
103
-
104
- return concat([
105
- "[",
106
- indent(
107
- concat([hardline, join(hardline, path.map(printComment, "comments"))])
108
- ),
109
- line,
110
- "]"
111
- ]);
112
- }
113
-
114
95
  // An array node is any literal array in Ruby. This includes all of the special
115
96
  // array literals as well as regular arrays. If it is a special array literal
116
97
  // then it will have one child that represents the special array, otherwise it
@@ -122,7 +103,7 @@ function printArray(path, opts, print) {
122
103
  // If there is no inner arguments node, then we're dealing with an empty
123
104
  // array, so we can go ahead and return.
124
105
  if (args === null) {
125
- return array.comments ? printEmptyArrayWithComments(path, opts) : "[]";
106
+ return printEmptyCollection(path, opts, "[", "]");
126
107
  }
127
108
 
128
109
  // If we have an array that contains only simple string literals with no
@@ -31,9 +31,13 @@ function printOpAssign(path, opts, print) {
31
31
  );
32
32
  }
33
33
 
34
+ function printVarField(path, opts, print) {
35
+ return path.getValue().body ? path.call(print, "body", 0) : "";
36
+ }
37
+
34
38
  module.exports = {
35
39
  assign: printAssign,
36
40
  opassign: printOpAssign,
37
- var_field: first,
41
+ var_field: printVarField,
38
42
  var_ref: first
39
43
  };
@@ -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])
@@ -100,15 +134,44 @@ function printMethodAddArg(path, opts, print) {
100
134
  return concat([methodDoc, argsDoc]);
101
135
  }
102
136
 
103
- function printMethodAddBlock(path, { rubyToProc }, print) {
137
+ // Sorbet type annotations look like the following:
138
+ //
139
+ // {method_add_block
140
+ // [{method_add_arg
141
+ // [{fcall
142
+ // [{@ident "sig"}]},
143
+ // {args []}]},
144
+ // {brace_block [nil, {stmts}]}}]}
145
+ //
146
+ function isSorbetTypeAnnotation(node) {
147
+ const [callNode, blockNode] = node.body;
148
+
149
+ return (
150
+ callNode.type === "method_add_arg" &&
151
+ callNode.body[0].type === "fcall" &&
152
+ callNode.body[0].body[0].body === "sig" &&
153
+ callNode.body[1].type === "args" &&
154
+ callNode.body[1].body.length === 0 &&
155
+ blockNode.type === "brace_block"
156
+ );
157
+ }
158
+
159
+ function printMethodAddBlock(path, opts, print) {
104
160
  const node = path.getValue();
105
161
 
106
162
  const [callNode, blockNode] = node.body;
107
163
  const [callDoc, blockDoc] = path.map(print, "body");
108
164
 
165
+ // Very special handling here for sorbet type annotations. They look like Ruby
166
+ // code, but they're not actually Ruby code, so we're not going to mess with
167
+ // them at all.
168
+ if (isSorbetTypeAnnotation(node)) {
169
+ return opts.originalText.slice(opts.locStart(node), opts.locEnd(node));
170
+ }
171
+
109
172
  // Don't bother trying to do any kind of fancy toProc transform if the option
110
173
  // is disabled.
111
- if (rubyToProc) {
174
+ if (opts.rubyToProc) {
112
175
  const proc = toProc(path, blockNode);
113
176
 
114
177
  if (proc && callNode.type === "call") {