prettier 0.21.0 → 1.0.1

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +112 -7
  3. data/CONTRIBUTING.md +4 -4
  4. data/README.md +18 -14
  5. data/package.json +9 -6
  6. data/src/embed.js +27 -8
  7. data/src/nodes.js +5 -2
  8. data/src/nodes/alias.js +29 -31
  9. data/src/nodes/aref.js +26 -26
  10. data/src/nodes/args.js +55 -47
  11. data/src/nodes/arrays.js +132 -106
  12. data/src/nodes/assign.js +32 -32
  13. data/src/nodes/blocks.js +8 -3
  14. data/src/nodes/calls.js +163 -60
  15. data/src/nodes/case.js +11 -7
  16. data/src/nodes/class.js +74 -0
  17. data/src/nodes/commands.js +36 -31
  18. data/src/nodes/conditionals.js +44 -30
  19. data/src/nodes/constants.js +39 -21
  20. data/src/nodes/flow.js +11 -1
  21. data/src/nodes/hashes.js +90 -109
  22. data/src/nodes/heredocs.js +34 -0
  23. data/src/nodes/hooks.js +21 -22
  24. data/src/nodes/ints.js +27 -20
  25. data/src/nodes/lambdas.js +14 -27
  26. data/src/nodes/loops.js +10 -5
  27. data/src/nodes/massign.js +87 -65
  28. data/src/nodes/methods.js +48 -73
  29. data/src/nodes/operators.js +70 -39
  30. data/src/nodes/params.js +26 -16
  31. data/src/nodes/patterns.js +108 -33
  32. data/src/nodes/regexp.js +45 -14
  33. data/src/nodes/rescue.js +72 -59
  34. data/src/nodes/statements.js +86 -44
  35. data/src/nodes/strings.js +95 -85
  36. data/src/nodes/super.js +35 -0
  37. data/src/nodes/undef.js +42 -0
  38. data/src/parser.js +86 -0
  39. data/src/parser.rb +2400 -621
  40. data/src/printer.js +90 -0
  41. data/src/ruby.js +19 -41
  42. data/src/toProc.js +4 -4
  43. data/src/utils.js +24 -88
  44. data/src/utils/literalLineNoBreak.js +7 -0
  45. data/src/utils/printEmptyCollection.js +42 -0
  46. metadata +12 -49
  47. data/src/nodes/scopes.js +0 -61
  48. data/src/parse.js +0 -37
  49. data/src/print.js +0 -23
@@ -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,12 +1,5 @@
1
- const embed = require("./embed");
2
- const parse = require("./parse");
3
- const print = require("./print");
4
-
5
- const pragmaPattern = /#\s*@(prettier|format)/;
6
- const hasPragma = (text) => pragmaPattern.test(text);
7
-
8
- const locStart = (node) => node.char_start;
9
- const locEnd = (node) => node.char_end;
1
+ const printer = require("./printer");
2
+ const parser = require("./parser");
10
3
 
