prettier 1.2.2 → 1.4.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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +64 -1
  3. data/CONTRIBUTING.md +2 -2
  4. data/README.md +22 -94
  5. data/node_modules/prettier/index.js +54 -54
  6. data/package.json +2 -3
  7. data/rubocop.yml +26 -0
  8. data/src/haml/embed.js +87 -0
  9. data/src/haml/nodes/comment.js +27 -0
  10. data/src/haml/nodes/doctype.js +34 -0
  11. data/src/haml/nodes/filter.js +16 -0
  12. data/src/haml/nodes/hamlComment.js +21 -0
  13. data/src/haml/nodes/plain.js +6 -0
  14. data/src/haml/nodes/root.js +8 -0
  15. data/src/haml/nodes/script.js +33 -0
  16. data/src/haml/nodes/silentScript.js +59 -0
  17. data/src/haml/nodes/tag.js +193 -0
  18. data/src/haml/parser.js +22 -0
  19. data/src/haml/parser.rb +138 -0
  20. data/src/haml/printer.js +28 -0
  21. data/src/parser/getLang.js +32 -0
  22. data/src/parser/getNetcat.js +50 -0
  23. data/src/parser/netcat.js +15 -0
  24. data/src/parser/parseSync.js +33 -0
  25. data/src/parser/requestParse.js +74 -0
  26. data/src/parser/server.rb +61 -0
  27. data/src/{ruby.js → plugin.js} +25 -4
  28. data/src/prettier.js +1 -0
  29. data/src/rbs/parser.js +39 -0
  30. data/src/rbs/parser.rb +88 -0
  31. data/src/rbs/printer.js +605 -0
  32. data/src/{embed.js → ruby/embed.js} +6 -2
  33. data/src/{nodes.js → ruby/nodes.js} +0 -0
  34. data/src/{nodes → ruby/nodes}/alias.js +1 -1
  35. data/src/{nodes → ruby/nodes}/aref.js +8 -1
  36. data/src/{nodes → ruby/nodes}/args.js +2 -2
  37. data/src/{nodes → ruby/nodes}/arrays.js +2 -3
  38. data/src/{nodes → ruby/nodes}/assign.js +7 -3
  39. data/src/ruby/nodes/blocks.js +90 -0
  40. data/src/{nodes → ruby/nodes}/calls.js +20 -47
  41. data/src/{nodes → ruby/nodes}/case.js +1 -1
  42. data/src/{nodes → ruby/nodes}/class.js +1 -1
  43. data/src/ruby/nodes/commands.js +131 -0
  44. data/src/{nodes → ruby/nodes}/conditionals.js +3 -3
  45. data/src/{nodes → ruby/nodes}/constants.js +2 -2
  46. data/src/{nodes → ruby/nodes}/flow.js +2 -2
  47. data/src/{nodes → ruby/nodes}/hashes.js +32 -10
  48. data/src/{nodes → ruby/nodes}/heredocs.js +2 -2
  49. data/src/ruby/nodes/hooks.js +34 -0
  50. data/src/{nodes → ruby/nodes}/ints.js +0 -0
  51. data/src/{nodes → ruby/nodes}/lambdas.js +2 -2
  52. data/src/{nodes → ruby/nodes}/loops.js +10 -7
  53. data/src/{nodes → ruby/nodes}/massign.js +8 -1
  54. data/src/{nodes → ruby/nodes}/methods.js +10 -9
  55. data/src/{nodes → ruby/nodes}/operators.js +2 -2
  56. data/src/{nodes → ruby/nodes}/params.js +31 -16
  57. data/src/{nodes → ruby/nodes}/patterns.js +17 -6
  58. data/src/{nodes → ruby/nodes}/regexp.js +2 -2
  59. data/src/{nodes → ruby/nodes}/rescue.js +34 -27
  60. data/src/{nodes → ruby/nodes}/return.js +21 -10
  61. data/src/{nodes → ruby/nodes}/statements.js +9 -9
  62. data/src/{nodes → ruby/nodes}/strings.js +28 -36
  63. data/src/{nodes → ruby/nodes}/super.js +2 -2
  64. data/src/{nodes → ruby/nodes}/undef.js +1 -1
  65. data/src/ruby/parser.js +39 -0
  66. data/src/{parser.rb → ruby/parser.rb} +498 -529
  67. data/src/{printer.js → ruby/printer.js} +1 -3
  68. data/src/{toProc.js → ruby/toProc.js} +4 -8
  69. data/src/utils.js +10 -93
  70. data/src/utils/containsAssignment.js +11 -0
  71. data/src/utils/getTrailingComma.js +5 -0
  72. data/src/utils/hasAncestor.js +17 -0
  73. data/src/utils/literal.js +7 -0
  74. data/src/utils/makeCall.js +14 -0
  75. data/src/utils/noIndent.js +11 -0
  76. data/src/utils/skipAssignIndent.js +10 -0
  77. metadata +71 -41
  78. data/src/nodes/blocks.js +0 -85
  79. data/src/nodes/commands.js +0 -91
  80. data/src/nodes/hooks.js +0 -44
  81. data/src/parser.js +0 -86
