Skip to content

Commit f04e498

Browse files
committed
refactor: Created parsers.ts (2)
1 parent 0cb2e89 commit f04e498

3 files changed

Lines changed: 144 additions & 140 deletions

File tree

src/parsers.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,27 @@
1-
import type { Parser } from 'prettier';
1+
import type { File } from '@babel/types';
2+
import type { Parser, ParserOptions } from 'prettier';
3+
import { parsers as prettierParsers } from 'prettier/plugins/babel.js';
24

3-
import { parser } from './parsers/index.js';
4-
import { type NodeType, PARSER_NAME } from './utils/index.js';
5+
import { convertAst, preprocess } from './parsers/index.js';
6+
import { assert } from './utils/assert.js';
7+
import { type NodeType, PARSER_NAME, PRINTER_NAME } from './utils/index.js';
8+
9+
const parser = prettierParsers['babel-ts'] as Parser<NodeType>;
10+
11+
async function parse(text: string, options: ParserOptions<NodeType>) {
12+
const { code, templates } = preprocess(text, options.filepath);
13+
14+
const ast = await parser.parse(code, options);
15+
assert('expected ast', ast);
16+
convertAst(ast as File, { parser, templates });
17+
18+
return ast;
19+
}
520

621
export const parsers: Record<string, Parser<NodeType>> = {
7-
[PARSER_NAME]: parser,
22+
[PARSER_NAME]: {
23+
...parser,
24+
astFormat: PRINTER_NAME,
25+
parse,
26+
},
827
};

src/parsers/convert-ast.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import traverse from '@babel/traverse';
2+
import type {
3+
BlockStatement,
4+
File,
5+
ObjectExpression,
6+
StaticBlock,
7+
} from '@babel/types';
8+
import type { Parser } from 'prettier';
9+
10+
import type { NodeType } from '../utils/index.js';
11+
import type { Template } from './preprocess.js';
12+
13+
type Data = {
14+
parser: Parser<NodeType>;
15+
templates: Template[];
16+
};
17+
18+
/** Converts a node into a GlimmerTemplate node */
19+
function convertNode(
20+
node: BlockStatement | ObjectExpression | StaticBlock,
21+
rawTemplate: Template,
22+
): void {
23+
node.innerComments = [];
24+
node.extra = Object.assign(node.extra ?? {}, {
25+
isGlimmerTemplate: true as const,
26+
template: rawTemplate,
27+
});
28+
}
29+
30+
function findCorrectCommentBlockIndex(
31+
comments: File['comments'],
32+
start: number,
33+
end: number,
34+
): number {
35+
if (!comments) {
36+
return -1;
37+
}
38+
39+
return comments.findIndex((comment) => {
40+
const { start: commentStart, end: commentEnd } = comment;
41+
42+
return (
43+
(commentStart === start && commentEnd === end) ||
44+
(commentStart === start + 1 && commentEnd === end - 1) ||
45+
(commentStart === start + 7 && commentEnd === end - 1)
46+
);
47+
});
48+
}
49+
50+
/** Traverses the AST and replaces the transformed template parts with other AST */
51+
export function convertAst(ast: File, data: Data): void {
52+
const { parser, templates } = data;
53+
54+
traverse(ast, {
55+
enter(path) {
56+
if (templates.length === 0) {
57+
return null;
58+
}
59+
60+
const { node } = path;
61+
62+
switch (node.type) {
63+
case 'BlockStatement':
64+
case 'ObjectExpression':
65+
case 'StaticBlock': {
66+
const [start, end] = [parser.locStart(node), parser.locEnd(node)];
67+
68+
const templateIndex = templates.findIndex((template) => {
69+
const { utf16Range } = template;
70+
71+
if (utf16Range.start === start && utf16Range.end === end) {
72+
return true;
73+
}
74+
75+
return (
76+
node.type === 'ObjectExpression' &&
77+
utf16Range.start === start - 1 &&
78+
utf16Range.end === end + 1
79+
);
80+
});
81+
82+
if (templateIndex === -1) {
83+
return null;
84+
}
85+
86+
const rawTemplate = templates.splice(templateIndex, 1)[0];
87+
88+
if (!rawTemplate) {
89+
throw new Error(
90+
'expected raw template because splice index came from findIndex',
91+
);
92+
}
93+
94+
if (ast.comments && ast.comments.length > 0) {
95+
const commentBlockIndex = findCorrectCommentBlockIndex(
96+
ast.comments,
97+
start,
98+
end,
99+
);
100+
101+
if (commentBlockIndex !== undefined && commentBlockIndex >= 0) {
102+
ast.comments.splice(commentBlockIndex, 1);
103+
}
104+
}
105+
106+
convertNode(node, rawTemplate);
107+
}
108+
}
109+
110+
return null;
111+
},
112+
});
113+
114+
if (templates.length > 0) {
115+
throw new Error(
116+
`failed to process all templates, ${templates.length} remaining`,
117+
);
118+
}
119+
}

