Skip to content

Commit 8544c1d

Browse files
authored
Merge pull request #29 from gitKrystan/unhack-babel
Remove babel hacks
2 parents 1fbaf12 + ca1b026 commit 8544c1d

9 files changed

Lines changed: 144 additions & 219 deletions

File tree

src/config.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,3 @@ export const TEMPLATE_TAG_PLACEHOLDER = util.TEMPLATE_TAG_PLACEHOLDER as string;
1111

1212
export const TEMPLATE_TAG_OPEN = `<${TEMPLATE_TAG_NAME}>`;
1313
export const TEMPLATE_TAG_CLOSE = `</${TEMPLATE_TAG_NAME}>`;
14-
15-
export const GLIMMER_EXPRESSION_TYPE = 'GlimmerExpression';

src/parse.ts

Lines changed: 47 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
1+
import type { NodePath } from '@babel/core';
12
import { traverse } from '@babel/core';
23
import type { Node } from '@babel/types';
34
import {
45
isBinaryExpression,
56
isMemberExpression,
67
isTaggedTemplateExpression,
78
} from '@babel/types';
8-
// @ts-expect-error FIXME: TS7016 Is this a hack? IDK!
9-
import { defineAliasedType } from '@babel/types/lib/definitions/utils';
109
import { getTemplateLocals } from '@glimmer/syntax';
1110
import { preprocessEmbeddedTemplates } from 'ember-template-imports/lib/preprocess-embedded-templates';
1211
import type { Parser } from 'prettier';
1312
import { parsers as babelParsers } from 'prettier/parser-babel';
1413

