Skip to content

Commit

Permalink
feature(type-compiler): support literal expression directives like "u…
Browse files Browse the repository at this point in the history
…se strict", "use client"

This makes sure that the first literal expression is kept at the very top
  • Loading branch information
marcj committed Oct 16, 2023
1 parent 9f86e68 commit b234d8a
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
32 changes: 21 additions & 11 deletions packages/type-compiler/src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ import type {
TypeReferenceNode,
UnionTypeNode,
} from 'typescript';
import ts from 'typescript';
import ts, { isExpressionStatement } from 'typescript';

import {
ensureImportIsEmitted,
Expand Down Expand Up @@ -932,6 +932,8 @@ export class ReflectionTransformer implements CustomTransformer {
};
this.sourceFile = visitNode(this.sourceFile, visitor);

const newTopStatements: Statement[] = [];

while (true) {
let allCompiled = true;
for (const d of this.compileDeclarations.values()) {
Expand All @@ -948,16 +950,14 @@ export class ReflectionTransformer implements CustomTransformer {
}

if (this.embedDeclarations.size) {
const embedded: Statement[] = [];
for (const node of this.embedDeclarations.keys()) {
this.compiledDeclarations.add(node);
}
const entries = Array.from(this.embedDeclarations.entries());
this.embedDeclarations.clear();
for (const [node, d] of entries) {
embedded.push(...this.createProgramVarFromNode(node, d.name, d.sourceFile));
newTopStatements.push(...this.createProgramVarFromNode(node, d.name, d.sourceFile));
}
this.sourceFile = this.f.updateSourceFile(this.sourceFile, [...embedded, ...this.sourceFile.statements]);
}
}

Expand All @@ -981,7 +981,6 @@ export class ReflectionTransformer implements CustomTransformer {
};
this.sourceFile = visitNode(this.sourceFile, compileDeclarations);

const embedTopExpression: Statement[] = [];
if (this.addImports.length) {
const compilerOptions = this.compilerOptions;
const handledIdentifier: string[] = [];
Expand All @@ -1001,7 +1000,7 @@ export class ReflectionTransformer implements CustomTransformer {
'@ts-ignore',
true,
);
embedTopExpression.push(typeDeclWithComment);
newTopStatements.push(typeDeclWithComment);
} else {
//import {identifier} from './bar.js'
// import { identifier as identifier } is used to avoid automatic elision of imports (in angular builds for example)
Expand All @@ -1017,7 +1016,7 @@ export class ReflectionTransformer implements CustomTransformer {
'@ts-ignore',
true,
);
embedTopExpression.push(typeDeclWithComment);
newTopStatements.push(typeDeclWithComment);
}
}
}
Expand Down Expand Up @@ -1062,11 +1061,11 @@ export class ReflectionTransformer implements CustomTransformer {
true
)
);
embedTopExpression.push(assignType);
newTopStatements.push(assignType);
}

if (this.tempResultIdentifier) {
embedTopExpression.push(
newTopStatements.push(
this.f.createVariableStatement(
undefined,
this.f.createVariableDeclarationList(
Expand All @@ -1082,8 +1081,19 @@ export class ReflectionTransformer implements CustomTransformer {
);
}

if (embedTopExpression.length) {
this.sourceFile = this.f.updateSourceFile(this.sourceFile, [...embedTopExpression, ...this.sourceFile.statements]);
if (newTopStatements.length) {
// we want to keep "use strict", or "use client", etc at the very top
const indexOfFirstLiteralExpression = this.sourceFile.statements.findIndex(v => isExpressionStatement(v) && isStringLiteral(v.expression));

const newStatements = indexOfFirstLiteralExpression === -1
? [...newTopStatements, ...this.sourceFile.statements]
: [
...this.sourceFile.statements.slice(0, indexOfFirstLiteralExpression + 1),
...newTopStatements,
...this.sourceFile.statements.slice(indexOfFirstLiteralExpression + 1),
];
this.sourceFile = this.f.updateSourceFile(this.sourceFile, newStatements);
// this.sourceFile = this.f.updateSourceFile(this.sourceFile, [...newTopStatements, ...this.sourceFile.statements]);
}

// console.log('transform sourceFile', this.sourceFile.fileName);
Expand Down
10 changes: 10 additions & 0 deletions packages/type-compiler/tests/transpile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,3 +437,13 @@ test('keyof this expression', () => {
});
console.log(res);
});

test('keep "use x" at top', () => {
const res = transpile({
'app': `
"use client";
const a = (a: string) => {};
`
});
expect(res.app.startsWith('"use client";')).toBe(true);
});

0 comments on commit b234d8a

Please sign in to comment.