@@ -6,9 +6,9 @@ const {
6
6
  mapDoc,
7
7
  markAsRoot,
8
8
  stripTrailingHardline
9
- } = require("./prettier");
9
+ } = require("../prettier");
10
10
 
11
- const { literalLineNoBreak } = require("./utils");
11
+ const { literalLineNoBreak } = require("../utils");
12
12
 
13
13
  const parsers = {
14
14
  css: "css",
@@ -20,6 +20,10 @@ const parsers = {
20
20
  scss: "scss"
21
21
  };
22
22
 
23
+ // This function is in here because it handles embedded parser values. I don't
24
+ // have a test that exercises it because I'm not sure for which parser it is
25
+ // necessary, but since it's in prettier core I'm keeping it here.
26
+ /* istanbul ignore next */
23
27
  const replaceNewlines = (doc) =>
24
28
  mapDoc(doc, (currentDoc) =>
25
29
  typeof currentDoc === "string" && currentDoc.includes("\n")
File without changes
@@ -5,7 +5,7 @@ const {
5
5
  group,
6
6
  hardline,
7
7
  line
8
- } = require("../prettier");
8
+ } = require("../../prettier");
9
9
 
10
10
  // In general, return the printed doc of the argument at the provided index.
11
11
  // Special handling is given for symbol literals that are not bare words, as we
@@ -1,4 +1,11 @@
1
- const { concat, group, indent, join, line, softline } = require("../prettier");
1
+ const {
2
+ concat,
3
+ group,
4
+ indent,
5
+ join,
6
+ line,
7
+ softline
8
+ } = require("../../prettier");
2
9
 
3
10
  // `aref` nodes are when you're pulling a value out of a collection at a
4
11
  // specific index. Put another way, it's any time you're calling the method
@@ -6,10 +6,10 @@ const {
6
6
  join,
7
7
  line,
8
8
  softline
9
- } = require("../prettier");
9
+ } = require("../../prettier");
10
+ const { getTrailingComma } = require("../../utils");
10
11
 
11
12
  const toProc = require("../toProc");
12
- const { getTrailingComma } = require("../utils");
13
13
 
14
14
  function printArgParen(path, opts, print) {
15
15
  const argsNode = path.getValue().body[0];
@@ -6,9 +6,8 @@ const {
6
6
  join,
7
7
  line,
8
8
  softline
9
- } = require("../prettier");
10
-
11
- const { getTrailingComma, printEmptyCollection } = require("../utils");
9
+ } = require("../../prettier");
10
+ const { getTrailingComma, printEmptyCollection } = require("../../utils");
12
11
 
13
12
  // Checks that every argument within this args node is a string_literal node
14
13
  // that has no spaces or interpolations. This means we're dealing with an array
@@ -1,5 +1,5 @@
1
- const { concat, group, indent, join, line } = require("../prettier");
2
- const { first, skipAssignIndent } = require("../utils");
1
+ const { concat, group, indent, join, line } = require("../../prettier");
2
+ const { skipAssignIndent } = require("../../utils");
3
3
 
