Skip to content

Commit 06023cd

Browse files
authored
Merge pull request #299 from prettier/stricter-types
Stricter types for development
2 parents 73a5046 + ade9110 commit 06023cd

File tree

8 files changed

+228
-99
lines changed

8 files changed

+228
-99
lines changed

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
/yarn.lock
77
/LICENSE
88

9+
/src/types.ts
910
/test/fixture.xml
1011
/test/__snapshots__/*

bin/print.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ import fs from "fs";
44
import prettier from "prettier";
55

66
import plugin from "../src/plugin";
7-
import { XMLOptions } from "../src/types";
87

98
const code = fs.existsSync(process.argv[2])
109
? fs.readFileSync(process.argv[2], "utf-8")
1110
: process.argv.slice(2).join(" ").replace(/\\n/g, "\n");
1211

13-
const options: Partial<XMLOptions> = {
12+
const options = {
1413
parser: "xml",
15-
plugins: [plugin],
14+
plugins: [plugin as any as string],
1615
xmlWhitespaceSensitivity: "ignore"
1716
};
1817

src/embed.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
import { ContentCtx, ElementCstNode } from "@xml-tools/parser";
2-
import type { AstPath, Doc, ParserOptions, Printer } from "prettier";
31
import { builders, utils } from "prettier/doc";
4-
5-
import { XMLAst, XMLOptions } from "./types";
2+
import {
3+
AnyNode,
4+
ContentCtx,
5+
Doc,
6+
ElementCstNode,
7+
Embed,
8+
Options,
9+
Path
10+
} from "./types";
611

712
const {
813
dedentToRoot,
@@ -27,11 +32,11 @@ function replaceNewlines(doc: Doc) {
2732

2833
// Get the start and end element tags from the current node on the tree
2934
function getElementTags(
30-
path: AstPath<XMLAst>,
31-
opts: XMLOptions,
32-
print: (path: AstPath<XMLAst>) => Doc
35+
path: Path<ElementCstNode>,
36+
opts: Options,
37+
print: (path: Path<AnyNode>) => Doc
3338
) {
34-
const node = path.getValue() as ElementCstNode;
39+
const node = path.getValue();
3540
const { OPEN, Name, attribute, START_CLOSE, SLASH_OPEN, END_NAME, END } =
3641
node.children;
3742

@@ -55,7 +60,7 @@ function getElementTags(
5560

5661
// Get the name of the parser that is represented by the given element node,
5762
// return null if a matching parser cannot be found
58-
function getParser(node: ElementCstNode, opts: ParserOptions<XMLAst>) {
63+
function getParser(node: ElementCstNode, opts: Options) {
5964
const { Name, attribute } = node.children;
6065
const parser = Name[0].image.toLowerCase();
6166

@@ -114,7 +119,7 @@ function getSource(content: ContentCtx) {
114119
.join("");
115120
}
116121

117-
const embed: Printer<XMLAst>["embed"] = (path, print, textToDoc, opts) => {
122+
const embed: Embed = (path, print, textToDoc, opts) => {
118123
const node = path.getValue();
119124

120125
// If the node isn't an element node, then skip
@@ -138,14 +143,17 @@ const embed: Printer<XMLAst>["embed"] = (path, print, textToDoc, opts) => {
138143

139144
// Get the open and close tags of this element, then return the properly
140145
// formatted content enclosed within them
141-
const { openTag, closeTag } = getElementTags(path, opts as XMLOptions, print);
146+
const nodePath = path as Path<typeof node>;
147+
const { openTag, closeTag } = getElementTags(nodePath, opts, print);
142148

143149
return group([
144150
openTag,
145151
literalline,
146152
dedentToRoot(
147153
replaceNewlines(
148-
utils.stripTrailingHardline(textToDoc(getSource(content), { parser }))
154+
utils.stripTrailingHardline(
155+
textToDoc(getSource(content), { ...opts, parser })
156+
)
149157
)
150158
),
151159
hardline,

src/parser.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { Parser } from "prettier";
21
import { parse as xmlToolsParse } from "@xml-tools/parser";
2+
import type { Parser } from "./types";
33

44
const parser: Parser = {
55
parse(text) {
@@ -13,16 +13,10 @@ const parser: Parser = {
1313
},
1414
astFormat: "xml",
1515
locStart(node) {
16-
if (node.location) {
17-
return node.location.startOffset;
18-
}
19-
return node.startOffset;
16+
return node.location!.startOffset;
2017
},
2118
locEnd(node) {
22-
if (node.location) {
23-
return node.location.endOffset;
24-
}
25-
return node.endOffset;
19+
return node.location!.endOffset!;
2620
}
2721
};
2822

src/plugin.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import type { Plugin } from "prettier";
21
import prettier from "prettier";
32

4-
import type { XMLAst } from "./types";
3+
import type { Plugin } from "./types";
54
import parser from "./parser";
65
import printer from "./printer";
76

87
// These are the extra options defined by this plugin.
9-
const options: Plugin<XMLAst>["options"] = {
8+
const options: Plugin["options"] = {
109
xmlWhitespaceSensitivity: {
1110
type: "choice",
1211
category: "XML",
@@ -44,7 +43,7 @@ if (
4443
};
4544
}
4645

47-
const plugin: Plugin<XMLAst> = {
46+
const plugin: Plugin = {
4847
languages: [
4948
{
5049
name: "XML",

src/printer.ts

Lines changed: 51 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
1-
import type {
2-
ChardataCstNode,
3-
ContentCstNode,
4-
ReferenceCstNode
5-
} from "@xml-tools/parser";
6-
import type { IToken } from "chevrotain";
7-
import type { AstPath, Doc, Printer } from "prettier";
81
import { builders } from "prettier/doc";
9-
102
import embed from "./embed";
11-
12-
import { ContentCstNodeExt, XMLAst, XMLOptions } from "./types";
3+
import type { ContentCstNode, Doc, IToken, Path, Printer } from "./types";
134

145
const { fill, group, hardline, indent, join, line, literalline, softline } =
156
builders;
@@ -42,13 +33,20 @@ function isWhitespaceIgnorable(node: ContentCstNode) {
4233
return !CData && !reference && !hasIgnoreRanges(Comment);
4334
}
4435

45-
function printIToken(path: AstPath<XMLAst>) {
46-
const node = path.getValue() as any as IToken;
36+
type Fragment = {
37+
offset: number;
38+
printed: Doc;
39+
startLine?: number;
40+
endLine?: number;
41+
};
42+
43+
function printIToken(path: Path<IToken>): Fragment {
44+
const node = path.getValue();
4745

4846
return {
4947
offset: node.startOffset,
50-
startLine: node.startLine!,
51-
endLine: node.endLine!,
48+
startLine: node.startLine,
49+
endLine: node.endLine,
5250
printed: node.image
5351
};
5452
}
@@ -59,9 +57,9 @@ function replaceNewlinesWithLiteralLines(content: string) {
5957
.map((value, idx) => (idx % 2 === 0 ? value : literalline));
6058
}
6159

62-
const printer: Printer<XMLAst> = {
60+
const printer: Printer = {
6361
embed,
64-
print(path, opts: XMLOptions, print) {
62+
print(path, opts, print) {
6563
const node = path.getValue();
6664

6765
switch (node.name) {
@@ -79,22 +77,25 @@ const printer: Printer<XMLAst> = {
7977
.map((value, index) => (index % 2 === 0 ? value : literalline));
8078
}
8179
case "content": {
82-
let fragments = path.call((childrenPath) => {
83-
let response: { offset: number; printed: Doc }[] = [];
84-
const children =
85-
childrenPath.getValue() as any as ContentCstNodeExt["children"];
80+
const nodePath = path as Path<typeof node>;
81+
82+
let fragments = nodePath.call((childrenPath) => {
83+
let response: Fragment[] = [];
84+
const children = childrenPath.getValue();
8685

8786
if (children.CData) {
88-
response = response.concat(path.map(printIToken, "CData"));
87+
response = response.concat(childrenPath.map(printIToken, "CData"));
8988
}
9089

9190
if (children.Comment) {
92-
response = response.concat(path.map(printIToken, "Comment"));
91+
response = response.concat(
92+
childrenPath.map(printIToken, "Comment")
93+
);
9394
}
9495

9596
if (children.chardata) {
9697
response = response.concat(
97-
path.map(
98+
childrenPath.map(
9899
(charDataPath) => ({
99100
offset: charDataPath.getValue().location!.startOffset,
100101
printed: print(charDataPath)
@@ -106,7 +107,7 @@ const printer: Printer<XMLAst> = {
106107

107108
if (children.element) {
108109
response = response.concat(
109-
path.map(
110+
childrenPath.map(
110111
(elementPath) => ({
111112
offset: elementPath.getValue().location!.startOffset,
112113
printed: print(elementPath)
@@ -118,15 +119,14 @@ const printer: Printer<XMLAst> = {
118119

119120
if (children.PROCESSING_INSTRUCTION) {
120121
response = response.concat(
121-
path.map(printIToken, "PROCESSING_INSTRUCTION")
122+
childrenPath.map(printIToken, "PROCESSING_INSTRUCTION")
122123
);
123124
}
124125

125126
if (children.reference) {
126127
response = response.concat(
127-
path.map((referencePath) => {
128-
const referenceNode =
129-
referencePath.getValue() as any as ReferenceCstNode;
128+
childrenPath.map((referencePath) => {
129+
const referenceNode = referencePath.getValue();
130130

131131
return {
132132
offset: referenceNode.location!.startOffset,
@@ -199,17 +199,17 @@ const printer: Printer<XMLAst> = {
199199
}
200200
case "document": {
201201
const { docTypeDecl, element, misc, prolog } = node.children;
202-
const parts: { offset: number; printed: Doc }[] = [];
202+
const fragments: Fragment[] = [];
203203

204204
if (docTypeDecl) {
205-
parts.push({
205+
fragments.push({
206206
offset: docTypeDecl[0].location!.startOffset,
207207
printed: path.call(print, "children", "docTypeDecl", 0)
208208
});
209209
}
210210

211211
if (prolog) {
212-
parts.push({
212+
fragments.push({
213213
offset: prolog[0].location!.startOffset,
214214
printed: path.call(print, "children", "prolog", 0)
215215
});
@@ -218,12 +218,12 @@ const printer: Printer<XMLAst> = {
218218
if (misc) {
219219
misc.forEach((node) => {
220220
if (node.children.PROCESSING_INSTRUCTION) {
221-
parts.push({
221+
fragments.push({
222222
offset: node.location!.startOffset,
223223
printed: node.children.PROCESSING_INSTRUCTION[0].image
224224
});
225225
} else if (node.children.Comment) {
226-
parts.push({
226+
fragments.push({
227227
offset: node.location!.startOffset,
228228
printed: node.children.Comment[0].image
229229
});
@@ -232,18 +232,18 @@ const printer: Printer<XMLAst> = {
232232
}
233233

234234
if (element) {
235-
parts.push({
235+
fragments.push({
236236
offset: element[0].location!.startOffset,
237237
printed: path.call(print, "children", "element", 0)
238238
});
239239
}
240240

241-
parts.sort((left, right) => left.offset - right.offset);
241+
fragments.sort((left, right) => left.offset - right.offset);
242242

243243
return [
244244
join(
245245
hardline,
246-
parts.map(({ printed }) => printed)
246+
fragments.map(({ printed }) => printed)
247247
),
248248
hardline
249249
];
@@ -297,24 +297,22 @@ const printer: Printer<XMLAst> = {
297297
opts.xmlWhitespaceSensitivity === "ignore" &&
298298
isWhitespaceIgnorable(content[0])
299299
) {
300-
const fragments = path.call(
300+
const nodePath = path as Path<typeof node>;
301+
302+
const fragments = nodePath.call(
301303
(childrenPath) => {
302-
const children =
303-
childrenPath.getValue() as any as ContentCstNodeExt["children"];
304-
let response: {
305-
offset: number;
306-
startLine: number;
307-
endLine: number;
308-
printed: Doc;
309-
}[] = [];
304+
const children = childrenPath.getValue();
305+
let response: Fragment[] = [];
310306

311307
if (children.Comment) {
312-
response = response.concat(path.map(printIToken, "Comment"));
308+
response = response.concat(
309+
childrenPath.map(printIToken, "Comment")
310+
);
313311
}
314312

315313
if (children.chardata) {
316-
path.each((charDataPath) => {
317-
const chardata = charDataPath.getValue() as ChardataCstNode;
314+
childrenPath.each((charDataPath) => {
315+
const chardata = charDataPath.getValue();
318316
if (!chardata.children.TEXT) {
319317
return;
320318
}
@@ -348,7 +346,7 @@ const printer: Printer<XMLAst> = {
348346

349347
if (children.element) {
350348
response = response.concat(
351-
path.map((elementPath) => {
349+
childrenPath.map((elementPath) => {
352350
const location = elementPath.getValue().location!;
353351

354352
return {
@@ -363,7 +361,7 @@ const printer: Printer<XMLAst> = {
363361

364362
if (children.PROCESSING_INSTRUCTION) {
365363
response = response.concat(
366-
path.map(printIToken, "PROCESSING_INSTRUCTION")
364+
childrenPath.map(printIToken, "PROCESSING_INSTRUCTION")
367365
);
368366
}
369367

@@ -398,17 +396,17 @@ const printer: Printer<XMLAst> = {
398396
}
399397

400398
const docs: Doc[] = [];
401-
let lastLine: number = fragments[0].startLine;
399+
let lastLine: number = fragments[0].startLine!;
402400

403401
fragments.forEach((node) => {
404-
if (node.startLine - lastLine >= 2) {
402+
if (node.startLine! - lastLine >= 2) {
405403
docs.push(hardline, hardline);
406404
} else {
407405
docs.push(hardline);
408406
}
409407

410408
docs.push(node.printed);
411-
lastLine = node.endLine;
409+
lastLine = node.endLine!;
412410
});
413411

414412
return group([openTag, indent(docs), hardline, closeTag]);

0 commit comments

Comments
 (0)