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(vue-script-setup-converter): Remove defineComponent from import declaration #53

Merged
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`snapshot > defineNuxtComponent 1`] = `
"import { defineNuxtComponent, useNuxtApp } from '#imports';
"import { useNuxtApp } from '#imports';
definePageMeta({
name: 'HelloWorld', layout: 'test-layout', middleware: 'test-middleware'
});
Expand All @@ -15,7 +15,7 @@ const onSubmit = () => {
`;

exports[`snapshot > lang=js 1`] = `
"import { defineComponent, toRefs, computed, ref } from 'vue';
"import { toRefs, computed, ref } from 'vue';
const props = defineProps({
msg: {
type: String,
Expand All @@ -35,7 +35,7 @@ const count = ref(0);
`;

exports[`snapshot > lang=ts 1`] = `
"import { defineComponent, toRefs, computed, ref } from 'vue';
"import { toRefs, computed, ref } from 'vue';
type Props = {
msg?: string;
foo: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export default defineComponent({
</script>`);
expect(output).toMatchInlineSnapshot(
`
"import { defineComponent, toRefs, computed } from 'vue';
"import { toRefs, computed } from 'vue';
type Props = { msg?: string; }; const props = withDefaults(defineProps<Props>(), { msg: 'HelloWorld' });

const { msg } = toRefs(props);
Expand Down Expand Up @@ -157,7 +157,7 @@ export default defineComponent({
expect(output).toMatchInlineSnapshot(
`
"import type { PropType } from 'vue';
import { defineComponent, computed } from 'vue';
import { computed } from 'vue';
type Props = { msg?: string; }; const props = withDefaults(defineProps<Props>(), { msg: 'HelloWorld' });

const newMsg = computed(() => props.msg + '- HelloWorld');
Expand Down
16 changes: 15 additions & 1 deletion packages/vue-script-setup-converter/src/lib/convertSrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import {
} from "ts-morph";
import { parse } from "@vue/compiler-sfc";
import { getNodeByKind } from "./helper";
import {
hasNamedImportIdentifier,
removeNamedImportIdentifier,
} from "./helpers/module";
import { convertPageMeta } from "./converter/pageMetaConverter";
import { convertProps } from "./converter/propsConverter";
import { convertSetup } from "./converter/setupConverter";
Expand Down Expand Up @@ -52,7 +56,17 @@ export const convertSrc = (input: string) => {
sourceFile
.getStatements()
.filter((state) => !Node.isExportAssignment(state))
.map((x) => x.getText())
.map((x) => {
if (x.isKind(SyntaxKind.ImportDeclaration)) {
if (hasNamedImportIdentifier(x, "defineComponent")) {
removeNamedImportIdentifier(x, "defineComponent");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be better to extract only the ImportDeclaration and insert it later.
(I don't want to rewrite the original sorce.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I don't want to rewrite the original sorce.)

Pros.

I thought so too, but chose to rewrite the original once, because no real harm would come from rewriting the original at this time, and because duplicating the importDeclaration would have been somewhat tedious.

However, on second thought, I decided that it could be a breeding ground for bugs in the future, so I will fix it.

😺

}
if (hasNamedImportIdentifier(x, "defineNuxtComponent")) {
removeNamedImportIdentifier(x, "defineNuxtComponent");
}
}
return x.getText();
})
);

if (isDefineNuxtComponent(callexpression)) {
Expand Down
1 change: 1 addition & 0 deletions packages/vue-script-setup-converter/src/lib/helper.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// TODO: Move to helpers/node.ts
Copy link
Contributor Author

@inouetakuya inouetakuya May 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will handle this in another Pull Request 🙏

import { SyntaxKind, Node, PropertyAssignment, CallExpression } from "ts-morph";

export const getNodeByKind = (
Expand Down
90 changes: 90 additions & 0 deletions packages/vue-script-setup-converter/src/lib/helpers/module.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { expect, describe, it } from "vitest";
import { ScriptTarget, Project, ImportDeclaration } from "ts-morph";
import { parse } from "@vue/compiler-sfc";
import {
hasNamedImportIdentifier,
removeNamedImportIdentifier,
} from "./module";

const getSourceFile = (input: string, lang: "js" | "ts" = "js") => {
const {
descriptor: { script },
} = parse(input);

const project = new Project({
tsConfigFilePath: "tsconfig.json",
compilerOptions: {
target: ScriptTarget.Latest,
},
});

return project.createSourceFile("s.tsx", script?.content ?? "");
};

describe("helpers/module", () => {
describe("hasNamedImportIdentifier", () => {
describe("when importDeclaration includes target namedImport", () => {
const source = `<script>import { defineComponent, ref } from 'vue';</script>`;

it("returns true", () => {
const sourceFile = getSourceFile(source);
const importDeclaration = sourceFile.getImportDeclaration("vue");
const result = hasNamedImportIdentifier(
importDeclaration as ImportDeclaration,
"defineComponent"
);

expect(result).toBe(true);
});
});

describe("when importDeclaration does not include target namedImport", () => {
const source = `<script>import { ref } from 'vue';</script>`;

it("returns true", () => {
const sourceFile = getSourceFile(source);
const importDeclaration = sourceFile.getImportDeclaration("vue");
const result = hasNamedImportIdentifier(
importDeclaration as ImportDeclaration,
"defineComponent"
);

expect(result).toBe(false);
});
});
});

describe("removeNamedImportIdentifier", () => {
describe("when importDeclaration includes target namedImport", () => {
const source = `<script>import { defineComponent, ref } from 'vue';</script>`;

it("removes namedImport from importDeclaration", () => {
const sourceFile = getSourceFile(source);
const importDeclaration = sourceFile.getImportDeclaration("vue");

if (!importDeclaration)
throw new Error("importDeclaration is not found.");

removeNamedImportIdentifier(importDeclaration, "defineComponent");

expect(importDeclaration.getText()).toBe("import { ref } from 'vue';");
});
});

describe("when importDeclaration does not include target namedImport", () => {
const source = `<script>import { ref } from 'vue';</script>`;

it("makes no change to importDeclaration", () => {
const sourceFile = getSourceFile(source);
const importDeclaration = sourceFile.getImportDeclaration("vue");

if (!importDeclaration)
throw new Error("importDeclaration is not found.");

removeNamedImportIdentifier(importDeclaration, "defineComponent");

expect(importDeclaration.getText()).toBe("import { ref } from 'vue';");
});
});
});
});
24 changes: 24 additions & 0 deletions packages/vue-script-setup-converter/src/lib/helpers/module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { ImportDeclaration } from "ts-morph";

export const hasNamedImportIdentifier = (
importDeclaration: ImportDeclaration,
identifier: string
): boolean => {
return Boolean(
importDeclaration.getNamedImports().find((namedImport) => {
return namedImport.getName() === identifier;
})
);
};

// NOTE: This function makes a side effect
export const removeNamedImportIdentifier = (
importDeclaration: ImportDeclaration,
identifier: string
): void => {
importDeclaration.getNamedImports().forEach((namedImport) => {
if (namedImport.getName() === identifier) {
namedImport.remove();
}
});
};
Loading