Skip to content

Commit

Permalink
fix(ast): Allow parser to apply multiple visitors to on AST
Browse files Browse the repository at this point in the history
BREAKING CHANGE: `visitor` esbuild plugin option has been renamed to `visitors`
  • Loading branch information
lgollut committed Oct 10, 2023
1 parent fd6e080 commit 408bcc9
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 18 deletions.
8 changes: 5 additions & 3 deletions packages/esbuild-plugin-ast-vue/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { resolveStyle } from './style';
import { resolveTemplate } from './template';
import { resolvePath, validateDependency } from './utils';

type ExtractNonArray<T> = T extends Array<any> ? never : T;

export interface AstParserVueOptions extends AstParserOptions {
templateOptions?: Pick<
SFCTemplateCompileOptions,
Expand All @@ -33,7 +35,7 @@ export interface AstParserVueOptions extends AstParserOptions {
| 'postcssOptions'
| 'postcssPlugins'
>;
templateVisitor: AstParserOptions['visitor'];
templateVisitor: ExtractNonArray<AstParserOptions['visitors']>;
}

validateDependency();
Expand All @@ -42,7 +44,7 @@ export function astParserVue({
templateOptions,
scriptOptions,
styleOptions,
visitor,
visitors,
templateVisitor,
}: AstParserVueOptions): Plugin {
return {
Expand Down Expand Up @@ -88,7 +90,7 @@ export function astParserVue({
});

return {
contents: parser(code, visitor),
contents: parser(code, visitors),
errors: error,
resolveDir: dirname,
loader: isTs ? 'ts' : 'js',
Expand Down
35 changes: 33 additions & 2 deletions packages/esbuild-plugin-ast/src/__tests__/parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import { parser } from '../parser';

describe('parser', () => {
const source = 'const value = 1;';

it('should return the source if no valid visitor is provided', () => {
expect(parser(source, {})).toBe(source);
expect(parser(source, {})).toContain(source);
});

it('should transform the source if visitor is a valid visitor object', () => {
Expand All @@ -26,4 +25,36 @@ describe('parser', () => {

expect(parser(source, visitor)).toMatch('const value = 2;');
});

it('should transform the source if multiple visitor are passed', () => {
const visitors: Visitor[] = [
{
enter: (node) => {
if (node.type !== 'Literal') {
return node;
}

return {
...node,
value: 2,
raw: '2',
};
},
},
{
enter: (node) => {
if (node.type !== 'Identifier') {
return node;
}

return {
...node,
name: 'expected',
};
},
},
];

expect(parser(source, visitors)).toMatch('const expected = 2;');
});
});
2 changes: 1 addition & 1 deletion packages/esbuild-plugin-ast/src/__tests__/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('astParser', () => {
const virtualPackage = 'ast-plugin';

const pluginOptions: AstParserOptions = {
visitor: {
visitors: {
enter(node) {
if (
node.type === 'CallExpression' &&
Expand Down
20 changes: 12 additions & 8 deletions packages/esbuild-plugin-ast/src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,29 @@ const isFunction = (v: unknown) =>
* Create an AST representation of the provided source and use the
* visitor object to transform it if provided
*/
export function parser(source: string, visitor: Visitor) {
if (!visitor) {
export function parser(source: string, visitors: Visitor | Visitor[]) {
if (!visitors) {
/* eslint-disable-next-line no-console */
console.warn(
'[esbuildPluginAst]: No visitor provided, the plugin will have no effect.',
);
return source;
}

if (!isFunction(visitor.enter) && !isFunction(visitor.leave)) {
return source;
}
const visitorArray = Array.isArray(visitors) ? visitors : [visitors];

const ast = Parser.parse(source, {
let ast = Parser.parse(source, {
ecmaVersion: 'latest',
sourceType: 'module',
}) as Node;

const newAst = replace(ast, visitor);
for (const visitor of visitorArray) {
if (!isFunction(visitor.enter) && !isFunction(visitor.leave)) {
continue;
}

ast = replace(ast, visitor);
}

return generate(newAst);
return generate(ast);
}
9 changes: 6 additions & 3 deletions packages/esbuild-plugin-ast/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ import type { Plugin, OnResolveArgs } from 'esbuild';

export interface AstParserOptions {
dependencies?: string[];
visitor: Visitor;
visitors: Visitor | Visitor[];
}

export function astParser({ dependencies, visitor }: AstParserOptions): Plugin {
export function astParser({
dependencies,
visitors,
}: AstParserOptions): Plugin {
return {
name: 'astParser',
setup(build) {
Expand Down Expand Up @@ -112,7 +115,7 @@ export function astParser({ dependencies, visitor }: AstParserOptions): Plugin {
const source = await readFile(args.path, 'utf-8');

return {
contents: parser(source, visitor),
contents: parser(source, visitors),
};
});
},
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.eslint.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"noEmit": true
"noEmit": true,
"types": ["@liip/esbuild-plugin-ast"]
},
"include": ["."]
}

0 comments on commit 408bcc9

Please # to comment.