prettier 0.20.0 → 1.0.0.pre.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +118 -4
  3. data/CONTRIBUTING.md +8 -6
  4. data/README.md +67 -60
  5. data/node_modules/prettier/bin-prettier.js +12317 -50112
  6. data/node_modules/prettier/index.js +33352 -27419
  7. data/node_modules/prettier/third-party.js +5678 -7676
  8. data/package.json +4 -4
  9. data/src/embed.js +27 -8
  10. data/src/nodes.js +6 -2
  11. data/src/nodes/alias.js +65 -24
  12. data/src/nodes/aref.js +55 -0
  13. data/src/nodes/args.js +55 -47
  14. data/src/nodes/arrays.js +150 -137
  15. data/src/nodes/assign.js +32 -32
  16. data/src/nodes/blocks.js +8 -3
  17. data/src/nodes/calls.js +129 -70
  18. data/src/nodes/case.js +11 -7
  19. data/src/nodes/class.js +74 -0
  20. data/src/nodes/commands.js +36 -31
  21. data/src/nodes/conditionals.js +48 -46
  22. data/src/nodes/constants.js +39 -21
  23. data/src/nodes/flow.js +45 -17
  24. data/src/nodes/hashes.js +126 -112
  25. data/src/nodes/heredocs.js +34 -0
  26. data/src/nodes/hooks.js +36 -7
  27. data/src/nodes/ints.js +27 -20
  28. data/src/nodes/lambdas.js +69 -52
  29. data/src/nodes/loops.js +19 -29
  30. data/src/nodes/massign.js +87 -65
  31. data/src/nodes/methods.js +48 -73
  32. data/src/nodes/operators.js +70 -39
  33. data/src/nodes/params.js +26 -16
  34. data/src/nodes/patterns.js +108 -33
  35. data/src/nodes/regexp.js +38 -14
  36. data/src/nodes/rescue.js +72 -59
  37. data/src/nodes/statements.js +86 -44
  38. data/src/nodes/strings.js +94 -90
  39. data/src/nodes/super.js +35 -0
  40. data/src/nodes/undef.js +42 -0
  41. data/src/parser.js +71 -0
  42. data/src/parser.rb +2554 -0
  43. data/src/printer.js +90 -0
  44. data/src/ruby.js +20 -61
  45. data/src/toProc.js +4 -4
  46. data/src/utils.js +24 -88
  47. data/src/utils/inlineEnsureParens.js +42 -0
  48. data/src/utils/isEmptyStmts.js +7 -0
  49. data/src/utils/literalLineNoBreak.js +7 -0
  50. metadata +15 -20
  51. data/src/haml.js +0 -21
  52. data/src/haml/embed.js +0 -58
  53. data/src/haml/nodes/comment.js +0 -27
  54. data/src/haml/nodes/doctype.js +0 -32
  55. data/src/haml/nodes/filter.js +0 -16
  56. data/src/haml/nodes/hamlComment.js +0 -21
  57. data/src/haml/nodes/script.js +0 -29
  58. data/src/haml/nodes/silentScript.js +0 -59
  59. data/src/haml/nodes/tag.js +0 -157
  60. data/src/haml/parse.js +0 -18
  61. data/src/haml/parse.rb +0 -64
  62. data/src/haml/print.js +0 -38
  63. data/src/nodes/scopes.js +0 -61
  64. data/src/parse.js +0 -37
  65. data/src/print.js +0 -23
  66. data/src/ripper.rb +0 -811
