Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add declaration type in ESMExport #227

Merged
merged 4 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/analyze.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ export interface TypeImport extends Omit<ESMImport, "type"> {
export interface ESMExport {
_type?: "declaration" | "named" | "default" | "star";
type: "declaration" | "named" | "default" | "star";
declarationType?:
| "let"
| "var"
| "const"
| "enum"
| "const enum"
| "class"
| "function"
| "async function";
code: string;
start: number;
end: number;
Expand Down Expand Up @@ -305,7 +314,7 @@ export function findTypeExports(code: string): ESMExport[] {
);
}

function normalizeExports(exports: ESMExport[]) {
function normalizeExports(exports: (ESMExport & { declaration?: string })[]) {
for (const exp of exports) {
if (!exp.name && exp.names && exp.names.length === 1) {
exp.name = exp.names[0];
Expand All @@ -317,6 +326,12 @@ function normalizeExports(exports: ESMExport[]) {
if (!exp.names && exp.name) {
exp.names = [exp.name];
}
if (exp.type === "declaration") {
exp.declarationType = exp.declaration.replace(
/^declare\s*/,
"",
) as ESMExport["declarationType"];
}
}
return exports;
}
Expand Down
141 changes: 118 additions & 23 deletions test/exports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,72 +325,167 @@ describe("findTypeExports", () => {
it("finds type exports", () => {
const matches = findTypeExports(
`
export type { Foo } from "./foo";
export type { Bar } from "./bar";
interface Qux {}
export interface Qux {}

export type { Qux }
export type Bing = Qux
export type { Foo } from "./foo";
export type { Bar } from "./bar";

export declare let foo: string
export declare var bar: string
export declare const baz: string
export declare enum Qux { A, B, C }
export declare const enum Qux { A, B, C }
export declare class Foo {}
export declare function getWidget(n: number): Widget
export declare async function loadWidget(n: number): Promise<Widget>
`,
);
expect(matches).toMatchInlineSnapshot(`
[
{
"code": "export interface Qux",
"declaration": "interface",
"declarationType": "interface",
"end": 31,
"name": "Qux",
"names": [
"Qux",
],
"start": 11,
"type": "declaration",
},
{
"code": "export type Bing",
"declaration": "type",
"end": 172,
"declarationType": "type",
"end": 92,
"name": "Bing",
"names": [
"Bing",
],
"start": 156,
"start": 76,
"type": "declaration",
},
{
"code": "export declare let foo",
"declaration": "declare let",
"declarationType": "let",
"end": 220,
"name": "foo",
"names": [
"foo",
],
"start": 198,
"type": "declaration",
},
{
"code": "export declare var bar",
"declaration": "declare var",
"declarationType": "var",
"end": 261,
"name": "bar",
"names": [
"bar",
],
"start": 239,
"type": "declaration",
},
{
"code": "export declare const baz",
"declaration": "declare const",
"declarationType": "const",
"end": 304,
"name": "baz",
"names": [
"baz",
],
"start": 280,
"type": "declaration",
},
{
"code": "export declare const enum Qux",
"declaration": "declare const enum",
"declarationType": "const enum",
"end": 398,
"name": "Qux",
"names": [
"Qux",
],
"start": 369,
"type": "declaration",
},
{
"code": "export declare class Foo",
"declaration": "declare class",
"declarationType": "class",
"end": 445,
"name": "Foo",
"names": [
"Foo",
],
"start": 421,
"type": "declaration",
},
{
"code": "export declare function getWidget",
"declaration": "declare function",
"end": 222,
"declarationType": "function",
"end": 492,
"name": "getWidget",
"names": [
"getWidget",
],
"start": 189,
"start": 459,
"type": "declaration",
},
{
"code": "export declare async function loadWidget",
"declaration": "declare async function",
"declarationType": "async function",
"end": 562,
"name": "loadWidget",
"names": [
"loadWidget",
],
"start": 522,
"type": "declaration",
},
{
"code": "export type { Qux }",
"end": 65,
"exports": " Qux",
"name": "Qux",
"names": [
"Qux",
],
"specifier": undefined,
"start": 46,
"type": "named",
},
{
"code": "export type { Foo } from "./foo"",
"end": 43,
"end": 141,
"exports": " Foo",
"name": "Foo",
"names": [
"Foo",
],
"specifier": "./foo",
"start": 11,
"start": 109,
"type": "named",
},
{
"code": "export type { Bar } from "./bar"",
"end": 87,
"end": 185,
"exports": " Bar",
"name": "Bar",
"names": [
"Bar",
],
"specifier": "./bar",
"start": 55,
"type": "named",
},
{
"code": "export type { Qux }",
"end": 145,
"exports": " Qux",
"name": "Qux",
"names": [
"Qux",
],
"specifier": undefined,
"start": 126,
"start": 153,
"type": "named",
},
]
Expand Down