prettier 1.0.0.pre.rc1 → 1.2.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.
@@ -32,7 +32,7 @@ function isSingleQuotable(node) {
32
32
  const quotePattern = new RegExp("\\\\([\\s\\S])|(['\"])", "g");
33
33
 
34
34
  function normalizeQuotes(content, enclosingQuote, originalQuote) {
35
- const replaceOther = ["'", '"'].includes(originalQuote);
35
+ const replaceOther = originalQuote === '"';
36
36
  const otherQuote = enclosingQuote === '"' ? "'" : '"';
37
37
 
38
38
  // Escape and unescape single and double quotes as needed to be able to
@@ -3,18 +3,33 @@ const path = require("path");
3
3
 
4
4
  // In order to properly parse ruby code, we need to tell the ruby process to
5
5
  // parse using UTF-8. Unfortunately, the way that you accomplish this looks
6
- // differently depending on your platform. This object below represents all of
7
- // the possible values of process.platform per:
8
- // https://nodejs.org/api/process.html#process_process_platform
9
- const LANG = {
10
- aix: "C.UTF-8",
11
- darwin: "en_US.UTF-8",
12
- freebsd: "C.UTF-8",
13
- linux: "C.UTF-8",
14
- openbsd: "C.UTF-8",
15
- sunos: "C.UTF-8",
16
- win32: ".UTF-8"
17
- }[process.platform];
6
+ // differently depending on your platform.
7
+ const LANG = (() => {
8
+ const { env, platform } = process;
9
+ const envValue = env.LC_ALL || env.LC_CTYPE || env.LANG;
10
+
11
+ // If an env var is set for the locale that already includes UTF-8 in the
12
+ // name, then assume we can go with that.
13
+ if (envValue && envValue.includes("UTF-8")) {
14
+ return envValue;
15
+ }
16
+
17
+ // Otherwise, we're going to guess which encoding to use based on the system.
18
+ // This is probably not the best approach in the world, as you could be on
19
+ // linux and not have C.UTF-8, but in that case you're probably passing an env
20
+ // var for it. This object below represents all of the possible values of
21
+ // process.platform per:
22
+ // https://nodejs.org/api/process.html#process_process_platform
23
+ return {
24
+ aix: "C.UTF-8",
25
+ darwin: "en_US.UTF-8",
26
+ freebsd: "C.UTF-8",
27
+ linux: "C.UTF-8",
28
+ openbsd: "C.UTF-8",
29
+ sunos: "C.UTF-8",
30
+ win32: ".UTF-8"
31
+ }[platform];
32
+ })();
18
33
 
19
34
  // This function is responsible for taking an input string of text and returning
20
35
  // to prettier a JavaScript object that is the equivalent AST that represents
@@ -314,7 +314,9 @@ class Prettier::Parser < Ripper
314
314
  arg.merge(type: :args, body: [arg])
315
315
  else
316
316
  args.merge!(
317
- body: args[:body] << arg, end: arg[:end], char_end: arg[:char_end]
317
+ body: args[:body] << arg,
318
+ end: arg[:end],
319
+ char_end: arg[:char_end]
318
320
  )
319
321
  end
320
322
  end
@@ -566,8 +568,10 @@ class Prettier::Parser < Ripper
566
568
 
567
569
  # Here we're going to determine the bounds for the stmts
568
570
  consequent = parts[1..-1].compact.first
569
- self[:body][0].bind(char_start,
570
- consequent ? consequent[:char_start] : char_end)
571
+ self[:body][0].bind(
572
+ char_start,
573
+ consequent ? consequent[:char_start] : char_end
574
+ )
571
575
 
572
576
  # Next we're going to determine the rescue clause if there is one
573
577
  if parts[1]
@@ -810,18 +814,43 @@ class Prettier::Parser < Ripper
810
814
  # │ └> params
811
815
  # └> ident
812
816
  #
817
+ # You can also have single-line methods since Ruby 3.0+, which have slightly
818
+ # different syntax but still flow through this method. Those look like:
819
+ #
820
+ # def foo = bar
821
+ # | |
822
+ # | └> stmt
823
+ # └> ident
824
+ #
813
825
  def on_def(ident, params, bodystmt)
814
826
  # Make sure to delete this scanner event in case you're defining something
815
827
  # like def class which would lead to this being a kw and causing all kinds
816
828
  # of trouble
817
829
  scanner_events.delete(ident)
818
830
 
831
+ # Find the beginning of the method definition, which works for single-line
832
+ # and normal method definitions.
833
+ beging = find_scanner_event(:@kw, 'def')
834
+
835
+ # If there is not a params node, then we have a single-line method
836
+ unless params
837
+ return(
838
+ {
839
+ type: :defsl,
840
+ body: [ident, bodystmt],
841
+ start: beging[:start],
842
+ char_start: beging[:char_start],
843
+ end: bodystmt[:end],
844
+ char_end: bodystmt[:char_end]
845
+ }
846
+ )
847
+ end
848
+
819
849
  if params[:type] == :params && !params[:body].any?
820
850
  location = ident[:char_end]
821
851
  params.merge!(char_start: location, char_end: location)
822
852
  end
823
853
 
824
- beging = find_scanner_event(:@kw, 'def')
825
854
  ending = find_scanner_event(:@kw, 'end')
826
855
 
827
856
  bodystmt.bind(
@@ -1064,7 +1093,10 @@ class Prettier::Parser < Ripper
1064
1093
  # event, so here we'll initialize the current embdoc.
1065
1094
  def on_embdoc_beg(value)
1066
1095
  @embdoc = {
1067
- type: :@embdoc, value: value, start: lineno, char_start: char_pos
1096
+ type: :@embdoc,
1097
+ value: value,
1098
+ start: lineno,
1099
+ char_start: char_pos
1068
1100
  }
1069
1101
  end
1070
1102
 
@@ -1150,6 +1182,24 @@ class Prettier::Parser < Ripper
1150
1182
  }
1151
1183
  end
1152
1184
 
1185
+ # fndptn is a parser event that represents matching against a pattern where
1186
+ # you find a pattern in an array using the Ruby 3.0+ pattern matching syntax.
1187
+ def on_fndptn(const, presplat, args, postsplat)
1188
+ beging = const || find_scanner_event(:@lbracket)
1189
+ ending = find_scanner_event(:@rbracket)
1190
+
1191
+ pieces = [const, presplat, *args, postsplat].compact
1192
+
1193
+ {
1194
+ type: :fndptn,
1195
+ body: [const, presplat, args, postsplat],
1196
+ start: beging[:start],
1197
+ char_start: beging[:char_start],
1198
+ end: ending[:end],
1199
+ char_end: ending[:char_end]
1200
+ }
1201
+ end
1202
+
1153
1203
  # for is a parser event that represents using the somewhat esoteric for
1154
1204
  # loop. It accepts as arguments an ident which is the iterating variable,
1155
1205
  # an enumerable for that which is being enumerated, and a stmts event that
@@ -1181,7 +1231,8 @@ class Prettier::Parser < Ripper
1181
1231
  # Here we're going to expand out the location information for the assocs
1182
1232
  # node so that it can grab up any remaining comments inside the hash.
1183
1233
  assoclist_from_args.merge!(
1184
- char_start: beging[:char_end], char_end: ending[:char_start]
1234
+ char_start: beging[:char_end],
1235
+ char_end: ending[:char_start]
1185
1236
  )
1186
1237
  end
1187
1238
 
@@ -1211,9 +1262,12 @@ class Prettier::Parser < Ripper
1211
1262
 
1212
1263
  # Here we're going to artificially create an extra node type so that if
1213
1264
  # there are comments after the declaration of a heredoc, they get printed.
1214
- location.merge(
1215
- type: :heredoc, beging: location.merge(type: :@heredoc_beg, body: beging)
1216
- ).tap { |node| @heredocs << node }
1265
+ location
1266
+ .merge(
1267
+ type: :heredoc,
1268
+ beging: location.merge(type: :@heredoc_beg, body: beging)
1269
+ )
1270
+ .tap { |node| @heredocs << node }
1217
1271
  end
1218
1272
 
1219
1273
  # This is a parser event that occurs when you're using a heredoc with a
@@ -1440,7 +1494,9 @@ class Prettier::Parser < Ripper
1440
1494
  part.merge(type: :mlhs, body: [part])
1441
1495
  else
1442
1496
  mlhs.merge!(
1443
- body: mlhs[:body] << part, end: part[:end], char_end: part[:char_end]
1497
+ body: mlhs[:body] << part,
1498
+ end: part[:end],
1499
+ char_end: part[:char_end]
1444
1500
  )
1445
1501
  end
1446
1502
  end
@@ -1543,7 +1599,9 @@ class Prettier::Parser < Ripper
1543
1599
  part.merge(type: :mrhs, body: [part])
1544
1600
  else
1545
1601
  mrhs.merge!(
1546
- body: mrhs[:body] << part, end: part[:end], char_end: part[:char_end]
1602
+ body: mrhs[:body] << part,
1603
+ end: part[:end],
1604
+ char_end: part[:char_end]
1547
1605
  )
1548
1606
  end
1549
1607
  end
@@ -1644,7 +1702,10 @@ class Prettier::Parser < Ripper
1644
1702
  # some found at the end of the source string.
1645
1703
  def on_program(stmts)
1646
1704
  range = {
1647
- start: 1, end: lines.length, char_start: 0, char_end: source.length
1705
+ start: 1,
1706
+ end: lines.length,
1707
+ char_start: 0,
1708
+ char_end: source.length
1648
1709
  }
1649
1710
 
1650
1711
  stmts[:body] << @__end__ if @__end__
@@ -1701,7 +1762,8 @@ class Prettier::Parser < Ripper
1701
1762
  # expression literal, like /foo/. It can be followed by any number of
1702
1763
  # regexp_add events, which we'll append onto an array body.
1703
1764
  def on_regexp_new
1704
- find_scanner_event(:@regexp_beg).merge!(type: :regexp, body: [])
1765
+ beging = find_scanner_event(:@regexp_beg)
1766
+ beging.merge!(type: :regexp, body: [], beging: beging[:body])
1705
1767
  end
1706
1768
 
1707
1769
  # regexp_add is a parser event that represents a piece of a regular
@@ -1949,7 +2011,9 @@ class Prettier::Parser < Ripper
1949
2011
  # piece of the string.
1950
2012
  def on_string_add(string, piece)
1951
2013
  string.merge!(
1952
- body: string[:body] << piece, end: piece[:end], char_end: piece[:char_end]
2014
+ body: string[:body] << piece,
2015
+ end: piece[:end],
2016
+ char_end: piece[:char_end]
1953
2017
  )
1954
2018
  end
1955
2019
 
@@ -2285,7 +2349,7 @@ class Prettier::Parser < Ripper
2285
2349
  else
2286
2350
  # You can hit this pattern if you're assigning to a splat using pattern
2287
2351
  # matching syntax in Ruby 2.7+
2288
- { type: :var_field, body: [] }
2352
+ { type: :var_field, body: nil }
2289
2353
  end
2290
2354
  end
2291
2355
 
@@ -2406,7 +2470,9 @@ class Prettier::Parser < Ripper
2406
2470
  piece.merge(type: :word, body: [piece])
2407
2471
  else
2408
2472
  word.merge!(
2409
- body: word[:body] << piece, end: piece[:end], char_end: piece[:char_end]
2473
+ body: word[:body] << piece,
2474
+ end: piece[:end],
2475
+ char_end: piece[:char_end]
2410
2476
  )
2411
2477
  end
2412
2478
  end
@@ -2487,7 +2553,9 @@ class Prettier::Parser < Ripper
2487
2553
  else
2488
2554
  ending = find_scanner_event(:@tstring_end)
2489
2555
  xstring.merge!(
2490
- type: :xstring_literal, end: ending[:end], char_end: ending[:char_end]
2556
+ type: :xstring_literal,
2557
+ end: ending[:end],
2558
+ char_end: ending[:char_end]
2491
2559
  )
2492
2560
  end
2493
2561
  end
@@ -20,6 +20,18 @@ function printNode(path, opts, print) {
20
20
  throw new Error(`Unsupported node encountered: ${type}\n${ast}`);
21
21
  }
22
22
 
23
+ // This is an escape-hatch to ignore nodes in the tree. If you have a comment
24
+ // that includes this pattern, then the entire node will be ignored and just the
25
+ // original source will be printed out.
26
+ function hasPrettierIgnore(path) {
27
+ const node = path.getValue();
28
+
29
+ return (
30
+ node.comments &&
31
+ node.comments.some((comment) => comment.value.includes("prettier-ignore"))
32
+ );
33
+ }
34
+
23
35
  const noComments = [
24
36
  "args",
25
37
  "args_add_block",
@@ -83,6 +95,7 @@ function isBlockComment(comment) {
83
95
  module.exports = {
84
96
  embed,
85
97
  print: printNode,
98
+ hasPrettierIgnore,
86
99
  canAttachComment,
87
100
  getCommentChildNodes,
88
101
  printComment,
@@ -76,30 +76,37 @@ module.exports = {
76
76
  ruby: printer
77
77
  },
78
78
  options: {
79
+ rubyArrayLiteral: {
80
+ type: "boolean",
81
+ category: "Ruby",
82
+ default: true,
83
+ description:
84
+ "When possible, favor the use of string and symbol array literals."
85
+ },
79
86
  rubyHashLabel: {
80
87
  type: "boolean",
81
- category: "Global",
88
+ category: "Ruby",
82
89
  default: true,
83
90
  description:
84
91
  "When possible, uses the shortened hash key syntax, as opposed to hash rockets."
85
92
  },
86
93
  rubyModifier: {
87
94
  type: "boolean",
88
- category: "Global",
95
+ category: "Ruby",
89
96
  default: true,
90
97
  description:
91
98
  "When it fits on one line, allows if, unless, while, and until statements to use the modifier form."
92
99
  },
93
100
  rubySingleQuote: {
94
101
  type: "boolean",
95
- category: "Global",
102
+ category: "Ruby",
96
103
  default: true,
97
104
  description:
98
105
  "When double quotes are not necessary for interpolation, prefers the use of single quotes for string literals."
99
106
  },
100
107
  rubyToProc: {
101
108
  type: "boolean",
102
- category: "Global",
109
+ category: "Ruby",
103
110
  default: false,
104
111
  description:
105
112
  "When possible, convert blocks to the more concise Symbol#to_proc syntax."
@@ -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.rubyToProc) {
14
+ const toProc = (path, node) => {
15
+ if (!node) {
16
16
  return null;
17
17
  }
18
18
 
@@ -1,8 +1,7 @@
1
1
  const { concat } = require("./prettier");
2
2
  const isEmptyStmts = require("./utils/isEmptyStmts");
3
3
  const literalLineNoBreak = require("./utils/literalLineNoBreak");
4
-
5
- const concatBody = (path, opts, print) => concat(path.map(print, "body"));
4
+ const printEmptyCollection = require("./utils/printEmptyCollection");
6
5
 
7
6
  // If the node is a type of assignment or if the node is a paren and nested
8
7
  // inside that paren is a node that is a type of assignment.
@@ -79,7 +78,6 @@ const skipAssignIndent = (node) =>
79
78
  (node.type === "call" && skipAssignIndent(node.body[0]));
80
79
 
81
80
  module.exports = {
82
- concatBody,
83
81
  containsAssignment,
84
82
  docLength,
85
83
  empty,
@@ -92,5 +90,6 @@ module.exports = {
92
90
  makeCall,
93
91
  noIndent,
94
92
  prefix,
93
+ printEmptyCollection,
95
94
  skipAssignIndent
96
95
  };
@@ -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: 1.0.0.pre.rc1
4
+ version: 1.2.0
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-09 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-26 00:00:00.000000000 Z
12
+ dependencies: []
55
13
  description:
56
14
  email:
57
15
  executables:
@@ -115,6 +73,7 @@ files:
115
73
  - src/utils/inlineEnsureParens.js
116
74
  - src/utils/isEmptyStmts.js
117
75
  - src/utils/literalLineNoBreak.js
76
+ - src/utils/printEmptyCollection.js
118
77
  homepage: https://github.com/prettier/plugin-ruby#readme
119
78
  licenses:
120
79
  - MIT
@@ -130,11 +89,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
89
  version: '0'
131
90
  required_rubygems_version: !ruby/object:Gem::Requirement
132
91
  requirements:
133
- - - ">"
92
+ - - ">="
134
93
  - !ruby/object:Gem::Version
135
- version: 1.3.1
94
+ version: '0'
136
95
  requirements: []
137
- rubygems_version: 3.0.3
96
+ rubygems_version: 3.1.4
138
97
  signing_key:
139
98
  specification_version: 4
140
99
  summary: prettier plugin for the Ruby programming language