Skip to content

Commit 6ff486a

Browse files
authored
(fix) take arrow function into account when adding return type (#1934)
#1932 also make ts a param
1 parent 0f813a3 commit 6ff486a

File tree

10 files changed

+91
-20
lines changed

10 files changed

+91
-20
lines changed

packages/language-server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
"prettier-plugin-svelte": "~2.9.0",
5858
"svelte": "^3.55.0",
5959
"svelte-preprocess": "~5.0.0",
60-
"svelte2tsx": "~0.6.4",
60+
"svelte2tsx": "~0.6.8",
6161
"typescript": "*",
6262
"vscode-css-languageservice": "~6.2.0",
6363
"vscode-html-languageservice": "~5.0.0",

packages/language-server/src/plugins/typescript/DocumentSnapshot.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ export class JSOrTSDocumentSnapshot extends IdentityMapper implements DocumentSn
537537

538538
private adjustText() {
539539
const result = internalHelpers.upsertKitFile(
540+
ts,
540541
this.filePath,
541542
{
542543
clientHooksPath: this.clientHooksPath,

packages/svelte2tsx/index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,15 @@ export const internalHelpers: {
128128
)=> boolean,
129129
isParamsFile: (fileName: string, basename: string, paramsPath: string) =>boolean,
130130
upsertKitFile: (
131+
_ts: typeof ts,
131132
fileName: string,
132133
kitFilesSettings: InternalHelpers.KitFilesSettings,
133134
getSource: () => ts.SourceFile | undefined,
134135
surround?: (code: string) => string
135136
) => { text: string; addedCode: InternalHelpers.AddedCode[] } | undefined,
136137
toVirtualPos: (pos: number, addedCode: InternalHelpers.AddedCode[]) => number,
137138
toOriginalPos: (pos: number, addedCode: InternalHelpers.AddedCode[]) => {pos: number; inGenerated: boolean},
138-
findExports: (source: ts.SourceFile, isTsFile: boolean) => Map<
139+
findExports: (_ts: typeof ts, source: ts.SourceFile, isTsFile: boolean) => Map<
139140
string,
140141
| {
141142
type: 'function';

packages/svelte2tsx/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "svelte2tsx",
3-
"version": "0.6.4",
3+
"version": "0.6.8",
44
"description": "Convert Svelte components to TSX for type checking",
55
"author": "David Pershouse",
66
"license": "MIT",

packages/svelte2tsx/src/helpers/sveltekit.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import path from 'path';
2-
import ts from 'typescript';
2+
import type ts from 'typescript';
33
import { findExports } from './typescript';
44

5+
type _ts = typeof ts;
6+
57
export interface AddedCode {
68
generatedPos: number;
79
originalPos: number;
@@ -87,29 +89,39 @@ export function isParamsFile(fileName: string, basename: string, paramsPath: str
8789
}
8890

8991
export function upsertKitFile(
92+
ts: _ts,
9093
fileName: string,
9194
kitFilesSettings: KitFilesSettings,
9295
getSource: () => ts.SourceFile | undefined,
9396
surround: (text: string) => string = (text) => text
9497
): { text: string; addedCode: AddedCode[] } {
9598
let basename = path.basename(fileName);
9699
const result =
97-
upserKitRouteFile(fileName, basename, getSource, surround) ??
100+
upserKitRouteFile(ts, fileName, basename, getSource, surround) ??
98101
upserKitServerHooksFile(
102+
ts,
99103
fileName,
100104
basename,
101105
kitFilesSettings.serverHooksPath,
102106
getSource,
103107
surround
104108
) ??
105109
upserKitClientHooksFile(
110+
ts,
106111
fileName,
107112
basename,
108113
kitFilesSettings.clientHooksPath,
109114
getSource,
110115
surround
111116
) ??
112-
upserKitParamsFile(fileName, basename, kitFilesSettings.paramsPath, getSource, surround);
117+
upserKitParamsFile(
118+
ts,
119+
fileName,
120+
basename,
121+
kitFilesSettings.paramsPath,
122+
getSource,
123+
surround
124+
);
113125
if (!result) {
114126
return;
115127
}
@@ -128,6 +140,7 @@ export function upsertKitFile(
128140
}
129141

130142
function upserKitRouteFile(
143+
ts: _ts,
131144
fileName: string,
132145
basename: string,
133146
getSource: () => ts.SourceFile | undefined,
@@ -144,7 +157,7 @@ function upserKitRouteFile(
144157
};
145158

146159
const isTsFile = basename.endsWith('.ts');
147-
const exports = findExports(source, isTsFile);
160+
const exports = findExports(ts, source, isTsFile);
148161

149162
// add type to load function if not explicitly typed
150163
const load = exports.get('load');
@@ -175,6 +188,7 @@ function upserKitRouteFile(
175188
// add types to GET/PUT/POST/PATCH/DELETE/OPTIONS if not explicitly typed
176189
const insertApiMethod = (name: string) => {
177190
addTypeToFunction(
191+
ts,
178192
exports,
179193
surround,
180194
insert,
@@ -194,6 +208,7 @@ function upserKitRouteFile(
194208
}
195209

196210
function upserKitParamsFile(
211+
ts: _ts,
197212
fileName: string,
198213
basename: string,
199214
paramsPath: string,
@@ -213,14 +228,15 @@ function upserKitParamsFile(
213228
};
214229

215230
const isTsFile = basename.endsWith('.ts');
216-
const exports = findExports(source, isTsFile);
231+
const exports = findExports(ts, source, isTsFile);
217232

218-
addTypeToFunction(exports, surround, insert, 'match', 'string', 'boolean');
233+
addTypeToFunction(ts, exports, surround, insert, 'match', 'string', 'boolean');
219234

220235
return { addedCode, originalText: source.getFullText() };
221236
}
222237

223238
function upserKitClientHooksFile(
239+
ts: _ts,
224240
fileName: string,
225241
basename: string,
226242
clientHooksPath: string,
@@ -240,9 +256,10 @@ function upserKitClientHooksFile(
240256
};
241257

242258
const isTsFile = basename.endsWith('.ts');
243-
const exports = findExports(source, isTsFile);
259+
const exports = findExports(ts, source, isTsFile);
244260

245261
addTypeToFunction(
262+
ts,
246263
exports,
247264
surround,
248265
insert,
@@ -254,6 +271,7 @@ function upserKitClientHooksFile(
254271
}
255272

256273
function upserKitServerHooksFile(
274+
ts: _ts,
257275
fileName: string,
258276
basename: string,
259277
serverHooksPath: string,
@@ -273,10 +291,10 @@ function upserKitServerHooksFile(
273291
};
274292

275293
const isTsFile = basename.endsWith('.ts');
276-
const exports = findExports(source, isTsFile);
294+
const exports = findExports(ts, source, isTsFile);
277295

278296
const addType = (name: string, type: string) => {
279-
addTypeToFunction(exports, surround, insert, name, type);
297+
addTypeToFunction(ts, exports, surround, insert, name, type);
280298
};
281299

282300
addType('handleError', `import('@sveltejs/kit').HandleServerError`);
@@ -310,6 +328,7 @@ function addTypeToVariable(
310328
}
311329

312330
function addTypeToFunction(
331+
ts: _ts,
313332
exports: Map<
314333
string,
315334
| {
@@ -331,9 +350,11 @@ function addTypeToFunction(
331350
const paramInsertion = surround(!returnType ? `: Parameters<${type}>[0]` : `: ${type}`);
332351
insert(paramPos, paramInsertion);
333352
if (!fn.node.type && fn.node.body) {
334-
const returnPos = fn.node.body.getStart();
353+
const returnPos = ts.isArrowFunction(fn.node)
354+
? fn.node.equalsGreaterThanToken.getStart()
355+
: fn.node.body.getStart();
335356
const returnInsertion = surround(
336-
!returnType ? `: ReturnType<${type}>` : `: ${returnType}`
357+
!returnType ? `: ReturnType<${type}> ` : `: ${returnType} `
337358
);
338359
insert(returnPos, returnInsertion);
339360
}

packages/svelte2tsx/src/helpers/typescript.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import ts from 'typescript';
1+
import type ts from 'typescript';
2+
3+
type _ts = typeof ts;
24

35
/**
46
* Finds the top level const/let/function exports of a source file.
57
*/
6-
export function findExports(source: ts.SourceFile, isTsFile: boolean) {
8+
export function findExports(ts: _ts, source: ts.SourceFile, isTsFile: boolean) {
79
const exports = new Map<
810
string,
911
| {
@@ -28,7 +30,7 @@ export function findExports(source: ts.SourceFile, isTsFile: boolean) {
2830
exports.set(statement.name.text, {
2931
type: 'function',
3032
node: statement,
31-
hasTypeDefinition: hasTypedParameter(statement, isTsFile)
33+
hasTypeDefinition: hasTypedParameter(ts, statement, isTsFile)
3234
});
3335
}
3436
if (
@@ -59,7 +61,7 @@ export function findExports(source: ts.SourceFile, isTsFile: boolean) {
5961
exports.set(declaration.name.getText(), {
6062
type: 'function',
6163
node,
62-
hasTypeDefinition: hasTypeDefinition || hasTypedParameter(node, isTsFile)
64+
hasTypeDefinition: hasTypeDefinition || hasTypedParameter(ts, node, isTsFile)
6365
});
6466
} else {
6567
exports.set(declaration.name.getText(), {
@@ -75,6 +77,7 @@ export function findExports(source: ts.SourceFile, isTsFile: boolean) {
7577
}
7678

7779
function hasTypedParameter(
80+
ts: _ts,
7881
node: ts.FunctionDeclaration | ts.ArrowFunction | ts.FunctionExpression,
7982
isTsFile: boolean
8083
): boolean {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as assert from 'assert';
2+
import ts from 'typescript';
3+
import { internalHelpers } from '../../src';
4+
5+
describe('Internal Helpers - upsertKitFile', () => {
6+
function upsert(file: string, source: string, expected: string) {
7+
const sourceFile = ts.createSourceFile('d', source, ts.ScriptTarget.Latest, true);
8+
const result = internalHelpers.upsertKitFile(
9+
ts,
10+
file,
11+
{
12+
clientHooksPath: 'hooks.client',
13+
paramsPath: 'params',
14+
serverHooksPath: 'hooks.server'
15+
},
16+
() => sourceFile
17+
);
18+
assert.strictEqual(result?.text, expected);
19+
}
20+
21+
it('upserts +page.ts function', () => {
22+
upsert(
23+
'+page.ts',
24+
`export function load(e) { return e; }`,
25+
`export function load(e: import('./$types').PageLoadEvent) { return e; }`
26+
);
27+
});
28+
29+
it('upserts handle hook const', () => {
30+
upsert(
31+
'hooks.server.ts',
32+
`export const handle = async ({ event, resolve }) => {};`,
33+
`export const handle = async ({ event, resolve }: Parameters<import('@sveltejs/kit').Handle>[0]) : ReturnType<import('@sveltejs/kit').Handle> => {};`
34+
);
35+
});
36+
37+
it('upserts GET async function', () => {
38+
upsert(
39+
'+server.ts',
40+
`export async function GET(e) {}`,
41+
`export async function GET(e: import('./$types').RequestEvent) : Response | Promise<Response> {}`
42+
);
43+
});
44+
});

packages/typescript-plugin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@
2424
},
2525
"dependencies": {
2626
"@jridgewell/sourcemap-codec": "^1.4.14",
27-
"svelte2tsx": "~0.6.4"
27+
"svelte2tsx": "~0.6.8"
2828
}
2929
}

packages/typescript-plugin/src/language-service/diagnostics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ function getKitDiagnostics<
170170
isKitRouteExportAllowedIn(basename, kitExports[key])
171171
);
172172
if (source && basename.startsWith('+')) {
173-
const exports = internalHelpers.findExports(source, /* irrelevant */ false);
173+
const exports = internalHelpers.findExports(ts, source, /* irrelevant */ false);
174174
for (const exportName of exports.keys()) {
175175
if (!validExports.includes(exportName) && !exportName.startsWith('_')) {
176176
const node = exports.get(exportName)!.node;

packages/typescript-plugin/src/language-service/sveltekit.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ function getProxiedLanguageService(info: ts.server.PluginCreateInfo, ts: _ts, lo
581581

582582
upsertKitFile(fileName: string) {
583583
const result = internalHelpers.upsertKitFile(
584+
ts,
584585
fileName,
585586
{
586587
clientHooksPath: this.clientHooksPath,

0 commit comments

Comments
 (0)