@@ -0,0 +1,90 @@
1
+ const { concat, trim } = require("./prettier");
2
+
3
+ const embed = require("./embed");
4
+ const nodes = require("./nodes");
5
+
6
+ // This is the generic node print function, used to convert any node in the AST
7
+ // into its equivalent Doc representation.
8
+ function printNode(path, opts, print) {
9
+ const { type, body } = path.getValue();
10
+
11
+ if (type in nodes) {
12
+ return nodes[type](path, opts, print);
13
+ }
14
+
15
+ if (type[0] === "@") {
16
+ return body;
17
+ }
18
+
19
+ const ast = JSON.stringify(body, null, 2);
20
+ throw new Error(`Unsupported node encountered: ${type}\n${ast}`);
21
+ }
22
+
23
+ const noComments = [
24
+ "args",
25
+ "args_add_block",
26
+ "args_add_star",
27
+ "mlhs",
28
+ "mlhs_add_post",
29
+ "mlhs_add_star"
30
+ ];
31
+
32
+ // Certain nodes are used more for organizational purposed than for actually
33
+ // displaying content, so we tell prettier that we don't want comments attached
34
+ // to them.
35
+ function canAttachComment(node) {
36
+ return !noComments.includes(node.type);
37
+ }
38
+
39
+ // This function tells prettier how to recurse down our AST so that it can find
40
+ // where it needs to attach the comments.
41
+ function getCommentChildNodes(node) {
42
+ switch (node.type) {
43
+ case "heredoc":
44
+ return [node.beging];
45
+ case "rescue":
46
+ return [].concat(node.body[0]).concat(node.body.slice(1));
47
+ case "aryptn":
48
+ return [node.body[0]]
49
+ .concat(node.body[1])
50
+ .concat(node.body[2])
51
+ .concat(node.body[3]);
52
+ case "hshptn": {
53
+ const pairs = node.body[1];
54
+ const values = pairs.reduce((left, right) => left.concat(right), []);
55
+
56
+ return [node.body[0]].concat(values).concat(node.body[2]);
57
+ }
58
+ default:
59
+ return node.body;
60
+ }
61
+ }
62
+
63
+ // This is the generic print function for any comment in the AST. It handles
64
+ // both regular comments that begin with a # and embdoc comments, which are
65
+ // surrounded by =begin..=end.
66
+ function printComment(path, _opts) {
67
+ const comment = path.getValue();
68
+
69
+ if (comment.type === "@comment") {
70
+ return `#${comment.value}`;
71
+ }
72
+
73
+ return concat([trim, comment.value]);
74
+ }
75
+
76
+ // To be honest I'm not 100% sure this function is actually necessary, but it
77
+ // *feels* like a block comment equivalent in JavaScript so I'm going to leave
78
+ // it in place for now.
79
+ function isBlockComment(comment) {
80
+ return comment.type === "@embdoc";
81
+ }
82
+
83
+ module.exports = {
84
+ embed,
85
+ print: printNode,
86
+ canAttachComment,
87
+ getCommentChildNodes,
88
+ printComment,
89
+ isBlockComment
90
+ };
@@ -1,14 +1,5 @@
1
- const embed = require("./embed");
2
- const parse = require("./parse");
3
- const print = require("./print");
4
-
5
- const haml = require("./haml");
6
-
7
- const pragmaPattern = /#\s*@(prettier|format)/;
8
- const hasPragma = (text) => pragmaPattern.test(text);
9
-
10
- const locStart = (node) => node.char_start;
11
- const locEnd = (node) => node.char_end;
1
+ const printer = require("./printer");
2
+ const parser = require("./parser");
12
3
 