1514
import {
16-
GLIMMER_EXPRESSION_TYPE,
1715
PRINTER_NAME,
1816
TEMPLATE_TAG_NAME,
1917
TEMPLATE_TAG_PLACEHOLDER,
2018
} from './config';
2119
import type { Options } from './options';
2220
import { definePrinter } from './print/index';
2321
import type { BaseNode } from './types/ast';
24-
import { extractGlimmerExpression } from './types/glimmer';
2522
import {
2623
hasGlimmerArrayExpression,
2724
isRawGlimmerArrayExpression,
@@ -33,11 +30,6 @@ import { assert } from './utils/index';
3330

3431
const typescript = babelParsers['babel-ts'] as Parser<BaseNode>;
3532

36-
// FIXME: This is necessary for babel to not freak out with the custom type.
37-
// If we keep this code long-term we should augment the babel types
38-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
39-
const defineType = defineAliasedType('Glimmer');
40-
4133
const preprocess: Required<Parser<BaseNode>>['preprocess'] = (
4234
text,
4335
options
@@ -73,81 +65,58 @@ export const parser: Parser<BaseNode> = {
7365
options: Options
7466
): BaseNode {
7567
const ast = typescript.parse(text, parsers, options);
76-
// FIXME: This is necessary for babel to not freak out with the custom type.
77-
// If we keep this code long-term we should augment the babel types
78-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
79-
defineType(GLIMMER_EXPRESSION_TYPE, {
80-
inherits: 'TemplateExpression',
81-
aliases: ['Expression'],
82-
});
8368
traverse(ast as Node, {
84-
enter(path) {
85-
const node = path.node;
86-
const parentNode = path.parentPath?.node;
87-
88-
if (
89-
parentNode &&
90-
'property' in parentNode &&
91-
isRawGlimmerCallExpression(parentNode.property)
92-
) {
93-
throw new SyntaxError(
94-
'Ember <template> tag used as an object property.'
95-
);
96-
} else if (
97-
isBinaryExpression(node) &&
98-
(hasGlimmerArrayExpression(node.left) ||
99-
hasGlimmerArrayExpression(node.right))
100-
) {
101-
throw new SyntaxError(
102-
'Ember <template> tag used in binary expression.'
103-
);
104-
} else if (
105-
isTaggedTemplateExpression(node) &&
106-
hasGlimmerArrayExpression(node.tag)
107-
) {
108-
throw new SyntaxError(
109-
'Ember <template> tag used as tagged template expression.'
110-
);
111-
} else if (
112-
isMemberExpression(node) &&
113-
hasGlimmerArrayExpression(node.object)
114-
) {
115-
throw new SyntaxError(
116-
'Ember <template> tag used as member expression.'
117-
);
118-
}
119-
},
120-
ArrayExpression(path) {
121-
const node = path.node;
122-
if (isRawGlimmerArrayExpression(node)) {
123-
const newNode = extractGlimmerExpression(
124-
node.elements[0].arguments[0],
125-
node,
126-
hasAmbiguousNextLine(path, options)
127-
);
128-
// HACK: Babel types don't allow this
129-
path.replaceWith(newNode as unknown as Node);
130-
}
131-
},
132-
ClassProperty(path) {
133-
const node = path.node;
134-
if (isRawGlimmerClassProperty(node)) {
135-
const newNode = extractGlimmerExpression(node.key.arguments[0], node);
136-
// HACK: Babel types don't allow this
137-
path.replaceWith(newNode as unknown as Node);
138-
}
139-
},
140-
CallExpression(path) {
141-
const node = path.node;
142-
if (isRawGlimmerCallExpression(node)) {
143-
throw new SyntaxError('Found unhandled RawGlimmerCallExpression');
144-
}
145-
},
69+
enter: makeEnter(options),
14670
});
14771
return ast;
14872
},
14973
};
15074

75+
function makeEnter(options: Options) {
76+
return (path: NodePath) => {
77+
const node = path.node;
78+
const parentNode = path.parentPath?.node;
79+
80+
if (
81+
parentNode &&
82+
'property' in parentNode &&
83+
isRawGlimmerCallExpression(parentNode.property)
84+
) {
85+
throw new SyntaxError('Ember <template> tag used as an object property.');
86+
} else if (
87+
isBinaryExpression(node) &&
88+
(hasGlimmerArrayExpression(node.left) ||
89+
hasGlimmerArrayExpression(node.right))
90+
) {
91+
throw new SyntaxError('Ember <template> tag used in binary expression.');
92+
} else if (
93+
isTaggedTemplateExpression(node) &&
94+
hasGlimmerArrayExpression(node.tag)
95+
) {
96+
throw new SyntaxError(
97+
'Ember <template> tag used as tagged template expression.'
98+
);
99+
} else if (
100+
isMemberExpression(node) &&
101+
hasGlimmerArrayExpression(node.object)
102+
) {
103+
throw new SyntaxError('Ember <template> tag used as member expression.');
104+
}
105+
106+
if (isRawGlimmerArrayExpression(node) || isRawGlimmerClassProperty(node)) {
107+
const extra = {
108+
hasGlimmerExpression: true,
109+
forceSemi: hasAmbiguousNextLine(path, options),
110+
};
111+
if (typeof node.extra === 'object') {
112+
node.extra = { ...node.extra, ...extra };
113+
} else {
114+
node.extra = extra;
115+
}
116+
}
117+
};
118+
}
119+
151120
/**
152121
* Desugar template tag default exports because they parse as
153122
* ExpressionStatement, which has a bunch of irrelevant custom semicolon

src/print/index.ts

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@ import {
1111
getGlimmerExpression,
1212
isGlimmerExportDefaultDeclarationPath,
1313
isGlimmerExportDefaultDeclarationTSPath,
14-
isGlimmerExpressionPath,
1514
isGlimmerExpressionStatementPath,
1615
isGlimmerExpressionStatementTSPath,
1716
} from '../types/glimmer';
1817
import {
19-
isRawGlimmerArrayExpressionPath,
20-
isRawGlimmerClassPropertyPath,
18+
isGlimmerArrayExpressionPath,
19+
isGlimmerClassPropertyPath,
2120
} from '../types/raw';
2221
import { assert, assertExists } from '../utils/index';
2322
import { printTemplateTag } from './template';
@@ -117,25 +116,14 @@ export function definePrinter(options: Options): void {
117116
defaultHasPrettierIgnore
118117
);
119118

120-
if (isGlimmerExpressionPath(path)) {
121-
return printTemplateTag(
122-
path.getValue(),
123-
textToDoc,
124-
embedOptions,
125-
hasPrettierIgnore
126-
);
127-
} else if (isRawGlimmerClassPropertyPath(path)) {
128-
// FIXME: Should we throw in DEBUG mode?
129-
console.error('Found untagged GlimmerClassProperty', path.getValue());
119+
if (isGlimmerClassPropertyPath(path)) {
130120
return printTemplateTag(
131121
path.getValue().key.arguments[0],
132122
textToDoc,
133123
embedOptions,
134124
hasPrettierIgnore
135125
);
136-
} else if (isRawGlimmerArrayExpressionPath(path)) {
137-
// FIXME: Should we throw in DEBUG mode?
138-
console.error('Found untagged GlimmerArrayExpression', path.getValue());
126+
} else if (isGlimmerArrayExpressionPath(path)) {
139127
return printTemplateTag(
140128
path.getValue().elements[0].arguments[0],
141129
textToDoc,

src/print/template.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,17 @@ import { TEMPLATE_TAG_CLOSE, TEMPLATE_TAG_OPEN } from '../config';
66
import type { Options } from '../options';
77
import { getTemplateSingleQuote } from '../options';
88
import type { BaseNode } from '../types/ast';
9-
import type { GlimmerExpression } from '../types/glimmer';
109

1110
const {
1211
builders: { group, indent, softline },
1312
} = doc;
1413

1514
/**
16-
* Returns a Prettier `Doc` for the given `TemplateLiteral | GlimmerExpression`
17-
* that is formatted using Prettier's built-in glimmer parser.
15+
* Returns a Prettier `Doc` for the given `TemplateLiteral` that is formatted
16+
* using Prettier's built-in glimmer parser.
1817
*/
1918
export function printTemplateTag(
20-
node: TemplateLiteral | GlimmerExpression,
19+
node: TemplateLiteral,
2120
textToDoc: (
2221
text: string,
2322
// Don't use our `Options` here even though technically they are available
@@ -35,7 +34,6 @@ export function printTemplateTag(
3534
.map((quasi) => quasi.value.raw)
3635
.join()}${TEMPLATE_TAG_CLOSE}`;
3736
} else {
38-
// FIXME: Maybe could just concat tags before parse and allow glimmer printer to format it
3937
const contents = textToDoc(text.trim(), {
4038
...options,
4139
parser: 'glimmer',

src/types/ast.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import type { Comment, Node, SourceLocation } from '@babel/types';
22

3-
import type { GLIMMER_EXPRESSION_TYPE } from '../config';
4-
53
export interface BaseNode {
6-
type: Node['type'] | typeof GLIMMER_EXPRESSION_TYPE;
4+
type: Node['type'];
75
leadingComments?: Comment[] | null;
86
innerComments?: Comment[] | null;
97
trailingComments?: Comment[] | null;

0 commit comments

Comments
 (0)