prettier-plugin-wolfram 0.7.10 → 0.7.11

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prettier-plugin-wolfram",
3
- "version": "0.7.10",
3
+ "version": "0.7.11",
4
4
  "description": "Prettier plugin for Wolfram Language using tree-sitter",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,6 +1,7 @@
1
1
  import { doc } from "prettier";
2
2
  import { normalizeWolframOptions } from "../options.js";
3
3
  import { sameLineCommentSeparator } from "./commentSpacing.js";
4
+ import { sourceLineGap } from "./sourceLines.js";
4
5
 
5
6
  export function joinDocsWithSpace(docs) {
6
7
  const nonEmptyDocs = docs.filter(
@@ -41,6 +42,19 @@ function hasMarkedDocumentationCommentEntry(entry, options) {
41
42
  );
42
43
  }
43
44
 
45
+ function isCommaEntry(entry) {
46
+ return entry?.node?.type === "LeafNode" && entry.node.kind === "Token`Comma";
47
+ }
48
+
49
+ function canAttachMarkedTrailingComment(previousEntry, commentEntry, options) {
50
+ return (
51
+ previousEntry &&
52
+ !isCommaEntry(previousEntry) &&
53
+ hasDocumentationCommentMarker(commentEntry, options) &&
54
+ sourceLineGap(previousEntry.node, commentEntry.node, options) === 0
55
+ );
56
+ }
57
+
44
58
  function normalizeDocumentationCommentMarker(text) {
45
59
  return String(text).replace(/^\(\*\s*<\s*/u, "(* < ");
46
60
  }
@@ -77,6 +91,30 @@ export function joinCommentDocs(comments, options) {
77
91
  return joined;
78
92
  }
79
93
 
94
+ export function withMarkedTrailingCommentDocs(entries, options) {
95
+ const result = [];
96
+
97
+ for (const entry of entries) {
98
+ const previousEntry = result[result.length - 1];
99
+ if (canAttachMarkedTrailingComment(previousEntry, entry, options)) {
100
+ previousEntry.trailingComments ??= [];
101
+ previousEntry.trailingComments.push({
102
+ node: entry.node,
103
+ doc: entry.doc,
104
+ });
105
+ previousEntry.trailingCommentDoc = joinCommentDocs(
106
+ previousEntry.trailingComments,
107
+ options,
108
+ );
109
+ continue;
110
+ }
111
+
112
+ result.push(entry);
113
+ }
114
+
115
+ return result;
116
+ }
117
+
80
118
  export function renderFlatDoc(docNode, options) {
81
119
  const rendered = doc.printer.printDocToString(docNode, {
82
120
  printWidth: 100000,
@@ -91,16 +129,17 @@ export function documentationCommentColumn(
91
129
  entries,
92
130
  options,
93
131
  suffixForEntry = () => "",
132
+ columnOffset = 0,
94
133
  ) {
95
134
  options = normalizeWolframOptions(options);
96
135
  const manual = options.wolframDocumentationCommentColumn ?? 0;
97
- if (manual > 0) return manual;
136
+ if (manual > 0) return Math.max(1, manual - columnOffset);
98
137
  if (
99
138
  entries.some((entry) =>
100
139
  hasMarkedDocumentationCommentEntry(entry, options),
101
140
  )
102
141
  ) {
103
- return options.printWidth ?? 80;
142
+ return Math.max(1, (options.printWidth ?? 80) - columnOffset);
104
143
  }
105
144
  const padding = Math.max(
106
145
  1,
@@ -1,11 +1,16 @@
1
1
  // src/translator/nodes/call.js
2
2
  import { doc } from "prettier";
3
3
  const { builders } = doc;
4
- import { isComment, isTrivia } from "./leaf.js";
4
+ import { isComment, isTrivia, stringLineIndentDepth } from "./leaf.js";
5
5
  import { alignedRuleDoc, withAlignedRuleValues } from "../ruleAlignment.js";
6
6
  import { commentBoundarySeparator } from "../commentSpacing.js";
7
+ import {
8
+ documentationCommentColumn,
9
+ withAlignedTrailingComment,
10
+ withMarkedTrailingCommentDocs,
11
+ } from "../docComments.js";
7
12
  import { normalizeWolframOptions } from "../../options.js";
8
- const { group, indent, softline, line } = builders;
13
+ const { group, indent, softline, line, hardline } = builders;
9
14
 
10
15
  const BRACKET_KINDS = new Set(["Token`OpenSquare", "Token`CloseSquare"]);
11
16
 
@@ -14,7 +19,7 @@ function isBracketToken(node) {
14
19
  }
15
20
 
16
21
  function isCommaToken(node) {
17
- return node.type === "LeafNode" && node.kind === "Token`Comma";
22
+ return node?.type === "LeafNode" && node.kind === "Token`Comma";
18
23
  }
19
24
 
20
25
  function nextContentEntry(entries, startIndex) {
@@ -154,19 +159,48 @@ function printedEntries(path, print, entries) {
154
159
  }));
155
160
  }
156
161
 
157
- function sequenceDocs(entries, options, itemKind) {
162
+ function sequenceDocs(rawEntries, options, itemKind, columnOffset = 0) {
163
+ const entries = withMarkedTrailingCommentDocs(rawEntries, options);
158
164
  const docs = [];
159
165
  const commaGap = options.wolframSpaceAfterComma ? line : softline;
160
166
  const alignmentGroupId = entries.some((entry) => entry.alignedRuleDoc)
161
167
  ? Symbol("wolfram-align-rule-values")
162
168
  : null;
169
+ for (let i = 0; i < entries.length; i++) {
170
+ if (entries[i].trailingCommentDoc) {
171
+ entries[i].trailingCommentSuffix = trailingCommentSuffix(
172
+ entries,
173
+ i,
174
+ );
175
+ }
176
+ }
177
+ const trailingCommentEntries = entries.filter(
178
+ (entry) => entry.trailingCommentDoc,
179
+ );
180
+ const trailingCommentColumn =
181
+ trailingCommentEntries.length > 0
182
+ ? documentationCommentColumn(
183
+ trailingCommentEntries,
184
+ options,
185
+ (entry) => entry.trailingCommentSuffix ?? "",
186
+ columnOffset,
187
+ )
188
+ : null;
163
189
  let previousKind = null;
164
190
 
165
191
  for (let i = 0; i < entries.length; i++) {
166
192
  const entry = entries[i];
167
193
  if (isCommaToken(entry.node)) {
168
- if (previousKind === null || previousKind === "comma") continue;
169
194
  const previousEntry = previousContentEntry(entries, i);
195
+ if (
196
+ previousEntry?.trailingCommentDoc &&
197
+ previousEntry.trailingCommentSuffix === ","
198
+ ) {
199
+ previousKind = "comma";
200
+ continue;
201
+ }
202
+
203
+ if (previousKind === null || previousKind === "comma") continue;
170
204
  const followingEntry = nextContentEntry(entries, i);
171
205
  const separator =
172
206
  followingEntry &&
@@ -192,7 +226,27 @@ function sequenceDocs(entries, options, itemKind) {
192
226
  );
193
227
  }
194
228
 
195
- docs.push(alignedRuleDoc(entry, alignmentGroupId));
229
+ const entryDoc = alignedRuleDoc(entry, alignmentGroupId);
230
+ if (entry.trailingCommentDoc) {
231
+ docs.push(
232
+ withAlignedTrailingComment(
233
+ { ...entry, doc: entryDoc },
234
+ options,
235
+ trailingCommentColumn,
236
+ entry.trailingCommentSuffix ?? "",
237
+ ),
238
+ );
239
+ if (
240
+ entry.trailingCommentSuffix === "," &&
241
+ nextContentEntry(entries, i)
242
+ ) {
243
+ docs.push(hardline);
244
+ previousKind = "comma";
245
+ continue;
246
+ }
247
+ } else {
248
+ docs.push(entryDoc);
249
+ }
196
250
  previousKind = isComment(entry.node) ? "comment" : itemKind;
197
251
  }
198
252
 
@@ -205,6 +259,14 @@ function grouped(contents, alignmentGroupId) {
205
259
  : group(contents);
206
260
  }
207
261
 
262
+ function contentColumnOffset(path, options) {
263
+ return stringLineIndentDepth(path) * (options.tabWidth ?? 2);
264
+ }
265
+
266
+ function trailingCommentSuffix(entries, index) {
267
+ return isCommaToken(entries[index + 1]?.node) ? "," : "";
268
+ }
269
+
208
270
  function printPartCall(path, options, print, node, head) {
209
271
  const partEntry = partGroupEntry(node);
210
272
  if (!partEntry) return null;
@@ -223,7 +285,12 @@ function printPartCall(path, options, print, node, head) {
223
285
 
224
286
  if (args.length === 0) return [head, "[[]]"];
225
287
 
226
- const { docs, alignmentGroupId } = sequenceDocs(entries, options, "part");
288
+ const { docs, alignmentGroupId } = sequenceDocs(
289
+ entries,
290
+ options,
291
+ "part",
292
+ contentColumnOffset(path, options),
293
+ );
227
294
  return grouped(
228
295
  [head, "[[", indent([softline, ...docs]), softline, "]]"],
229
296
  alignmentGroupId,
@@ -246,7 +313,12 @@ export function printCall(path, options, print, node) {
246
313
 
247
314
  if (args.length === 0) return [head, "[]"];
248
315
 
249
- const { docs, alignmentGroupId } = sequenceDocs(entries, options, "arg");
316
+ const { docs, alignmentGroupId } = sequenceDocs(
317
+ entries,
318
+ options,
319
+ "arg",
320
+ contentColumnOffset(path, options),
321
+ );
250
322
  const contents = [head, "[", indent([softline, ...docs]), softline, "]"];
251
323
 
252
324
  return grouped(contents, alignmentGroupId);
@@ -1,11 +1,16 @@
1
1
  // src/translator/nodes/group.js
2
2
  import { doc } from "prettier";
3
3
  const { builders } = doc;
4
- import { isComment, isTrivia } from "./leaf.js";
4
+ import { isComment, isTrivia, stringLineIndentDepth } from "./leaf.js";
5
5
  import { alignedRuleDoc, withAlignedRuleValues } from "../ruleAlignment.js";
6
6
  import { commentBoundarySeparator } from "../commentSpacing.js";
7
+ import {
8
+ documentationCommentColumn,
9
+ withAlignedTrailingComment,
10
+ withMarkedTrailingCommentDocs,
11
+ } from "../docComments.js";
7
12
  import { normalizeWolframOptions } from "../../options.js";
8
- const { group, indent, softline, line } = builders;
13
+ const { group, indent, softline, line, hardline } = builders;
9
14
 
10
15
  const GROUP_DELIMITERS = {
11
16
  GroupSquare: ["[", "]"],
@@ -32,7 +37,7 @@ function isBracketToken(node) {
32
37
  }
33
38
 
34
39
  function isCommaToken(node) {
35
- return node.type === "LeafNode" && node.kind === "Token`Comma";
40
+ return node?.type === "LeafNode" && node.kind === "Token`Comma";
36
41
  }
37
42
 
38
43
  function nextContentEntry(entries, startIndex) {
@@ -96,14 +101,25 @@ function sequenceEntries(path, print, node) {
96
101
  }, []);
97
102
  }
98
103
 
104
+ function contentColumnOffset(path, options) {
105
+ return stringLineIndentDepth(path) * (options.tabWidth ?? 2);
106
+ }
107
+
108
+ function trailingCommentSuffix(entries, index) {
109
+ return isCommaToken(entries[index + 1]?.node) ? "," : "";
110
+ }
111
+
99
112
  export function printGroup(path, options, print, node) {
100
113
  options = normalizeWolframOptions(options);
101
114
  const [open, close] = GROUP_DELIMITERS[node.kind] ?? ["{", "}"];
102
- const entries = withAlignedRuleValues(
103
- sequenceEntries(path, print, node),
104
- path,
115
+ const entries = withMarkedTrailingCommentDocs(
116
+ withAlignedRuleValues(
117
+ sequenceEntries(path, print, node),
118
+ path,
119
+ options,
120
+ print,
121
+ ),
105
122
  options,
106
- print,
107
123
  );
108
124
 
109
125
  if (entries.length === 0) return `${open}${close}`;
@@ -113,13 +129,41 @@ export function printGroup(path, options, print, node) {
113
129
  const alignmentGroupId = entries.some((entry) => entry.alignedRuleDoc)
114
130
  ? Symbol("wolfram-align-rule-values")
115
131
  : null;
132
+ for (let i = 0; i < entries.length; i++) {
133
+ if (entries[i].trailingCommentDoc) {
134
+ entries[i].trailingCommentSuffix = trailingCommentSuffix(
135
+ entries,
136
+ i,
137
+ );
138
+ }
139
+ }
140
+ const trailingCommentEntries = entries.filter(
141
+ (entry) => entry.trailingCommentDoc,
142
+ );
143
+ const trailingCommentColumn =
144
+ trailingCommentEntries.length > 0
145
+ ? documentationCommentColumn(
146
+ trailingCommentEntries,
147
+ options,
148
+ (entry) => entry.trailingCommentSuffix ?? "",
149
+ contentColumnOffset(path, options),
150
+ )
151
+ : null;
116
152
  let previousKind = null;
117
153
 
118
154
  for (let i = 0; i < entries.length; i++) {
119
155
  const entry = entries[i];
120
156
  if (isCommaToken(entry.node)) {
121
- if (previousKind === null || previousKind === "comma") continue;
122
157
  const previousEntry = previousContentEntry(entries, i);
158
+ if (
159
+ previousEntry?.trailingCommentDoc &&
160
+ previousEntry.trailingCommentSuffix === ","
161
+ ) {
162
+ previousKind = "comma";
163
+ continue;
164
+ }
165
+
166
+ if (previousKind === null || previousKind === "comma") continue;
123
167
  const followingEntry = nextContentEntry(entries, i);
124
168
  const separator =
125
169
  followingEntry &&
@@ -145,7 +189,27 @@ export function printGroup(path, options, print, node) {
145
189
  );
146
190
  }
147
191
 
148
- docs.push(alignedRuleDoc(entry, alignmentGroupId));
192
+ const entryDoc = alignedRuleDoc(entry, alignmentGroupId);
193
+ if (entry.trailingCommentDoc) {
194
+ docs.push(
195
+ withAlignedTrailingComment(
196
+ { ...entry, doc: entryDoc },
197
+ options,
198
+ trailingCommentColumn,
199
+ entry.trailingCommentSuffix ?? "",
200
+ ),
201
+ );
202
+ if (
203
+ entry.trailingCommentSuffix === "," &&
204
+ nextContentEntry(entries, i)
205
+ ) {
206
+ docs.push(hardline);
207
+ previousKind = "comma";
208
+ continue;
209
+ }
210
+ } else {
211
+ docs.push(entryDoc);
212
+ }
149
213
  previousKind = isComment(entry.node) ? "comment" : "item";
150
214
  }
151
215