13
4
  /*
14
5
  * metadata mostly pulled from linguist and rubocop:
@@ -76,86 +67,54 @@ module.exports = {
76
67
  interpreters: ["jruby", "macruby", "rake", "rbx", "ruby"],
77
68
  linguistLanguageId: 326,
78
69
  vscodeLanguageIds: ["ruby"]
79
- },
80
- {
81
- name: "HAML",
82
- parsers: ["haml"],
83
- extensions: [".haml"],
84
- vscodeLanguageIds: ["haml"]
85
70
  }
86
71
  ],
87
72
  parsers: {
88
- ruby: {
89
- parse,
90
- astFormat: "ruby",
91
- hasPragma,
92
- locStart,
93
- locEnd
94
- },
95
- haml: {
96
- parse: haml.parse,
97
- astFormat: "haml",
98
- hasPragma: haml.hasPragma,
99
- locStart: haml.locStart,
100
- locEnd: haml.locEnd
101
- }
73
+ ruby: parser
102
74
  },
103
75
  printers: {
104
- ruby: {
105
- embed,
106
- print
107
- },
108
- haml: {
109
- embed: haml.embed,
110
- print: haml.print
111
- }
76
+ ruby: printer
112
77
  },
113
78
  options: {
114
- addTrailingCommas: {
79
+ rubyArrayLiteral: {
115
80
  type: "boolean",
116
- category: "Global",
117
- default: false,
118
- description:
119
- "Adds a trailing comma to array literals, hash literals, and method calls."
120
- },
121
- inlineConditionals: {
122
- type: "boolean",
123
- category: "Global",
81
+ category: "Ruby",
124
82
  default: true,
125
83
  description:
126
- "When it fits on one line, allows if and unless statements to use the modifier form."
84
+ "When possible, favor the use of string and symbol array literals."
127
85
  },
128
- inlineLoops: {
86
+ rubyHashLabel: {
129
87
  type: "boolean",
130
- category: "Global",
88
+ category: "Ruby",
131
89
  default: true,
132
90
  description:
133
- "When it fits on one line, allows while and until statements to use the modifier form."
91
+ "When possible, uses the shortened hash key syntax, as opposed to hash rockets."
134
92
  },
135
- preferHashLabels: {
93
+ rubyModifier: {
136
94
  type: "boolean",
137
- category: "Global",
95
+ category: "Ruby",
138
96
  default: true,
139
97
  description:
140
- "When possible, uses the shortened hash key syntax, as opposed to hash rockets."
98
+ "When it fits on one line, allows if, unless, while, and until statements to use the modifier form."
141
99
  },
142
- preferSingleQuotes: {
100
+ rubySingleQuote: {
143
101
  type: "boolean",
144
- category: "Global",
102
+ category: "Ruby",
145
103
  default: true,
146
104
  description:
147
105
  "When double quotes are not necessary for interpolation, prefers the use of single quotes for string literals."
148
106
  },
149
- toProcTransform: {
107
+ rubyToProc: {
150
108
  type: "boolean",
151
- category: "Global",
152
- default: true,
109
+ category: "Ruby",
110
+ default: false,
153
111
  description:
154
112
  "When possible, convert blocks to the more concise Symbol#to_proc syntax."
155
113
  }
156
114
  },
157
115
  defaultOptions: {
158
116
  printWidth: 80,
159
- tabWidth: 2
117
+ tabWidth: 2,
118
+ trailingComma: "none"
160
119
  }
161
120
  };
@@ -11,8 +11,8 @@ const isCall = (node) => ["::", "."].includes(node) || node.type === "@period";
11
11
  // [1, 2, 3].map(&:to_s)
12
12
  //
13
13
  // This works with `do` blocks as well.
14
- const toProc = (path, opts, node) => {
15
- if (!node || !opts.toProcTransform) {
14
+ const toProc = (path, node) => {
15
+ if (!node) {
16
16
  return null;
17
17
  }
18
18
 
@@ -57,9 +57,9 @@ const toProc = (path, opts, node) => {
57
57
  return null;
58
58
  }
59
59
 
60
- // Ensure that statement is a call
60
+ // Ensure that statement is a call and that it has no comments attached
61
61
  const [statement] = statements.body;
62
- if (statement.type !== "call") {
62
+ if (statement.type !== "call" || statement.comments) {
63
63
  return null;
64
64
  }
65
65
 
@@ -1,18 +1,13 @@
1
- const {
2
- breakParent,
3
- concat,
4
- hardline,
5
- lineSuffix,
6
- literalline
7
- } = require("./prettier");
8
-
9
- const concatBody = (path, opts, print) => concat(path.map(print, "body"));
1
+ const { concat } = require("./prettier");
2
+ const isEmptyStmts = require("./utils/isEmptyStmts");
3
+ const literalLineNoBreak = require("./utils/literalLineNoBreak");
10
4
 
11
5
  // If the node is a type of assignment or if the node is a paren and nested
12
6
  // inside that paren is a node that is a type of assignment.
13
7
  const containsAssignment = (node) =>
14
- ["assign", "massign"].includes(node.type) ||
15
- (node.type === "paren" && node.body[0].body.some(containsAssignment));
8
+ node &&
9
+ (["assign", "massign", "opassign"].includes(node.type) ||
10
+ (Array.isArray(node.body) && node.body.some(containsAssignment)));
16
11
 
17
12
  const docLength = (doc) => {
18
13
  if (doc.length) {
@@ -34,6 +29,8 @@ const empty = () => "";
34
29
 
35
30
  const first = (path, opts, print) => path.call(print, "body", 0);
36
31
 
32
+ const getTrailingComma = (opts) => ["all", "es5"].includes(opts.trailingComma);
33
+
37
34
  const hasAncestor = (path, types) => {
38
35
  let parent = 0;
39
36
  let parentNode = path.getParentNode();
@@ -52,45 +49,6 @@ const hasAncestor = (path, types) => {
52
49
 
53
50
  const literal = (value) => () => value;
54
51
 
55
- const makeArgs = (path, opts, print, argsIndex) => {
56
- let argNodes = path.getValue().body[argsIndex];
57
- const argPattern = [print, "body", argsIndex, "body"];
58
-
59
- if (argNodes.type === "args_add_block") {
60
- [argNodes] = argNodes.body;
61
- argPattern.push(0, "body");
62
- }
63
-
64
- const args = path.call(print, "body", argsIndex);
65
- const heredocs = [];
66
-
67
- argNodes.body.forEach((argNode, index) => {
68
- let pattern;
69
- let heredoc;
70
-
71
- if (argNode.type === "heredoc") {
72
- pattern = [index, "body"];
73
- heredoc = argNode;
74
- } else if (
75
- argNode.type === "string_literal" &&
76
- argNode.body[0].type === "heredoc"
77
- ) {
78
- pattern = [index, "body", 0, "body"];
79
- [heredoc] = argNode.body;
80
- } else {
81
- return;
82
- }
83
-
84
- const content = path.map.apply(path, argPattern.slice().concat(pattern));
85
- heredocs.push(
86
- concat([literalline].concat(content).concat([heredoc.ending]))
87
- );
88
- args[index] = heredoc.beging;
89
- });
90
-
91
- return { args, heredocs };
92
- };
93
-
94
52
  const makeCall = (path, opts, print) => {
95
53
  const operation = path.getValue().body[1];
96
54
 
@@ -101,57 +59,35 @@ const makeCall = (path, opts, print) => {
101
59
  return operation === "::" ? "." : path.call(print, "body", 1);
102
60
  };
103
61
 
104
- const makeList = (path, opts, print) => path.map(print, "body");
62
+ const noIndent = [
63
+ "array",
64
+ "hash",
65
+ "heredoc",
66
+ "if",
67
+ "method_add_block",
68
+ "xstring_literal"
69
+ ];
105
70
 
106
71
  const prefix = (value) => (path, opts, print) =>
107
72
  concat([value, path.call(print, "body", 0)]);
108
73
 
109
- const printComments = (printed, start, comments) => {
110
- let node = printed;
111
-
112
- comments.forEach((comment) => {
113
- if (comment.start < start) {
114
- node = concat([
115
- comment.break ? breakParent : "",
116
- comment.body,
117
- hardline,
118
- node
119
- ]);
120
- } else {
121
- node = concat([
122
- node,
123
- comment.break ? breakParent : "",
124
- lineSuffix(` ${comment.body}`)
125
- ]);
126
- }
127
- });
128
-
129
- return node;
130
- };
131
-
74
+ const skippable = ["array", "hash", "heredoc", "lambda", "regexp_literal"];
132
75
  const skipAssignIndent = (node) =>
133
- ["array", "hash", "heredoc", "lambda", "regexp_literal"].includes(
134
- node.type
135
- ) ||
136
- (node.type === "call" && skipAssignIndent(node.body[0])) ||
137
- (node.type === "string_literal" && node.body[0].type === "heredoc");
138
-
139
- const surround = (left, right) => (path, opts, print) =>
140
- concat([left, path.call(print, "body", 0), right]);
76
+ skippable.includes(node.type) ||
77
+ (node.type === "call" && skipAssignIndent(node.body[0]));
141
78
 
142
79
  module.exports = {
143
- concatBody,
144
80
  containsAssignment,
145
81
  docLength,
146
82
  empty,
147
83
  first,
84
+ getTrailingComma,
148
85
  hasAncestor,
86
+ isEmptyStmts,
149
87
  literal,
150
- makeArgs,
88
+ literalLineNoBreak,
151
89
  makeCall,
152
- makeList,
90
+ noIndent,
153
91
  prefix,
154
- printComments,
155
- skipAssignIndent,
156
- surround
92
+ skipAssignIndent
157
93
  };
@@ -0,0 +1,42 @@
1
+ const needsParens = ["args", "assign", "assoc_new", "massign", "opassign"];
2
+
3
+ // If you have a modifier statement (for instance an inline if statement or an
4
+ // inline while loop) there are times when you need to wrap the entire statement
5
+ // in parentheses. This occurs when you have something like:
6
+ //
7
+ // foo[:foo] =
8
+ // if bar?
9
+ // baz
10
+ // end
11
+ //
12
+ // Normally we would shorten this to an inline version, which would result in:
13
+ //
14
+ // foo[:foo] = baz if bar?
15
+ //
16
+ // but this actually has different semantic meaning. The first example will
17
+ // result in a nil being inserted into the hash for the :foo key, whereas the
18
+ // second example will result in an empty hash because the if statement applies
19
+ // to the entire assignment.
20
+ //
21
+ // We can fix this in a couple of ways. We can use the then keyword, as in:
22
+ //
23
+ // foo[:foo] = if bar? then baz end
24
+ //
25
+ // but I haven't actually seen this anywhere. We can also just leave it as is
26
+ // with the multi-line version, but for a short predicate and short value it
27
+ // looks pretty silly. The last option and the one I've selected here is to add
28
+ // parentheses on both sides of the expression, as in:
29
+ //
30
+ // foo[:foo] = (baz if bar?)
31
+ //
32
+ // This approach maintains the nice conciseness of the inline version, while
33
+ // keeping the correct semantic meaning.
34
+ const inlineEnsureParens = (path, parts) => {
35
+ if (needsParens.includes(path.getParentNode().type)) {
36
+ return ["("].concat(parts, ")");
37
+ }
38
+
39
+ return parts;
40
+ };
41
+
42
+ module.exports = inlineEnsureParens;
@@ -0,0 +1,7 @@
1
+ const isEmptyStmts = (node) =>
2
+ node &&
3
+ node.type === "stmts" &&
4
+ node.body.length === 1 &&
5
+ node.body[0].type === "void_stmt";
6
+
7
+ module.exports = isEmptyStmts;
@@ -0,0 +1,7 @@
1
+ const literalLineNoBreak = {
2
+ type: "line",
3
+ hard: true,
4
+ literal: true
5
+ };
6
+
7
+ module.exports = literalLineNoBreak;
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: 0.20.0
4
+ version: 1.0.0.pre.rc2
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-08-28 00:00:00.000000000 Z
11
+ date: 2020-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -73,31 +73,22 @@ files:
73
73
  - node_modules/prettier/third-party.js
74
74
  - package.json
75
75
  - src/embed.js
76
- - src/haml.js
77
- - src/haml/embed.js
78
- - src/haml/nodes/comment.js
79
- - src/haml/nodes/doctype.js
80
- - src/haml/nodes/filter.js
81
- - src/haml/nodes/hamlComment.js
82
- - src/haml/nodes/script.js
83
- - src/haml/nodes/silentScript.js
84
- - src/haml/nodes/tag.js
85
- - src/haml/parse.js
86
- - src/haml/parse.rb
87
- - src/haml/print.js
88
76
  - src/nodes.js
89
77
  - src/nodes/alias.js
78
+ - src/nodes/aref.js
90
79
  - src/nodes/args.js
91
80
  - src/nodes/arrays.js
92
81
  - src/nodes/assign.js
93
82
  - src/nodes/blocks.js
94
83
  - src/nodes/calls.js
95
84
  - src/nodes/case.js
85
+ - src/nodes/class.js
96
86
  - src/nodes/commands.js
97
87
  - src/nodes/conditionals.js
98
88
  - src/nodes/constants.js
99
89
  - src/nodes/flow.js
100
90
  - src/nodes/hashes.js
91
+ - src/nodes/heredocs.js
101
92
  - src/nodes/hooks.js
102
93
  - src/nodes/ints.js
103
94
  - src/nodes/lambdas.js
@@ -110,16 +101,20 @@ files:
110
101
  - src/nodes/regexp.js
111
102
  - src/nodes/rescue.js
112
103
  - src/nodes/return.js
113
- - src/nodes/scopes.js
114
104
  - src/nodes/statements.js
115
105
  - src/nodes/strings.js
116
- - src/parse.js
106
+ - src/nodes/super.js
107
+ - src/nodes/undef.js
108
+ - src/parser.js
109
+ - src/parser.rb
117
110
  - src/prettier.js
118
- - src/print.js
119
- - src/ripper.rb
111
+ - src/printer.js
120
112
  - src/ruby.js
121
113
  - src/toProc.js
122
114
  - src/utils.js
115
+ - src/utils/inlineEnsureParens.js
116
+ - src/utils/isEmptyStmts.js
117
+ - src/utils/literalLineNoBreak.js
123
118
  homepage: https://github.com/prettier/plugin-ruby#readme
124
119
  licenses:
125
120
  - MIT
@@ -135,9 +130,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
135
130
  version: '0'
136
131
  required_rubygems_version: !ruby/object:Gem::Requirement
137
132
  requirements:
138
- - - ">="
133
+ - - ">"
139
134
  - !ruby/object:Gem::Version
140
- version: '0'
135
+ version: 1.3.1
141
136
  requirements: []
142
137
  rubygems_version: 3.0.3
143
138
  signing_key: