@prettier/plugin-ruby
Advanced tools
Comparing version 1.5.4 to 1.5.5
@@ -9,2 +9,13 @@ # Changelog | ||
## [1.5.5] - 2021-03-25 | ||
### Changed | ||
- [#841](https://github.com/prettier/plugin-ruby/issues/841) - LoganBarnett, kddeisz - Better error messaging for when unix sockets are not supported by netcat. | ||
- [#844](https://github.com/prettier/plugin-ruby/issues/844) - andyw8, kddeisz - Ensure we ship all of the parsers with the prettier gem so that `rbprettier` can parse other languages as well. | ||
- [#847](https://github.com/prettier/plugin-ruby/issues/847) - jflinter, kddeisz - Ensure parentheses are present on union return types in RBS. | ||
- [#850](https://github.com/prettier/plugin-ruby/issues/850) - maethub, kddeisz - Ensure double quotes are used even when single quotes are requested for HAML attribute values. | ||
- [#849](https://github.com/prettier/plugin-ruby/issues/849) - indirect, kddeisz - Support HAML version <= 5.1 multi-line attributes. | ||
- [#810](https://github.com/prettier/plugin-ruby/issues/810) - valscion, kddeisz - Make it so that brace blocks containing heredocs have the correct end line so that they format subsequent statements correctly. | ||
## [1.5.4] - 2021-03-17 | ||
@@ -1097,3 +1108,4 @@ | ||
[unreleased]: https://github.com/prettier/plugin-ruby/compare/v1.5.4...HEAD | ||
[unreleased]: https://github.com/prettier/plugin-ruby/compare/v1.5.5...HEAD | ||
[1.5.5]: https://github.com/prettier/plugin-ruby/compare/v1.5.4...v1.5.5 | ||
[1.5.4]: https://github.com/prettier/plugin-ruby/compare/v1.5.3...v1.5.4 | ||
@@ -1100,0 +1112,0 @@ [1.5.3]: https://github.com/prettier/plugin-ruby/compare/v1.5.2...v1.5.3 |
{ | ||
"name": "@prettier/plugin-ruby", | ||
"version": "1.5.4", | ||
"version": "1.5.5", | ||
"description": "prettier plugin for the Ruby programming language", | ||
@@ -5,0 +5,0 @@ "main": "src/plugin.js", |
@@ -139,8 +139,7 @@ <div align="center"> | ||
| `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. | | ||
| `rubySingleQuote` | `--ruby-single-quote` | `true` | When double quotes are not necessary for interpolation, prefers the use of single quotes for string literals. | | ||
| `rubyToProc` | `--ruby-to-proc` | `false` | When possible, convert blocks to the more concise `Symbol#to_proc` syntax. | | ||
| `tabWidth` | `--tab-width` | `2` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#tab-width)). | | ||
| `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`. | | ||
| `rubySingleQuote` | `--ruby-single-quote` | `true` | When double quotes are not necessary for interpolation, prefers the use of single quotes for string literals. | | ||
| `rubyToProc` | `--ruby-to-proc` | `false` | When possible, convert blocks to the more concise `Symbol#to_proc` syntax. | | ||
| `tabWidth` | `--tab-width` | `2` | Same as in Prettier ([see prettier docs](https://prettier.io/docs/en/options.html#tab-width)). | | ||
| `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`. | | ||
Any of these can be added to your existing [prettier configuration | ||
@@ -158,3 +157,3 @@ file](https://prettier.io/docs/en/configuration.html). For example: | ||
```bash | ||
prettier --ruby-single-quote false --write '**/*' | ||
bundle exec rbprettier --ruby-single-quote false --write '**/*' | ||
``` | ||
@@ -161,0 +160,0 @@ |
@@ -39,3 +39,3 @@ const { | ||
const quote = opts.rubySingleQuote ? "'" : '"'; | ||
const quote = opts.rubySingleQuote && !value.includes("#{") ? "'" : '"'; | ||
return `${quote}${value}${quote}`; | ||
@@ -88,7 +88,32 @@ } | ||
// If we have support for multi-line attributes laid out like a regular hash, | ||
// then we print them that way here. | ||
if (opts.supportsMultiline) { | ||
return group( | ||
concat([ | ||
"{", | ||
indent(group(concat([boundary, join(concat([",", line]), parts)]))), | ||
boundary, | ||
"}" | ||
]) | ||
); | ||
} | ||
// Otherwise, if we only have one attribute, then just print it inline | ||
// regardless of how long it is. | ||
if (parts.length === 0) { | ||
return group(concat(["{", parts[0], "}"])); | ||
} | ||
// Otherwise, depending on how long the line is it will split the content into | ||
// multi-line attributes that old Haml understands. | ||
return group( | ||
concat([ | ||
"{", | ||
indent(group(concat([boundary, join(concat([",", line]), parts)]))), | ||
boundary, | ||
parts[0], | ||
",", | ||
align( | ||
opts.headerLength + 1, | ||
concat([line, join(concat([",", line]), parts.slice(1))]) | ||
), | ||
"}" | ||
@@ -99,3 +124,3 @@ ]) | ||
function getHeader(value, opts) { | ||
function getHeader(value, opts, supportsMultiline) { | ||
const { attributes } = value; | ||
@@ -136,3 +161,11 @@ const parts = []; | ||
} else { | ||
parts.push(getAttributesObject(value.dynamic_attributes.old, opts)); | ||
parts.push( | ||
getAttributesObject( | ||
value.dynamic_attributes.old, | ||
Object.assign({}, opts, { | ||
supportsMultiline, | ||
headerLength: parts.join("").length | ||
}) | ||
) | ||
); | ||
} | ||
@@ -183,4 +216,10 @@ } | ||
const { children, value } = path.getValue(); | ||
const header = getHeader(value, opts); | ||
// This is kind of a total hack in that I don't think you're really supposed | ||
// to directly use `path.stack`, but it's the easiest way to get the root node | ||
// without having to know how many levels deep we are. | ||
const { supports_multiline } = path.stack[0]; | ||
const header = getHeader(value, opts, supports_multiline); | ||
if (children.length === 0) { | ||
@@ -187,0 +226,0 @@ return header; |
@@ -1,3 +0,112 @@ | ||
const requestParse = require("./requestParse"); | ||
const { spawn, spawnSync, execSync } = require("child_process"); | ||
const { existsSync, mkdtempSync } = require("fs"); | ||
const os = require("os"); | ||
const path = require("path"); | ||
const process = require("process"); | ||
let sockfile = process.env.PRETTIER_RUBY_HOST; | ||
let netcat; | ||
// In order to properly parse ruby code, we need to tell the ruby process to | ||
// parse using UTF-8. Unfortunately, the way that you accomplish this looks | ||
// differently depending on your platform. | ||
/* istanbul ignore next */ | ||
function getLang() { | ||
const { env, platform } = process; | ||
const envValue = env.LC_ALL || env.LC_CTYPE || env.LANG; | ||
// If an env var is set for the locale that already includes UTF-8 in the | ||
// name, then assume we can go with that. | ||
if (envValue && envValue.includes("UTF-8")) { | ||
return envValue; | ||
} | ||
// Otherwise, we're going to guess which encoding to use based on the system. | ||
// This is probably not the best approach in the world, as you could be on | ||
// linux and not have C.UTF-8, but in that case you're probably passing an env | ||
// var for it. This object below represents all of the possible values of | ||
// process.platform per: | ||
// https://nodejs.org/api/process.html#process_process_platform | ||
return { | ||
aix: "C.UTF-8", | ||
darwin: "en_US.UTF-8", | ||
freebsd: "C.UTF-8", | ||
linux: "C.UTF-8", | ||
openbsd: "C.UTF-8", | ||
sunos: "C.UTF-8", | ||
win32: ".UTF-8" | ||
}[platform]; | ||
} | ||
// Spawn the parser.rb subprocess. We do this since booting Ruby is slow, and we | ||
// can re-use the parser process multiple times since it is statelesss. | ||
function spawnParseServer() { | ||
const tmpDir = mkdtempSync(path.join(os.tmpdir(), "prettier-ruby")); | ||
const tmpFile = path.join(tmpDir, `${process.pid}.sock`); | ||
const server = spawn("ruby", [path.join(__dirname, "./server.rb"), tmpFile], { | ||
env: Object.assign({}, process.env, { LANG: getLang() }), | ||
detached: true, | ||
stdio: "inherit" | ||
}); | ||
process.on("exit", () => { | ||
try { | ||
process.kill(-server.pid); | ||
} catch (e) { | ||
// ignore | ||
} | ||
}); | ||
server.unref(); | ||
const now = new Date(); | ||
// Wait for server to go live. | ||
while (!existsSync(tmpFile) && new Date() - now < 3000) { | ||
execSync("sleep 0.1"); | ||
} | ||
return tmpFile; | ||
} | ||
// Checks to see if an executable is available. | ||
function hasCommand(name) { | ||
let result; | ||
if (os.type() === "Windows_NT") { | ||
result = spawnSync("where", [name]); | ||
} else { | ||
result = spawnSync("command", ["-v", name]); | ||
} | ||
return result.status === 0; | ||
} | ||
// Finds a netcat-like adapter to use for sending data to a socket. We order | ||
// these by likelihood of being found so we can avoid some shell-outs. | ||
function findNetcat(opts) { | ||
if (opts.rubyNetcatCommand) { | ||
const splits = opts.rubyNetcatCommand.split(" "); | ||
return { command: splits[0], args: splits.slice(1) }; | ||
} | ||
if (hasCommand("nc")) { | ||
return { command: "nc", args: ["-U"] }; | ||
} | ||
if (hasCommand("telnet")) { | ||
return { command: "telnet", args: ["-u"] }; | ||
} | ||
if (hasCommand("ncat")) { | ||
return { command: "ncat", args: ["-U"] }; | ||
} | ||
if (hasCommand("socat")) { | ||
return { command: "socat", args: ["-"] }; | ||
} | ||
return { command: "node", args: [require.resolve("./netcat.js")] }; | ||
} | ||
// Formats and sends a request to the parser server. We use netcat (or something | ||
@@ -8,7 +117,25 @@ // like it) here since Prettier requires the results of `parse` to be | ||
function parseSync(parser, source, opts) { | ||
const { stdout, stderr, status } = requestParse(parser, source, opts); | ||
if (!sockfile) { | ||
sockfile = spawnParseServer(); | ||
} | ||
if (!netcat) { | ||
netcat = findNetcat(opts); | ||
} | ||
const response = spawnSync(netcat.command, netcat.args.concat(sockfile), { | ||
input: `${parser}|${source}`, | ||
maxBuffer: 15 * 1024 * 1024 | ||
}); | ||
const stdout = response.stdout.toString(); | ||
const stderr = response.stderr.toString(); | ||
const { status } = response; | ||
// We need special handling in case the user's version of nc doesn't support | ||
// using unix sockets. | ||
if (stderr.includes("invalid option -- U")) { | ||
if ( | ||
stderr.includes("invalid option -- U") || | ||
stderr.includes("Protocol not supported") | ||
) { | ||
throw new Error(` | ||
@@ -18,5 +145,5 @@ @prettier/plugin-ruby uses netcat to communicate over unix sockets between | ||
for parsing. Unfortunately the version of netcat that you have installed | ||
(GNU netcat) does not support unix sockets. To solve this either uninstall | ||
GNU netcat and use a different implementation, or change the value of the | ||
rubyNetcatCommand option in your prettier configuration. | ||
does not support unix sockets. To solve this either uninstall the version | ||
of netcat that you're using and use a different implementation, or change | ||
the value of the rubyNetcatCommand option in your prettier configuration. | ||
`); | ||
@@ -23,0 +150,0 @@ } |
@@ -150,3 +150,3 @@ const { | ||
// look like all kinds of things, listed in the case statement below. | ||
function printType(path) { | ||
function printType(path, { forceUnionParens = false } = {}) { | ||
const node = path.getValue(); | ||
@@ -177,4 +177,7 @@ | ||
const parentType = path.getParentNode().class; | ||
return parentType === "intersection" ? concat(["(", doc, ")"]) : doc; | ||
if (forceUnionParens || path.getParentNode().class === "intersection") { | ||
return concat(["(", doc, ")"]); | ||
} | ||
return doc; | ||
} | ||
@@ -520,3 +523,10 @@ case "intersection": | ||
parts.push("-> ", path.call(printType, "type", "return_type")); | ||
parts.push( | ||
"-> ", | ||
path.call( | ||
(typePath) => printType(typePath, { forceUnionParens: true }), | ||
"type", | ||
"return_type" | ||
) | ||
); | ||
@@ -523,0 +533,0 @@ return group(concat(parts)); |
@@ -61,3 +61,3 @@ const { | ||
join(concat([",", line]), path.call(print, "body", 0)), | ||
getTrailingComma(opts) && getArgParenTrailingComma(argsNode) | ||
getTrailingComma(opts) ? getArgParenTrailingComma(argsNode) : "" | ||
]) | ||
@@ -64,0 +64,0 @@ ), |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
352031
4528
2
80
206