4
4
  function printAssign(path, opts, print) {
5
5
  const [_targetNode, valueNode] = path.getValue().body;
@@ -35,9 +35,13 @@ function printVarField(path, opts, print) {
35
35
  return path.getValue().body ? path.call(print, "body", 0) : "";
36
36
  }
37
37
 
38
+ function printVarRef(path, opts, print) {
39
+ return path.call(print, "body", 0);
40
+ }
41
+
38
42
  module.exports = {
39
43
  assign: printAssign,
40
44
  opassign: printOpAssign,
41
45
  var_field: printVarField,
42
- var_ref: first
46
+ var_ref: printVarRef
43
47
  };
@@ -0,0 +1,90 @@
1
+ const {
2
+ breakParent,
3
+ concat,
4
+ group,
5
+ ifBreak,
6
+ indent,
7
+ join,
8
+ removeLines,
9
+ softline
10
+ } = require("../../prettier");
11
+ const { hasAncestor } = require("../../utils");
12
+
13
+ function printBlockVar(path, opts, print) {
14
+ const parts = ["|", removeLines(path.call(print, "body", 0))];
15
+
16
+ // The second part of this node is a list of optional block-local variables
17
+ if (path.getValue().body[1]) {
18
+ parts.push("; ", join(", ", path.map(print, "body", 1)));
19
+ }
20
+
21
+ parts.push("| ");
22
+ return concat(parts);
23
+ }
24
+
25
+ function printBlock(braces) {
26
+ return function printBlockWithBraces(path, opts, print) {
27
+ const [variables, statements] = path.getValue().body;
28
+ const stmts =
29
+ statements.type === "stmts" ? statements.body : statements.body[0].body;
30
+
31
+ let doBlockBody = "";
32
+ if (
33
+ stmts.length !== 1 ||
34
+ stmts[0].type !== "void_stmt" ||
35
+ stmts[0].comments
36
+ ) {
37
+ doBlockBody = indent(concat([softline, path.call(print, "body", 1)]));
38
+ }
39
+
40
+ // If this block is nested underneath a command or command_call node, then
41
+ // we can't use `do...end` because that will get associated with the parent
42
+ // node as opposed to the current node (because of the difference in
43
+ // operator precedence). Instead, we still use a multi-line format but
44
+ // switch to using braces instead.
45
+ const useBraces = braces && hasAncestor(path, ["command", "command_call"]);
46
+
47
+ const doBlock = concat([
48
+ useBraces ? " {" : " do",
49
+ variables ? concat([" ", path.call(print, "body", 0)]) : "",
50
+ doBlockBody,
51
+ concat([softline, useBraces ? "}" : "end"])
52
+ ]);
53
+
54
+ // We can hit this next pattern if within the block the only statement is a
55
+ // comment.
56
+ if (
57
+ stmts.length === 1 &&
58
+ stmts[0].type === "void_stmt" &&
59
+ stmts[0].comments
60
+ ) {
61
+ return concat([breakParent, doBlock]);
62
+ }
63
+
64
+ const blockReceiver = path.getParentNode().body[0];
65
+
66
+ // If the parent node is a command node, then there are no parentheses
67
+ // around the arguments to that command, so we need to break the block
68
+ if (["command", "command_call"].includes(blockReceiver.type)) {
69
+ return concat([breakParent, doBlock]);
70
+ }
71
+
72
+ const hasBody = stmts.some(({ type }) => type !== "void_stmt");
73
+ const braceBlock = concat([
74
+ " {",
75
+ hasBody || variables ? " " : "",
76
+ variables ? path.call(print, "body", 0) : "",
77
+ path.call(print, "body", 1),
78
+ hasBody ? " " : "",
79
+ "}"
80
+ ]);
81
+
82
+ return group(ifBreak(doBlock, braceBlock));
83
+ };
84
+ }
85
+
86
+ module.exports = {
87
+ block_var: printBlockVar,
88
+ brace_block: printBlock(true),
89
+ do_block: printBlock(false)
90
+ };
@@ -5,8 +5,8 @@ const {
5
5
  ifBreak,
6
6
  indent,
7
7
  softline
8
- } = require("../prettier");
9
- const { first, makeCall, noIndent } = require("../utils");
8
+ } = require("../../prettier");
9
+ const { makeCall, noIndent } = require("../../utils");
10
10
 
11
11
  const toProc = require("../toProc");
12
12
 