src/parsers/index.ts

Lines changed: 2 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,2 @@
1-
import traverse from '@babel/traverse';
2-
import type {
3-
BlockStatement,
4-
File,
5-
Node,
6-
ObjectExpression,
7-
StaticBlock,
8-
} from '@babel/types';
9-
import type { Parser } from 'prettier';
10-
import { parsers as babelParsers } from 'prettier/plugins/babel.js';
11-
12-
import type { PluginOptions } from '../options.js';
13-
import { assert } from '../utils/assert.js';
14-
import { PRINTER_NAME } from '../utils/index.js';
15-
import { preprocess, type Template } from './preprocess.js';
16-
17-
const typescript = babelParsers['babel-ts'] as Parser<Node | undefined>;
18-
19-
/** Converts a node into a GlimmerTemplate node */
20-
function convertNode(
21-
node: BlockStatement | ObjectExpression | StaticBlock,
22-
rawTemplate: Template,
23-
): void {
24-
node.innerComments = [];
25-
node.extra = Object.assign(node.extra ?? {}, {
26-
isGlimmerTemplate: true as const,
27-
template: rawTemplate,
28-
});
29-
}
30-
31-
function findCorrectCommentBlockIndex(
32-
comments: File['comments'],
33-
start: number,
34-
end: number,
35-
): number {
36-
if (!comments) {
37-
return -1;
38-
}
39-
40-
return comments.findIndex((comment) => {
41-
const { start: commentStart, end: commentEnd } = comment;
42-
43-
return (
44-
(commentStart === start && commentEnd === end) ||
45-
(commentStart === start + 1 && commentEnd === end - 1) ||
46-
(commentStart === start + 7 && commentEnd === end - 1)
47-
);
48-
});
49-
}
50-
51-
/** Traverses the AST and replaces the transformed template parts with other AST */
52-
function convertAst(ast: File, templates: Template[]): void {
53-
traverse(ast, {
54-
enter(path) {
55-
if (templates.length === 0) {
56-
return null;
57-
}
58-
59-
const { node } = path;
60-
61-
switch (node.type) {
62-
case 'BlockStatement':
63-
case 'ObjectExpression':
64-
case 'StaticBlock': {
65-
const [start, end] = [
66-
typescript.locStart(node),
67-
typescript.locEnd(node),
68-
];
69-
70-
const templateIndex = templates.findIndex((template) => {
71-
const { utf16Range } = template;
72-
73-
if (utf16Range.start === start && utf16Range.end === end) {
74-
return true;
75-
}
76-
77-
return (
78-
node.type === 'ObjectExpression' &&
79-
utf16Range.start === start - 1 &&
80-
utf16Range.end === end + 1
81-
);
82-
});
83-
84-
if (templateIndex === -1) {
85-
return null;
86-
}
87-
88-
const rawTemplate = templates.splice(templateIndex, 1)[0];
89-
90-
if (!rawTemplate) {
91-
throw new Error(
92-
'expected raw template because splice index came from findIndex',
93-
);
94-
}
95-
96-
if (ast.comments && ast.comments.length > 0) {
97-
const commentBlockIndex = findCorrectCommentBlockIndex(
98-
ast.comments,
99-
start,
100-
end,
101-
);
102-
103-
if (commentBlockIndex !== undefined && commentBlockIndex >= 0) {
104-
ast.comments.splice(commentBlockIndex, 1);
105-
}
106-
}
107-
108-
convertNode(node, rawTemplate);
109-
}
110-
}
111-
112-
return null;
113-
},
114-
});
115-
116-
if (templates.length > 0) {
117-
throw new Error(
118-
`failed to process all templates, ${templates.length} remaining`,
119-
);
120-
}
121-
}
122-
123-
export const parser: Parser<Node | undefined> = {
124-
...typescript,
125-
astFormat: PRINTER_NAME,
126-
127-
async parse(code: string, options: PluginOptions): Promise<Node> {
128-
const preprocessed = preprocess(code, options.filepath);
129-
130-
const ast = await typescript.parse(preprocessed.code, options);
131-
assert('expected ast', ast);
132-
convertAst(ast as File, preprocessed.templates);
133-
134-
return ast;
135-
},
136-
};
1+
export * from './convert-ast.js';
2+
export * from './preprocess.js';

0 commit comments

Comments
 (0)