prettier 1.4.0 → 1.5.4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +356 -380
- data/README.md +22 -11
- data/package.json +4 -4
- data/rubocop.yml +3 -0
- data/src/haml/parser.js +2 -2
- data/src/haml/parser.rb +0 -2
- data/src/parser/getNetcat.js +17 -10
- data/src/parser/netcat.js +0 -2
- data/src/parser/parseSync.js +25 -15
- data/src/parser/requestParse.js +3 -3
- data/src/parser/server.rb +7 -2
- data/src/plugin.js +7 -0
- data/src/rbs/parser.js +2 -2
- data/src/rbs/parser.rb +8 -4
- data/src/ruby/embed.js +61 -13
- data/src/ruby/nodes/args.js +86 -24
- data/src/ruby/nodes/arrays.js +36 -33
- data/src/ruby/nodes/class.js +17 -27
- data/src/ruby/nodes/commands.js +1 -1
- data/src/ruby/nodes/conditionals.js +1 -1
- data/src/ruby/nodes/hashes.js +28 -14
- data/src/ruby/nodes/heredocs.js +5 -3
- data/src/ruby/nodes/loops.js +4 -10
- data/src/ruby/nodes/methods.js +4 -11
- data/src/ruby/nodes/statements.js +3 -5
- data/src/ruby/parser.js +2 -2
- data/src/ruby/parser.rb +81 -5
- data/src/ruby/printer.js +8 -3
- data/src/utils.js +2 -1
- data/src/utils/inlineEnsureParens.js +8 -1
- data/src/utils/isEmptyBodyStmt.js +7 -0
- data/src/utils/isEmptyStmts.js +9 -5
- data/src/utils/literallineWithoutBreakParent.js +7 -0
- data/src/utils/printEmptyCollection.js +9 -2
- metadata +5 -4
- data/src/utils/literalLineNoBreak.js +0 -7
data/README.md
CHANGED
@@ -128,17 +128,19 @@ The `prettier` executable is now installed and ready for use:
|
|
128
128
|
|
129
129
|
Below are the options (from [`src/plugin.js`](src/plugin.js)) that `@prettier/plugin-ruby` currently supports:
|
130
130
|
|
131
|
-
| API Option
|
132
|
-
|
|
133
|
-
| `printWidth`
|
134
|
-
| `requirePragma`
|
135
|
-
| `rubyArrayLiteral`
|
136
|
-
| `rubyHashLabel`
|
137
|
-
| `rubyModifier`
|
138
|
-
| `
|
139
|
-
|
140
|
-
| `
|
141
|
-
| `
|
131
|
+
| API Option | CLI Option | Default | Description |
|
132
|
+
| ------------------- | ----------------------- | :-----: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
133
|
+
| `printWidth` | `--print-width` | `80` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#print-width)). |
|
134
|
+
| `requirePragma` | `--require-pragma` | `false` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#require-pragma)). |
|
135
|
+
| `rubyArrayLiteral` | `--ruby-array-literal` | `true` | When possible, favor the use of string and symbol array literals. |
|
136
|
+
| `rubyHashLabel` | `--ruby-hash-label` | `true` | When possible, uses the shortened hash key syntax, as opposed to hash rockets. |
|
137
|
+
| `rubyModifier` | `--ruby-modifier` | `true` | When it fits on one line, allows while and until statements to use the modifier form. |
|
138
|
+
| `rubyNetcatCommand` | `--ruby-netcat-command` | | The prefix of the command to execute to communicate between the node.js process and the Ruby process. (For example, `"nc -U"` or `"telnet -u"`) Normally you should not set this option. |
|
139
|
+
|
140
|
+
| `rubySingleQuote` | `--ruby-single-quote` | `true` | When double quotes are not necessary for interpolation, prefers the use of single quotes for string literals. |
|
141
|
+
| `rubyToProc` | `--ruby-to-proc` | `false` | When possible, convert blocks to the more concise `Symbol#to_proc` syntax. |
|
142
|
+
| `tabWidth` | `--tab-width` | `2` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#tab-width)). |
|
143
|
+
| `trailingComma` | `--trailing-comma` | `false` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#trailing-comma)). `"es5"` is equivalent to `true`. |
|
142
144
|
|
143
145
|
Any of these can be added to your existing [prettier configuration
|
144
146
|
file](https://prettier.io/docs/en/configuration.html). For example:
|
@@ -163,11 +165,20 @@ with some of RuboCop's functionality.
|
|
163
165
|
Prettier provides a RuboCop configuration file to disable the rules which clash.
|
164
166
|
To enable, add the following config at the top of your project's `.rubocop.yml`:
|
165
167
|
|
168
|
+
#### Ruby gem
|
169
|
+
|
166
170
|
```yaml
|
167
171
|
inherit_gem:
|
168
172
|
prettier: rubocop.yml
|
169
173
|
```
|
170
174
|
|
175
|
+
#### `npm` package
|
176
|
+
|
177
|
+
```yaml
|
178
|
+
inherit_from:
|
179
|
+
- node_modules/@prettier/plugin-ruby/rubocop.yml
|
180
|
+
```
|
181
|
+
|
171
182
|
## Contributing
|
172
183
|
|
173
184
|
Check out our [contributing guide](CONTRIBUTING.md). Bug reports and pull requests are welcome on GitHub at https://github.com/prettier/plugin-ruby.
|
data/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@prettier/plugin-ruby",
|
3
|
-
"version": "1.4
|
3
|
+
"version": "1.5.4",
|
4
4
|
"description": "prettier plugin for the Ruby programming language",
|
5
5
|
"main": "src/plugin.js",
|
6
6
|
"scripts": {
|
@@ -22,9 +22,9 @@
|
|
22
22
|
"prettier": ">=1.10"
|
23
23
|
},
|
24
24
|
"devDependencies": {
|
25
|
-
"eslint": "^7.
|
26
|
-
"eslint-config-prettier": "^
|
27
|
-
"husky": "^
|
25
|
+
"eslint": "^7.22.0",
|
26
|
+
"eslint-config-prettier": "^8.0.0",
|
27
|
+
"husky": "^5.0.9",
|
28
28
|
"jest": "^26.0.0",
|
29
29
|
"pretty-quick": "^3.1.0"
|
30
30
|
},
|
data/rubocop.yml
CHANGED
data/src/haml/parser.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
const parseSync = require("../parser/parseSync");
|
2
2
|
|
3
|
-
const parse = (text, _parsers,
|
4
|
-
return parseSync("haml", text);
|
3
|
+
const parse = (text, _parsers, opts) => {
|
4
|
+
return parseSync("haml", text, opts);
|
5
5
|
};
|
6
6
|
|
7
7
|
const pragmaPattern = /^\s*-#\s*@(prettier|format)/;
|
data/src/haml/parser.rb
CHANGED
data/src/parser/getNetcat.js
CHANGED
@@ -16,35 +16,42 @@ function hasCommand(name) {
|
|
16
16
|
|
17
17
|
// Finds an netcat-like adapter to use for sending data to a socket. We order
|
18
18
|
// these by likelihood of being found so we can avoid some shell-outs.
|
19
|
-
function
|
19
|
+
function getCommandAndArgs() {
|
20
20
|
if (hasCommand("nc")) {
|
21
|
-
return ["nc", "-U"];
|
21
|
+
return ["nc", ["-U"]];
|
22
22
|
}
|
23
23
|
|
24
24
|
if (hasCommand("telnet")) {
|
25
|
-
return ["telnet", "-u"];
|
25
|
+
return ["telnet", ["-u"]];
|
26
26
|
}
|
27
27
|
|
28
28
|
if (hasCommand("ncat")) {
|
29
|
-
return ["ncat", "-U"];
|
29
|
+
return ["ncat", ["-U"]];
|
30
30
|
}
|
31
31
|
|
32
32
|
if (hasCommand("socat")) {
|
33
|
-
return ["socat", "-"];
|
33
|
+
return ["socat", ["-"]];
|
34
34
|
}
|
35
35
|
|
36
|
-
return ["node", require.resolve("./netcat.js")];
|
36
|
+
return ["node", [require.resolve("./netcat.js")]];
|
37
37
|
}
|
38
38
|
|
39
39
|
let command;
|
40
|
-
let
|
40
|
+
let args;
|
41
41
|
|
42
|
-
function getNetcat() {
|
42
|
+
function getNetcat(opts) {
|
43
43
|
if (!command) {
|
44
|
-
|
44
|
+
if (opts.rubyNetcatCommand) {
|
45
|
+
const splits = opts.rubyNetcatCommand.split(" ");
|
46
|
+
|
47
|
+
command = splits[0];
|
48
|
+
args = splits.slice(1);
|
49
|
+
} else {
|
50
|
+
[command, args] = getCommandAndArgs();
|
51
|
+
}
|
45
52
|
}
|
46
53
|
|
47
|
-
return { command,
|
54
|
+
return { command, args };
|
48
55
|
}
|
49
56
|
|
50
57
|
module.exports = getNetcat;
|
data/src/parser/netcat.js
CHANGED
@@ -5,11 +5,9 @@
|
|
5
5
|
const { createConnection } = require("net");
|
6
6
|
|
7
7
|
const sock = process.argv[process.argv.length - 1];
|
8
|
-
|
9
8
|
const client = createConnection(sock, () => process.stdin.pipe(client));
|
10
9
|
|
11
10
|
client.on("data", (data) => process.stdout.write(data));
|
12
|
-
|
13
11
|
client.on("error", (error) => {
|
14
12
|
console.error(error);
|
15
13
|
});
|
data/src/parser/parseSync.js
CHANGED
@@ -4,27 +4,37 @@ const requestParse = require("./requestParse");
|
|
4
4
|
// like it) here since Prettier requires the results of `parse` to be
|
5
5
|
// synchronous and Node.js does not offer a mechanism for synchronous socket
|
6
6
|
// requests.
|
7
|
-
function parseSync(parser, source) {
|
8
|
-
const
|
7
|
+
function parseSync(parser, source, opts) {
|
8
|
+
const { stdout, stderr, status } = requestParse(parser, source, opts);
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
// We need special handling in case the user's version of nc doesn't support
|
11
|
+
// using unix sockets.
|
12
|
+
if (stderr.includes("invalid option -- U")) {
|
13
|
+
throw new Error(`
|
14
|
+
@prettier/plugin-ruby uses netcat to communicate over unix sockets between
|
15
|
+
the node.js process running prettier and an underlying Ruby process used
|
16
|
+
for parsing. Unfortunately the version of netcat that you have installed
|
17
|
+
(GNU netcat) does not support unix sockets. To solve this either uninstall
|
18
|
+
GNU netcat and use a different implementation, or change the value of the
|
19
|
+
rubyNetcatCommand option in your prettier configuration.
|
20
|
+
`);
|
21
|
+
}
|
16
22
|
|
17
|
-
|
23
|
+
// If we didn't receive anything over stdout or we have a bad exit status,
|
24
|
+
// then throw whatever we can.
|
25
|
+
if (stdout.length === 0 || (status !== null && status !== 0)) {
|
26
|
+
throw new Error(stderr || "An unknown error occurred");
|
18
27
|
}
|
19
28
|
|
20
|
-
const parsed = JSON.parse(
|
29
|
+
const parsed = JSON.parse(stdout);
|
21
30
|
|
22
31
|
if (parsed.error) {
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
32
|
+
const error = new Error(parsed.error);
|
33
|
+
if (parsed.loc) {
|
34
|
+
error.loc = parsed.loc;
|
35
|
+
}
|
36
|
+
|
37
|
+
throw error;
|
28
38
|
}
|
29
39
|
|
30
40
|
return parsed;
|
data/src/parser/requestParse.js
CHANGED
@@ -54,11 +54,11 @@ function ensureParseServer() {
|
|
54
54
|
}
|
55
55
|
|
56
56
|
// Sends a request to the parse server to parse the given content.
|
57
|
-
function requestParse(parser, source) {
|
57
|
+
function requestParse(parser, source, opts) {
|
58
58
|
ensureParseServer();
|
59
59
|
|
60
|
-
const { command,
|
61
|
-
const { stdout, stderr, status } = spawnSync(command,
|
60
|
+
const { command, args } = getNetcat(opts);
|
61
|
+
const { stdout, stderr, status } = spawnSync(command, args.concat(sockfile), {
|
62
62
|
input: `${parser}|${source}`,
|
63
63
|
maxBuffer: 15 * 1024 * 1024
|
64
64
|
});
|
data/src/parser/server.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'bundler/setup' if ENV['
|
3
|
+
require 'bundler/setup' if ENV['PLUGIN_RUBY_CI']
|
4
4
|
require 'socket'
|
5
5
|
require 'json'
|
6
6
|
|
@@ -14,7 +14,7 @@ $PROGRAM_NAME = 'prettier-ruby-parser'
|
|
14
14
|
# Make sure we trap these signals to be sure we get the quit command coming from
|
15
15
|
# the parent node process
|
16
16
|
quit = false
|
17
|
-
trap(:QUIT) { quit = true }
|
17
|
+
trap(:QUIT) { quit = true } if RUBY_PLATFORM != 'java'
|
18
18
|
trap(:INT) { quit = true }
|
19
19
|
trap(:TERM) { quit = true }
|
20
20
|
|
@@ -48,6 +48,11 @@ loop do
|
|
48
48
|
else
|
49
49
|
socket.write('{ "error": true }')
|
50
50
|
end
|
51
|
+
rescue Prettier::Parser::ParserError => error
|
52
|
+
loc = { start: { line: error.lineno, column: error.column } }
|
53
|
+
socket.write(JSON.fast_generate(error: error.message, loc: loc))
|
54
|
+
rescue StandardError => error
|
55
|
+
socket.write(JSON.fast_generate(error: error.message))
|
51
56
|
ensure
|
52
57
|
socket.close
|
53
58
|
end
|
data/src/plugin.js
CHANGED
@@ -36,6 +36,7 @@ module.exports = {
|
|
36
36
|
".rabl",
|
37
37
|
".rake",
|
38
38
|
".rb",
|
39
|
+
".rbi",
|
39
40
|
".rbuild",
|
40
41
|
".rbw",
|
41
42
|
".rbx",
|
@@ -118,6 +119,12 @@ module.exports = {
|
|
118
119
|
description:
|
119
120
|
"When it fits on one line, allows if, unless, while, and until statements to use the modifier form."
|
120
121
|
},
|
122
|
+
rubyNetcatCommand: {
|
123
|
+
type: "string",
|
124
|
+
category: "Ruby",
|
125
|
+
description:
|
126
|
+
'The prefix of the command to execute to communicate between the node.js process and the Ruby process. (For example, "nc -U" or "telnet -u") Normally you should not set this option.'
|
127
|
+
},
|
121
128
|
rubySingleQuote: {
|
122
129
|
type: "boolean",
|
123
130
|
category: "Ruby",
|
data/src/rbs/parser.js
CHANGED
@@ -4,8 +4,8 @@ const parseSync = require("../parser/parseSync");
|
|
4
4
|
// to prettier a JavaScript object that is the equivalent AST that represents
|
5
5
|
// the code stored in that string. We accomplish this by spawning a new Ruby
|
6
6
|
// process of parser.rb and reading JSON off STDOUT.
|
7
|
-
function parse(text, _parsers,
|
8
|
-
return parseSync("rbs", text);
|
7
|
+
function parse(text, _parsers, opts) {
|
8
|
+
return parseSync("rbs", text, opts);
|
9
9
|
}
|
10
10
|
|
11
11
|
const pragmaPattern = /#\s*@(prettier|format)/;
|
data/src/rbs/parser.rb
CHANGED
@@ -23,8 +23,14 @@ end
|
|
23
23
|
class RBS::Location
|
24
24
|
def to_json(*args)
|
25
25
|
{
|
26
|
-
start: {
|
27
|
-
|
26
|
+
start: {
|
27
|
+
line: start_line,
|
28
|
+
column: start_column
|
29
|
+
},
|
30
|
+
end: {
|
31
|
+
line: end_line,
|
32
|
+
column: end_column
|
33
|
+
},
|
28
34
|
start_pos: start_pos,
|
29
35
|
end_pos: end_pos
|
30
36
|
}.to_json(*args)
|
@@ -81,8 +87,6 @@ module Prettier
|
|
81
87
|
class RBSParser
|
82
88
|
def self.parse(text)
|
83
89
|
{ declarations: RBS::Parser.parse_signature(text) }
|
84
|
-
rescue StandardError
|
85
|
-
false
|
86
90
|
end
|
87
91
|
end
|
88
92
|
end
|
data/src/ruby/embed.js
CHANGED
@@ -8,7 +8,7 @@ const {
|
|
8
8
|
stripTrailingHardline
|
9
9
|
} = require("../prettier");
|
10
10
|
|
11
|
-
const {
|
11
|
+
const { literallineWithoutBreakParent } = require("../utils");
|
12
12
|
|
13
13
|
const parsers = {
|
14
14
|
css: "css",
|
@@ -24,18 +24,54 @@ const parsers = {
|
|
24
24
|
// have a test that exercises it because I'm not sure for which parser it is
|
25
25
|
// necessary, but since it's in prettier core I'm keeping it here.
|
26
26
|
/* istanbul ignore next */
|
27
|
-
|
28
|
-
mapDoc(doc, (currentDoc) =>
|
27
|
+
function replaceNewlines(doc) {
|
28
|
+
return mapDoc(doc, (currentDoc) =>
|
29
29
|
typeof currentDoc === "string" && currentDoc.includes("\n")
|
30
30
|
? concat(
|
31
31
|
currentDoc
|
32
32
|
.split(/(\n)/g)
|
33
|
-
.map((v, i) => (i % 2 === 0 ? v :
|
33
|
+
.map((v, i) => (i % 2 === 0 ? v : literallineWithoutBreakParent))
|
34
34
|
)
|
35
35
|
: currentDoc
|
36
36
|
);
|
37
|
+
}
|
37
38
|
|
38
|
-
|
39
|
+
// Returns a number that represents the minimum amount of leading whitespace
|
40
|
+
// that is present on every line in the given string. So for example if you have
|
41
|
+
// the following heredoc:
|
42
|
+
//
|
43
|
+
// <<~HERE
|
44
|
+
// my
|
45
|
+
// content
|
46
|
+
// here
|
47
|
+
// HERE
|
48
|
+
//
|
49
|
+
// then the return value of this function would be 2. If you indented every line
|
50
|
+
// of the inner content 2 more spaces then this function would return 4.
|
51
|
+
function getCommonLeadingWhitespace(content) {
|
52
|
+
const pattern = /^\s+/;
|
53
|
+
|
54
|
+
return content
|
55
|
+
.split("\n")
|
56
|
+
.slice(0, -1)
|
57
|
+
.reduce((minimum, line) => {
|
58
|
+
const matched = pattern.exec(line);
|
59
|
+
const length = matched ? matched[0].length : 0;
|
60
|
+
|
61
|
+
return minimum === null ? length : Math.min(minimum, length);
|
62
|
+
}, null);
|
63
|
+
}
|
64
|
+
|
65
|
+
// Returns a new string with the common whitespace stripped out. Effectively it
|
66
|
+
// emulates what a squiggly heredoc does in Ruby.
|
67
|
+
function stripCommonLeadingWhitespace(content) {
|
68
|
+
const lines = content.split("\n");
|
69
|
+
const minimum = getCommonLeadingWhitespace(content);
|
70
|
+
|
71
|
+
return lines.map((line) => line.slice(minimum)).join("\n");
|
72
|
+
}
|
73
|
+
|
74
|
+
function embed(path, print, textToDoc, _opts) {
|
39
75
|
const node = path.getValue();
|
40
76
|
|
41
77
|
// Currently we only support embedded formatting on heredoc nodes
|
@@ -45,6 +81,8 @@ const embed = (path, print, textToDoc, _opts) => {
|
|
45
81
|
|
46
82
|
// First, ensure that we don't have any interpolation
|
47
83
|
const { beging, body, ending } = node;
|
84
|
+
const isSquiggly = beging.body[2] === "~";
|
85
|
+
|
48
86
|
if (body.some((part) => part.type !== "@tstring_content")) {
|
49
87
|
return null;
|
50
88
|
}
|
@@ -56,24 +94,32 @@ const embed = (path, print, textToDoc, _opts) => {
|
|
56
94
|
return null;
|
57
95
|
}
|
58
96
|
|
59
|
-
// Get the content as if it were a source string
|
60
|
-
|
61
|
-
|
97
|
+
// Get the content as if it were a source string.
|
98
|
+
let content = body.map((part) => part.body).join("");
|
99
|
+
|
100
|
+
// If we're using a squiggly heredoc, then we're going to manually strip off
|
101
|
+
// the leading whitespace of each line up to the minimum leading whitespace so
|
102
|
+
// that the embedded parser can handle that for us.
|
103
|
+
if (isSquiggly) {
|
104
|
+
content = stripCommonLeadingWhitespace(content);
|
105
|
+
}
|
106
|
+
|
107
|
+
// Pass that content into the embedded parser. Get back the doc node.
|
62
108
|
const formatted = concat([
|
63
|
-
|
109
|
+
literallineWithoutBreakParent,
|
64
110
|
replaceNewlines(stripTrailingHardline(textToDoc(content, { parser })))
|
65
111
|
]);
|
66
112
|
|
67
113
|
// If we're using a squiggly heredoc, then we can properly handle indentation
|
68
114
|
// ourselves.
|
69
|
-
if (
|
115
|
+
if (isSquiggly) {
|
70
116
|
return concat([
|
71
117
|
path.call(print, "beging"),
|
72
118
|
lineSuffix(
|
73
119
|
group(
|
74
120
|
concat([
|
75
121
|
indent(markAsRoot(formatted)),
|
76
|
-
|
122
|
+
literallineWithoutBreakParent,
|
77
123
|
ending.trim()
|
78
124
|
])
|
79
125
|
)
|
@@ -86,9 +132,11 @@ const embed = (path, print, textToDoc, _opts) => {
|
|
86
132
|
return markAsRoot(
|
87
133
|
concat([
|
88
134
|
path.call(print, "beging"),
|
89
|
-
lineSuffix(
|
135
|
+
lineSuffix(
|
136
|
+
group(concat([formatted, literallineWithoutBreakParent, ending.trim()]))
|
137
|
+
)
|
90
138
|
])
|
91
139
|
);
|
92
|
-
}
|
140
|
+
}
|
93
141
|
|
94
142
|
module.exports = embed;
|