@@ -24,6 +24,12 @@ function printCall(path, opts, print) {
24
24
  // call syntax so if `call` is implicit, we don't print it out.
25
25
  const messageDoc = messageNode === "call" ? "" : path.call(print, "body", 2);
26
26
 
27
+ // For certain left sides of the call nodes, we want to attach directly to
28
+ // the } or end.
29
+ if (noIndent.includes(receiverNode.type)) {
30
+ return concat([receiverDoc, operatorDoc, messageDoc]);
31
+ }
32
+
27
33
  // The right side of the call node, as in everything including the operator
28
34
  // and beyond.
29
35
  const rightSideDoc = concat([
@@ -37,7 +43,7 @@ function printCall(path, opts, print) {
37
43
 
38
44
  // If our parent node is a chained node then we're not going to group the
39
45
  // right side of the expression, as we want to have a nice multi-line layout.
40
- if (chained.includes(parentNode.type)) {
46
+ if (chained.includes(parentNode.type) && !node.comments) {
41
47
  parentNode.chain = (node.chain || 0) + 1;
42
48
  parentNode.callChain = (node.callChain || 0) + 1;
43
49
  parentNode.breakDoc = (node.breakDoc || [receiverDoc]).concat(rightSideDoc);
@@ -47,18 +53,10 @@ function printCall(path, opts, print) {
47
53
  // If we're at the top of a chain, then we're going to print out a nice
48
54
  // multi-line layout if this doesn't break into multiple lines.
49
55
  if (!chained.includes(parentNode.type) && (node.chain || 0) >= 3) {
50
- let breakDoc = concat(node.breakDoc.concat(rightSideDoc));
51
- if (!noIndent.includes(node.firstReceiverType)) {
52
- breakDoc = indent(breakDoc);
53
- }
54
-
55
- return ifBreak(group(breakDoc), concat([receiverDoc, group(rightSideDoc)]));
56
- }
57
-
58
- // For certain left sides of the call nodes, we want to attach directly to
59
- // the } or end.
60
- if (noIndent.includes(receiverNode.type)) {
61
- return concat([receiverDoc, operatorDoc, messageDoc]);
56
+ return ifBreak(
57
+ group(indent(concat(node.breakDoc.concat(rightSideDoc)))),
58
+ concat([receiverDoc, group(rightSideDoc)])
59
+ );
62
60
  }
63
61
 
64
62
  return group(concat([receiverDoc, group(indent(rightSideDoc))]));
@@ -105,7 +103,7 @@ function printMethodAddArg(path, opts, print) {
105
103
 
106
104
  // If our parent node is a chained node then we're not going to group the
107
105
  // right side of the expression, as we want to have a nice multi-line layout.
108
- if (chained.includes(parentNode.type)) {
106
+ if (chained.includes(parentNode.type) && !node.comments) {
109
107
  parentNode.chain = (node.chain || 0) + 1;
110
108
  parentNode.breakDoc = (node.breakDoc || [methodDoc]).concat(argsDoc);
111
109
  parentNode.firstReceiverType = node.firstReceiverType;
@@ -138,41 +136,12 @@ function printMethodAddArg(path, opts, print) {
138
136
  return concat([methodDoc, argsDoc]);
139
137
  }
140
138
 
141
- // Sorbet type annotations look like the following:
142
- //
143
- // {method_add_block
144
- // [{method_add_arg
145
- // [{fcall
146
- // [{@ident "sig"}]},
147
- // {args []}]},
148
- // {brace_block [nil, {stmts}]}}]}
149
- //
150
- function isSorbetTypeAnnotation(node) {
151
- const [callNode, blockNode] = node.body;
152
-
153
- return (
154
- callNode.type === "method_add_arg" &&
155
- callNode.body[0].type === "fcall" &&
156
- callNode.body[0].body[0].body === "sig" &&
157
- callNode.body[1].type === "args" &&
158
- callNode.body[1].body.length === 0 &&
159
- blockNode
160
- );
161
- }
162
-
163
139
  function printMethodAddBlock(path, opts, print) {
164
140
  const node = path.getValue();
165
141
 
166
142
  const [callNode, blockNode] = node.body;
167
143
  const [callDoc, blockDoc] = path.map(print, "body");
168
144
 
169
- // Very special handling here for sorbet type annotations. They look like Ruby
170
- // code, but they're not actually Ruby code, so we're not going to mess with
171
- // them at all.
172
- if (isSorbetTypeAnnotation(node)) {
173
- return opts.originalText.slice(opts.locStart(node), opts.locEnd(node));
174
- }
175
-
176
145
  // Don't bother trying to do any kind of fancy toProc transform if the option
177
146
  // is disabled.
178
147
  if (opts.rubyToProc) {
@@ -217,10 +186,14 @@ function printMethodAddBlock(path, opts, print) {
217
186
  return concat([callDoc, blockDoc]);
218
187
  }
219
188
 
189
+ function printCallContainer(path, opts, print) {
190
+ return path.call(print, "body", 0);
191
+ }
192
+
220
193
  module.exports = {
221
194
  call: printCall,
222
- fcall: first,
195
+ fcall: printCallContainer,
223
196
  method_add_arg: printMethodAddArg,
224
197
  method_add_block: printMethodAddBlock,
225
- vcall: first
198
+ vcall: printCallContainer
226
199
  };
@@ -6,7 +6,7 @@ const {
6
6
  hardline,
7
7
  indent,
8
8
  line
9
- } = require("../prettier");
9
+ } = require("../../prettier");
10
10
 
11
11
  function printCase(path, opts, print) {
12
12
  const statement = ["case"];
@@ -5,7 +5,7 @@ const {
5
5
  ifBreak,
6
6
  indent,
7
7
  line
8
- } = require("../prettier");
8
+ } = require("../../prettier");
9
9
 
10
10
  function printClass(path, opts, print) {
11
11
  const [_constant, superclass, bodystmt] = path.getValue().body;
@@ -0,0 +1,131 @@
1
+ const {
2
+ align,
3
+ concat,
4
+ group,
5
+ ifBreak,
6
+ indent,
7
+ join,
8
+ line,
9
+ softline
10
+ } = require("../../prettier");
11
+ const { makeCall } = require("../../utils");
12
+
13
+ function docLength(doc) {
14
+ if (doc.length) {
15
+ return doc.length;
16
+ }
17
+
18
+ if (doc.parts) {
19
+ return doc.parts.reduce((sum, child) => sum + docLength(child), 0);
20
+ }
21
+
22
+ if (doc.contents) {
23
+ return docLength(doc.contents);
24
+ }
25
+
26
+ return 0;
27
+ }
28
+
29
+ function hasDef(node) {
30
+ return (
31
+ node.body[1].type === "args_add_block" &&
32
+ node.body[1].body[0].type === "args" &&
33
+ node.body[1].body[0].body[0] &&
34
+ ["def", "defs"].includes(node.body[1].body[0].body[0].type)
35
+ );
36
+ }
37
+
38
+ // Very special handling case for rspec matchers. In general with rspec matchers
39
+ // you expect to see something like:
40
+ //
41
+ // expect(foo).to receive(:bar).with(
42
+ // 'one',
43
+ // 'two',
44
+ // 'three',
45
+ // 'four',
46
+ // 'five'
47
+ // )
48
+ //
49
+ // In this case the arguments are aligned to the left side as opposed to being
50
+ // aligned with the `receive` call.
51
+ function skipArgsAlign(path) {
52
+ return ["to", "not_to"].includes(path.getValue().body[2].body);
53
+ }
54
+
55
+ // If there is a ternary argument to a command and it's going to get broken
56
+ // into multiple lines, then we're going to have to use parentheses around the
57
+ // command in order to make sure operator precedence doesn't get messed up.
58
+ function hasTernaryArg(node) {
59
+ return node.body[0].body.some((child) => child.type === "ifop");
60
+ }
61
+
62
+ function printCommand(path, opts, print) {
63
+ const node = path.getValue();
64
+
65
+ const command = path.call(print, "body", 0);
66
+ const joinedArgs = join(concat([",", line]), path.call(print, "body", 1));
67
+
68
+ const hasTernary = hasTernaryArg(node.body[1]);
69
+ let breakArgs;
70
+
71
+ if (hasTernary) {
72
+ breakArgs = indent(concat([softline, joinedArgs]));
73
+ } else if (hasDef(path.getValue())) {
74
+ breakArgs = joinedArgs;
75
+ } else {
76
+ breakArgs = align(command.length + 1, joinedArgs);
77
+ }
78
+
79
+ return group(
80
+ ifBreak(
81
+ concat([
82
+ command,
83
+ hasTernary ? "(" : " ",
84
+ breakArgs,
85
+ hasTernary ? concat([softline, ")"]) : ""
86
+ ]),
87
+ concat([command, " ", joinedArgs])
88
+ )
89
+ );
90
+ }
91
+
92
+ function printCommandCall(path, opts, print) {
93
+ const node = path.getValue();
94
+ const parts = [
95
+ path.call(print, "body", 0),
96
+ makeCall(path, opts, print),
97
+ path.call(print, "body", 2)
98
+ ];
99
+
100
+ if (!node.body[3]) {
101
+ return concat(parts);
102
+ }
103
+
104
+ const argDocs = join(concat([",", line]), path.call(print, "body", 3));
105
+ let breakDoc;
106
+
107
+ if (hasTernaryArg(node.body[3])) {
108
+ breakDoc = parts.concat(
109
+ "(",
110
+ indent(concat([softline, argDocs])),
111
+ softline,
112
+ ")"
113
+ );
114
+ parts.push(" ");
115
+ } else if (skipArgsAlign(path)) {
116
+ parts.push(" ");
117
+ breakDoc = parts.concat(argDocs);
118
+ } else {
119
+ parts.push(" ");
120
+ breakDoc = parts.concat(align(docLength(concat(parts)), argDocs));
121
+ }
122
+
123
+ const joinedDoc = parts.concat(argDocs);
124
+
125
+ return group(ifBreak(concat(breakDoc), concat(joinedDoc)));
126
+ }
127
+
128
+ module.exports = {
129
+ command: printCommand,
130
+ command_call: printCommandCall
131
+ };