Skip to content

Commit b1c0d9a

Browse files
authored
revert: "fix: support "setup" attribute in <script> tag in vue 3 (#676)" (#678)
This reverts commit 40e4ecf.
1 parent 40e4ecf commit b1c0d9a

9 files changed

+1137
-1149
lines changed

src/typescript-reporter/extension/vue/TypeScriptVueExtension.ts

Lines changed: 25 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import { VueTemplateCompilerV3 } from './types/vue__compiler-sfc';
1010

1111
interface GenericScriptSFCBlock {
1212
content: string;
13-
attrs: Record<string, string | true | undefined>;
13+
attrs: Record<string, string | true>;
14+
start?: number;
15+
end?: number;
16+
lang?: string;
1417
src?: string;
1518
}
1619

@@ -91,22 +94,6 @@ function createTypeScriptVueExtension(
9194
};
9295
}
9396

94-
function mergeVueScriptsContent(
95-
scriptContent: string | undefined,
96-
scriptSetupContent: string | undefined
97-
): string {
98-
const scriptLines = scriptContent?.split(/\r?\n/) ?? [];
99-
const scriptSetupLines = scriptSetupContent?.split(/\r?\n/) ?? [];
100-
const maxScriptLines = Math.max(scriptLines.length, scriptSetupLines.length);
101-
const mergedScriptLines: string[] = [];
102-
103-
for (let line = 0; line < maxScriptLines; ++line) {
104-
mergedScriptLines.push(scriptLines[line] || scriptSetupLines[line]);
105-
}
106-
107-
return mergedScriptLines.join('\n');
108-
}
109-
11097
function getVueEmbeddedSource(fileName: string): TypeScriptEmbeddedSource | undefined {
11198
if (!fs.existsSync(fileName)) {
11299
return undefined;
@@ -118,44 +105,25 @@ function createTypeScriptVueExtension(
118105
let script: GenericScriptSFCBlock | undefined;
119106
if (isVueTemplateCompilerV2(compiler)) {
120107
const parsed = compiler.parseComponent(vueSourceText, {
121-
pad: 'line',
108+
pad: 'space',
122109
});
123110

124111
script = parsed.script;
125112
} else if (isVueTemplateCompilerV3(compiler)) {
126-
const parsed = compiler.parse(vueSourceText, {
127-
pad: 'line',
128-
});
129-
130-
if (parsed.descriptor) {
131-
const parsedScript = parsed.descriptor.script;
132-
const parsedScriptSetup = parsed.descriptor.scriptSetup;
133-
let parsedContent = mergeVueScriptsContent(
134-
parsedScript?.content,
135-
parsedScriptSetup?.content
136-
);
137-
138-
if (parsedScriptSetup) {
139-
// a little bit naive, but should work in 99.9% cases without need for parsing script
140-
const alreadyHasExportDefault = /export\s+default[\s|{]/gm.test(parsedContent);
141-
142-
if (!alreadyHasExportDefault) {
143-
parsedContent += '\nexport default {};';
144-
}
145-
// add script setup lines at the end
146-
parsedContent +=
147-
"\n// @ts-ignore\nimport { defineProps, defineEmits, defineExpose, withDefaults } from '@vue/runtime-core';";
148-
}
149-
150-
if (parsedScript || parsedScriptSetup) {
151-
// map newer version of SFCScriptBlock to the generic one
152-
script = {
153-
content: parsedContent,
154-
attrs: {
155-
lang: parsedScript?.lang || parsedScriptSetup?.lang,
156-
},
157-
};
158-
}
113+
const parsed = compiler.parse(vueSourceText);
114+
115+
if (parsed.descriptor && parsed.descriptor.script) {
116+
const scriptV3 = parsed.descriptor.script;
117+
118+
// map newer version of SFCScriptBlock to the generic one
119+
script = {
120+
content: scriptV3.content,
121+
attrs: scriptV3.attrs,
122+
start: scriptV3.loc.start.offset,
123+
end: scriptV3.loc.end.offset,
124+
lang: scriptV3.lang,
125+
src: scriptV3.src,
126+
};
159127
}
160128
} else {
161129
throw new Error(
@@ -173,7 +141,12 @@ function createTypeScriptVueExtension(
173141
}
174142
} else {
175143
// <script lang="ts"></script> block
176-
return createVueInlineScriptEmbeddedSource(script.content, script.attrs.lang);
144+
// pad blank lines to retain diagnostics location
145+
const lineOffset = vueSourceText.slice(0, script.start).split(/\r?\n/g).length;
146+
const paddedSourceText =
147+
Array(lineOffset).join('\n') + vueSourceText.slice(script.start, script.end);
148+
149+
return createVueInlineScriptEmbeddedSource(paddedSourceText, script.attrs.lang);
177150
}
178151
}
179152

src/typescript-reporter/extension/vue/types/vue__compiler-sfc.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ interface SFCDescriptor {
2323
filename: string;
2424
template: SFCBlock | null;
2525
script: SFCBlock | null;
26-
scriptSetup: SFCBlock | null;
2726
styles: SFCBlock[];
2827
customBlocks: SFCBlock[];
2928
}
@@ -38,11 +37,7 @@ interface SFCParseResult {
3837
errors: CompilerError[];
3938
}
4039

41-
interface SFCParserOptionsV3 {
42-
pad?: true | 'line' | 'space';
43-
}
44-
4540
export interface VueTemplateCompilerV3 {
4641
// eslint-disable-next-line @typescript-eslint/no-explicit-any
47-
parse(template: string, options?: SFCParserOptionsV3): SFCParseResult;
42+
parse(template: string, options?: any): SFCParseResult;
4843
}

test/e2e/TypeScriptVueExtension.spec.ts

Lines changed: 12 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
WEBPACK_DEV_SERVER_VERSION,
88
} from './sandbox/WebpackDevServerDriver';
99
import { FORK_TS_CHECKER_WEBPACK_PLUGIN_VERSION } from './sandbox/Plugin';
10-
import semver from 'semver/preload';
1110

1211
describe('TypeScript Vue Extension', () => {
1312
let sandbox: Sandbox;
@@ -30,23 +29,21 @@ describe('TypeScript Vue Extension', () => {
3029
typescript: '^3.8.0',
3130
tsloader: '^7.0.0',
3231
vueloader: '^15.8.3',
33-
vue: '^2.0.0',
32+
vue: '^2.6.11',
3433
compiler: 'vue-template-compiler',
35-
qrcodevue: '^1.7.0',
3634
},
3735
{
3836
async: true,
3937
typescript: '^3.8.0',
4038
tsloader: '^7.0.0',
41-
vueloader: 'v16.8.3',
42-
vue: '^3.0.0',
39+
vueloader: 'v16.0.0-beta.3',
40+
vue: '^3.0.0-beta.14',
4341
compiler: '@vue/compiler-sfc',
44-
qrcodevue: '^3.0.0',
4542
},
4643
])(
4744
'reports semantic error for %p',
48-
async ({ async, typescript, tsloader, vueloader, vue, compiler, qrcodevue }) => {
49-
const fixtures = [
45+
async ({ async, typescript, tsloader, vueloader, vue, compiler }) => {
46+
await sandbox.load([
5047
await readFixture(join(__dirname, 'fixtures/environment/typescript-vue.fixture'), {
5148
FORK_TS_CHECKER_WEBPACK_PLUGIN_VERSION: JSON.stringify(
5249
FORK_TS_CHECKER_WEBPACK_PLUGIN_VERSION
@@ -59,23 +56,12 @@ describe('TypeScript Vue Extension', () => {
5956
VUE_LOADER_VERSION: JSON.stringify(vueloader),
6057
VUE_VERSION: JSON.stringify(vue),
6158
VUE_COMPILER: JSON.stringify(compiler),
62-
QRCODE_VUE_VERSION: JSON.stringify(qrcodevue),
6359
ASYNC: JSON.stringify(async),
6460
}),
65-
await readFixture(join(__dirname, 'fixtures/implementation/typescript-vue-shared.fixture')),
66-
];
67-
if (semver.satisfies('2.0.0', vue)) {
68-
fixtures.push(
69-
await readFixture(join(__dirname, 'fixtures/implementation/typescript-vue2.fixture'))
70-
);
71-
} else if (semver.satisfies('3.0.0', vue)) {
72-
fixtures.push(
73-
await readFixture(join(__dirname, 'fixtures/implementation/typescript-vue3.fixture'))
74-
);
75-
}
76-
await sandbox.load(fixtures);
61+
await readFixture(join(__dirname, 'fixtures/implementation/typescript-vue.fixture')),
62+
]);
7763

78-
if (semver.satisfies('2.0.0', vue)) {
64+
if (vue === '^2.6.11') {
7965
await sandbox.write(
8066
'src/vue-shim.d.ts',
8167
[
@@ -85,7 +71,7 @@ describe('TypeScript Vue Extension', () => {
8571
'}',
8672
].join('\n')
8773
);
88-
} else if (semver.satisfies('3.0.0', vue)) {
74+
} else {
8975
await sandbox.write('src/vue-shim.d.ts', 'declare module "*.vue";');
9076
}
9177

@@ -112,7 +98,7 @@ describe('TypeScript Vue Extension', () => {
11298
'ERROR in src/component/LoggedIn.vue:27:21',
11399
"TS2304: Cannot find name 'getUserName'.",
114100
' 25 | const user: User = this.user;',
115-
' 26 |',
101+
' 26 | ',
116102
" > 27 | return user ? getUserName(user) : '';",
117103
' | ^^^^^^^^^^^',
118104
' 28 | }',
@@ -140,7 +126,7 @@ describe('TypeScript Vue Extension', () => {
140126
'ERROR in src/component/LoggedIn.vue:27:29',
141127
"TS2339: Property 'firstName' does not exist on type 'User'.",
142128
' 25 | const user: User = this.user;',
143-
' 26 |',
129+
' 26 | ',
144130
" > 27 | return user ? `${user.firstName} ${user.lastName}` : '';",
145131
' | ^^^^^^^^^',
146132
' 28 | }',
@@ -150,7 +136,7 @@ describe('TypeScript Vue Extension', () => {
150136
[
151137
'ERROR in src/model/User.ts:11:16',
152138
"TS2339: Property 'firstName' does not exist on type 'User'.",
153-
' 9 |',
139+
' 9 | ',
154140
' 10 | function getUserName(user: User): string {',
155141
' > 11 | return [user.firstName, user.lastName]',
156142
' | ^^^^^^^^^',
@@ -159,62 +145,6 @@ describe('TypeScript Vue Extension', () => {
159145
' 14 | }',
160146
].join('\n'),
161147
]);
162-
163-
// fix the error
164-
await sandbox.patch(
165-
'src/model/User.ts',
166-
' lastName?: string;',
167-
[' firstName?: string;', ' lastName?: string;'].join('\n')
168-
);
169-
await driver.waitForNoErrors();
170-
171-
if (semver.satisfies('3.0.0', vue)) {
172-
await sandbox.patch(
173-
'src/component/Header.vue',
174-
'defineProps({',
175-
['let x: number = "1"', 'defineProps({'].join('\n')
176-
);
177-
178-
errors = await driver.waitForErrors();
179-
expect(errors).toEqual([
180-
[
181-
'ERROR in src/component/Header.vue:6:5',
182-
"TS2322: Type '\"1\"' is not assignable to type 'number'.",
183-
' 4 |',
184-
' 5 | <script setup lang="ts">',
185-
' > 6 | let x: number = "1"',
186-
' | ^',
187-
' 7 | defineProps({',
188-
' 8 | title: String,',
189-
' 9 | });',
190-
].join('\n'),
191-
]);
192-
// fix the issue
193-
await sandbox.patch('src/component/Header.vue', 'let x: number = "1"', '');
194-
await driver.waitForNoErrors();
195-
196-
// introduce error in second <script>
197-
await sandbox.patch(
198-
'src/component/Logo.vue',
199-
'export default {',
200-
['let x: number = "1";', 'export default {'].join('\n')
201-
);
202-
203-
errors = await driver.waitForErrors();
204-
expect(errors).toEqual([
205-
[
206-
'ERROR in src/component/Logo.vue:15:5',
207-
"TS2322: Type '\"1\"' is not assignable to type 'number'.",
208-
' 13 |',
209-
' 14 | <script lang="ts">',
210-
' > 15 | let x: number = "1";',
211-
' | ^',
212-
' 16 | export default {',
213-
' 17 | inheritAttrs: false,',
214-
' 18 | customOptions: {}',
215-
].join('\n'),
216-
]);
217-
}
218148
}
219149
);
220150
});

test/e2e/fixtures/environment/typescript-vue.fixture

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"typescript": ${TYPESCRIPT_VERSION},
1818
"vue-loader": ${VUE_LOADER_VERSION},
1919
${VUE_COMPILER}: ${VUE_VERSION},
20-
"qrcode.vue": ${QRCODE_VUE_VERSION},
20+
"qrcode.vue": "^1.7.0",
2121
"webpack": ${WEBPACK_VERSION},
2222
"webpack-cli": ${WEBPACK_CLI_VERSION},
2323
"webpack-dev-server": ${WEBPACK_DEV_SERVER_VERSION}

test/e2e/fixtures/implementation/typescript-vue-shared.fixture renamed to test/e2e/fixtures/implementation/typescript-vue.fixture

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// src/component/LoginView.vue
1+
/// src/App.vue
22
<template>
33
<logged-in v-if="user" :user="user" @logout="logout"></logged-in>
44
<login-form v-else @login="login"></login-form>
@@ -108,7 +108,7 @@ export default {
108108
}
109109
},
110110
computed: {
111-
userName() {
111+
userName: () => {
112112
const user: User = this.user;
113113

114114
return user ? getUserName(user) : '';

test/e2e/fixtures/implementation/typescript-vue2.fixture

Lines changed: 0 additions & 8 deletions
This file was deleted.

test/e2e/fixtures/implementation/typescript-vue3.fixture

Lines changed: 0 additions & 63 deletions
This file was deleted.

0 commit comments

Comments
 (0)