11
4
  /*
12
5
  * metadata mostly pulled from linguist and rubocop:
@@ -77,59 +70,43 @@ module.exports = {
77
70
  }
78
71
  ],
79
72
  parsers: {
80
- ruby: {
81
- parse,
82
- astFormat: "ruby",
83
- hasPragma,
84
- locStart,
85
- locEnd
86
- }
73
+ ruby: parser
87
74
  },
88
75
  printers: {
89
- ruby: {
90
- embed,
91
- print
92
- }
76
+ ruby: printer
93
77
  },
94
78
  options: {
95
- addTrailingCommas: {
96
- type: "boolean",
97
- category: "Global",
98
- default: false,
99
- description:
100
- "Adds a trailing comma to array literals, hash literals, and method calls."
101
- },
102
- inlineConditionals: {
79
+ rubyArrayLiteral: {
103
80
  type: "boolean",
104
- category: "Global",
81
+ category: "Ruby",
105
82
  default: true,
106
83
  description:
107
- "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."
108
85
  },
109
- inlineLoops: {
86
+ rubyHashLabel: {
110
87
  type: "boolean",
111
- category: "Global",
88
+ category: "Ruby",
112
89
  default: true,
113
90
  description:
114
- "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."
115
92
  },
116
- preferHashLabels: {
93
+ rubyModifier: {
117
94
  type: "boolean",
118
- category: "Global",
95
+ category: "Ruby",
119
96
  default: true,
120
97
  description:
121
- "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."
122
99
  },
123
- preferSingleQuotes: {
100
+ rubySingleQuote: {
124
101
  type: "boolean",
125
- category: "Global",
102
+ category: "Ruby",
126
103
  default: true,
127
104
  description:
128
105
  "When double quotes are not necessary for interpolation, prefers the use of single quotes for string literals."
129
106
  },
130
- toProcTransform: {
107
+ rubyToProc: {
131
108
  type: "boolean",
132
- category: "Global",
109
+ category: "Ruby",
133
110
  default: false,
134
111
  description:
135
112
  "When possible, convert blocks to the more concise Symbol#to_proc syntax."
@@ -137,6 +114,7 @@ module.exports = {
137
114
  },
138
115
  defaultOptions: {
139
116
  printWidth: 80,
140
- tabWidth: 2
117
+ tabWidth: 2,
118
+ trailingComma: "none"
141
119
  }
142
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,19 +1,14 @@
1
- const {
2
- breakParent,
3
- concat,
4
- hardline,
5
- lineSuffix,
6
- literalline
7
- } = require("./prettier");
1
+ const { concat } = require("./prettier");
8
2
  const isEmptyStmts = require("./utils/isEmptyStmts");
9
-
10
- const concatBody = (path, opts, print) => concat(path.map(print, "body"));
3
+ const literalLineNoBreak = require("./utils/literalLineNoBreak");
4
+ const printEmptyCollection = require("./utils/printEmptyCollection");
11
5
 
12
6
  // If the node is a type of assignment or if the node is a paren and nested
13
7
  // inside that paren is a node that is a type of assignment.
14
8
  const containsAssignment = (node) =>
15
- ["assign", "massign"].includes(node.type) ||
16
- (node.type === "paren" && node.body[0].body.some(containsAssignment));
9
+ node &&
10
+ (["assign", "massign", "opassign"].includes(node.type) ||
11
+ (Array.isArray(node.body) && node.body.some(containsAssignment)));
17
12
 
18
13
  const docLength = (doc) => {
19
14
  if (doc.length) {
@@ -35,6 +30,8 @@ const empty = () => "";
35
30
 
36
31
  const first = (path, opts, print) => path.call(print, "body", 0);
37
32
 
33
+ const getTrailingComma = (opts) => ["all", "es5"].includes(opts.trailingComma);
34
+
38
35
  const hasAncestor = (path, types) => {
39
36
  let parent = 0;
40
37
  let parentNode = path.getParentNode();
@@ -53,34 +50,6 @@ const hasAncestor = (path, types) => {
53
50
 
54
51
  const literal = (value) => () => value;
55
52
 
56
- const makeArgs = (path, opts, print, argsIndex) => {
57
- let argNodes = path.getValue().body[argsIndex];
58
- const argPattern = [print, "body", argsIndex, "body"];
59
-
60
- if (argNodes.type === "args_add_block") {
61
- [argNodes] = argNodes.body;
62
- argPattern.push(0, "body");
63
- }
64
-
65
- const args = path.call(print, "body", argsIndex);
66
- const heredocs = [];
67
-
68
- argNodes.body.forEach((argNode, index) => {
69
- if (argNode.type === "heredoc") {
70
- const content = path.map.apply(
71
- path,
72
- argPattern.slice().concat([index, "body"])
73
- );
74
- heredocs.push(
75
- concat([literalline].concat(content).concat([argNode.ending]))
76
- );
77
- args[index] = argNode.beging;
78
- }
79
- });
80
-
81
- return { args, heredocs };
82
- };
83
-
84
53
  const makeCall = (path, opts, print) => {
85
54
  const operation = path.getValue().body[1];
86
55
 
@@ -91,69 +60,36 @@ const makeCall = (path, opts, print) => {
91
60
  return operation === "::" ? "." : path.call(print, "body", 1);
92
61
  };
93
62
 
94
- const makeList = (path, opts, print) => path.map(print, "body");
95
-
96
- const nodeDive = (node, steps) => {
97
- let current = node;
98
-
99
- steps.forEach((step) => {
100
- current = current[step];
101
- });
102
-
103
- return current;
104
- };
63
+ const noIndent = [
64
+ "array",
65
+ "hash",
66
+ "heredoc",
67
+ "if",
68
+ "method_add_block",
69
+ "xstring_literal"
70
+ ];
105
71
 
106
72
  const prefix = (value) => (path, opts, print) =>
107
73
  concat([value, path.call(print, "body", 0)]);
108
74
 
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
-
75
+ const skippable = ["array", "hash", "heredoc", "lambda", "regexp_literal"];
132
76
  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]);
77
+ skippable.includes(node.type) ||
78
+ (node.type === "call" && skipAssignIndent(node.body[0]));
141
79
 
142
80
  module.exports = {
143
- concatBody,
144
81
  containsAssignment,
145
82
  docLength,
146
83
  empty,
147
84
  first,
85
+ getTrailingComma,
148
86
  hasAncestor,
149
87
  isEmptyStmts,
150
88
  literal,
151
- makeArgs,
89
+ literalLineNoBreak,
152
90
  makeCall,
153
- makeList,
154
- nodeDive,
91
+ noIndent,
155
92
  prefix,
156
- printComments,
157
- skipAssignIndent,
158
- surround
93
+ printEmptyCollection,
94
+ skipAssignIndent
159
95
  };
@@ -0,0 +1,7 @@
1
+ const literalLineNoBreak = {
2
+ type: "line",
3
+ hard: true,
4
+ literal: true
5
+ };
6
+
7
+ module.exports = literalLineNoBreak;
@@ -0,0 +1,42 @@
1
+ const { concat, group, hardline, indent, join, line } = require("../prettier");
2
+
3
+ // Empty collections are array or hash literals that do not contain any
4
+ // contents. They can, however, have comments inside the body. You can solve
5
+ // this by having a child node inside the array that gets the comments attached
6
+ // to it, but that requires modifying the parser. Instead, we can just manually
7
+ // print out the non-leading comments here.
8
+ function printEmptyCollection(path, opts, startToken, endToken) {
9
+ const node = path.getValue();
10
+
11
+ // If there are no comments or only leading comments, then we can just print
12
+ // out the start and end token and be done, as there are no comments inside
13
+ // the body of this node.
14
+ if (!node.comments || !node.comments.some((comment) => !comment.leading)) {
15
+ return `${startToken}${endToken}`;
16
+ }
17
+
18
+ const comments = [];
19
+
20
+ // For each comment, go through its path and print it out manually.
21
+ const printComment = (commentPath) => {
22
+ const comment = commentPath.getValue();
23
+
24
+ if (!comment.leading) {
25
+ comment.printed = true;
26
+ comments.push(opts.printer.printComment(commentPath));
27
+ }
28
+ };
29
+
30
+ path.each(printComment, "comments");
31
+
32
+ return group(
33
+ concat([
34
+ startToken,
35
+ indent(concat([hardline, join(hardline, comments)])),
36
+ line,
37
+ endToken
38
+ ])
39
+ );
40
+ }
41
+
42
+ module.exports = printEmptyCollection;
metadata CHANGED
@@ -1,57 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prettier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 1.0.1
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-02 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: minitest
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '5.13'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '5.13'
41
- - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '13.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '13.0'
11
+ date: 2020-12-12 00:00:00.000000000 Z
12
+ dependencies: []
55
13
  description:
56
14
  email:
57
15
  executables:
@@ -82,11 +40,13 @@ files:
82
40
  - src/nodes/blocks.js
83
41
  - src/nodes/calls.js
84
42
  - src/nodes/case.js
43
+ - src/nodes/class.js
85
44
  - src/nodes/commands.js
86
45
  - src/nodes/conditionals.js
87
46
  - src/nodes/constants.js
88
47
  - src/nodes/flow.js
89
48
  - src/nodes/hashes.js
49
+ - src/nodes/heredocs.js
90
50
  - src/nodes/hooks.js
91
51
  - src/nodes/ints.js
92
52
  - src/nodes/lambdas.js
@@ -99,18 +59,21 @@ files:
99
59
  - src/nodes/regexp.js
100
60
  - src/nodes/rescue.js
101
61
  - src/nodes/return.js
102
- - src/nodes/scopes.js
103
62
  - src/nodes/statements.js
104
63
  - src/nodes/strings.js
105
- - src/parse.js
64
+ - src/nodes/super.js
65
+ - src/nodes/undef.js
66
+ - src/parser.js
106
67
  - src/parser.rb
107
68
  - src/prettier.js
108
- - src/print.js
69
+ - src/printer.js
109
70
  - src/ruby.js
110
71
  - src/toProc.js
111
72
  - src/utils.js
112
73
  - src/utils/inlineEnsureParens.js
113
74
  - src/utils/isEmptyStmts.js
75
+ - src/utils/literalLineNoBreak.js
76
+ - src/utils/printEmptyCollection.js
114
77
  homepage: https://github.com/prettier/plugin-ruby#readme
115
78
  licenses:
116
79
  - MIT
@@ -130,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
93
  - !ruby/object:Gem::Version
131
94
  version: '0'
132
95
  requirements: []
133
- rubygems_version: 3.0.3
96
+ rubygems_version: 3.1.4
134
97
  signing_key:
135
98
  specification_version: 4
136
99
  summary: prettier plugin for the Ruby programming language