Skip to content

Commit

Permalink
feat: ts5.2 clickable inlay parameter hints (#2162)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonlyu123 authored Oct 10, 2023
1 parent 62a1c94 commit 582b76a
Show file tree
Hide file tree
Showing 16 changed files with 245 additions and 67 deletions.
10 changes: 7 additions & 3 deletions packages/language-server/src/ls-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ export interface TsInlayHintsConfig {
| undefined;
parameterTypes: { enabled: boolean } | undefined;
propertyDeclarationTypes: { enabled: boolean } | undefined;
variableTypes: { enabled: boolean } | undefined;
variableTypes: { enabled: boolean; suppressWhenTypeMatchesName: boolean } | undefined;
}

export type TsUserConfigLang = 'typescript' | 'javascript';
Expand Down Expand Up @@ -440,9 +440,13 @@ export class LSConfigManager {
includeInlayFunctionLikeReturnTypeHints: inlayHints?.functionLikeReturnTypes?.enabled,
includeInlayParameterNameHints: inlayHints?.parameterNames?.enabled,
includeInlayParameterNameHintsWhenArgumentMatchesName:
inlayHints?.parameterNames?.suppressWhenArgumentMatchesName,
inlayHints?.parameterNames?.suppressWhenArgumentMatchesName === false,
includeInlayFunctionParameterTypeHints: inlayHints?.parameterTypes?.enabled,
includeInlayVariableTypeHints: inlayHints?.variableTypes?.enabled
includeInlayVariableTypeHints: inlayHints?.variableTypes?.enabled,
includeInlayPropertyDeclarationTypeHints: inlayHints?.propertyDeclarationTypes?.enabled,
includeInlayVariableTypeHintsWhenTypeMatchesName:
inlayHints?.variableTypes?.suppressWhenTypeMatchesName === false,
interactiveInlayHints: true
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import ts from 'typescript';
import { CancellationToken } from 'vscode-languageserver';
import { Position, Range, InlayHint, InlayHintKind } from 'vscode-languageserver-types';
import { Document, isInTag } from '../../../lib/documents';
import {
Position,
Range,
InlayHint,
InlayHintKind,
InlayHintLabelPart
} from 'vscode-languageserver-types';
import { Document, isInTag, mapLocationToOriginal } from '../../../lib/documents';
import { getAttributeContextAtPosition } from '../../../lib/documents/parseHtml';
import { InlayHintProvider } from '../../interfaces';
import { DocumentSnapshot, SvelteDocumentSnapshot } from '../DocumentSnapshot';
Expand All @@ -11,8 +17,10 @@ import {
isInGeneratedCode,
findChildOfKind,
findRenderFunction,
findClosestContainingNode
findClosestContainingNode,
SnapshotMap
} from './utils';
import { convertRange } from '../utils';

export class InlayHintProviderImpl implements InlayHintProvider {
constructor(private readonly lsAndTsDocResolver: LSAndTSDocResolver) {}
Expand Down Expand Up @@ -52,7 +60,10 @@ export class InlayHintProviderImpl implements InlayHintProvider {
const renderFunctionReturnTypeLocation =
renderFunction && this.getTypeAnnotationPosition(renderFunction);

const result = inlayHints
const snapshotMap = new SnapshotMap(this.lsAndTsDocResolver);
snapshotMap.set(tsDoc.filePath, tsDoc);

const convertPromises = inlayHints
.filter(
(inlayHint) =>
!isInGeneratedCode(tsDoc.getFullText(), inlayHint.position) &&
Expand All @@ -61,21 +72,20 @@ export class InlayHintProviderImpl implements InlayHintProvider {
!this.isGeneratedVariableTypeHint(sourceFile, inlayHint) &&
!this.isGeneratedFunctionReturnType(sourceFile, inlayHint)
)
.map((inlayHint) => ({
label: inlayHint.text,
.map(async (inlayHint) => ({
label: await this.convertInlayHintLabelParts(inlayHint, snapshotMap),
position: this.getOriginalPosition(document, tsDoc, inlayHint),
kind: this.convertInlayHintKind(inlayHint.kind),
paddingLeft: inlayHint.whitespaceBefore,
paddingRight: inlayHint.whitespaceAfter
}))
.filter(
(inlayHint) =>
inlayHint.position.line >= 0 &&
inlayHint.position.character >= 0 &&
!this.checkGeneratedFunctionHintWithSource(inlayHint, document)
);
}));

return result;
return (await Promise.all(convertPromises)).filter(
(inlayHint) =>
inlayHint.position.line >= 0 &&
inlayHint.position.character >= 0 &&
!this.checkGeneratedFunctionHintWithSource(inlayHint, document)
);
}

private areInlayHintsEnabled(preferences: ts.UserPreferences) {
Expand Down Expand Up @@ -106,6 +116,43 @@ export class InlayHintProviderImpl implements InlayHintProvider {
};
}

private async convertInlayHintLabelParts(inlayHint: ts.InlayHint, snapshotMap: SnapshotMap) {
if (!inlayHint.displayParts) {
return inlayHint.text;
}

const convertPromises = inlayHint.displayParts.map(
async (part): Promise<InlayHintLabelPart> => {
if (!part.file || !part.span) {
return {
value: part.text
};
}

const snapshot = await snapshotMap.retrieve(part.file);
if (!snapshot) {
return {
value: part.text
};
}

const originalLocation = mapLocationToOriginal(
snapshot,
convertRange(snapshot, part.span)
);

return {
value: part.text,
location: originalLocation.range.start.line < 0 ? undefined : originalLocation
};
}
);

const parts = await Promise.all(convertPromises);

return parts;
}

private getOriginalPosition(
document: Document,
tsDoc: SvelteDocumentSnapshot,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
[
{
"label": ": void",
"position": { "line": 5, "character": 30 },
"kind": 1,
"paddingLeft": true
},
{
"label": ": MouseEvent",
"position": {
"line": 7,
"character": 22
},
"position": { "line": 9, "character": 22 },
"kind": 1,
"paddingLeft": true
},
{
"label": "message:",
"position": {
"line": 7,
"character": 38
},
"label": [
{
"value": "message",
"location": {
"range": {
"start": { "line": 5, "character": 17 },
"end": { "line": 5, "character": 24 }
},
"uri": "<workspaceUri>/component-handler/input.svelte"
}
},
{ "value": ":" }
],
"position": { "line": 9, "character": 30 },
"kind": 2,
"paddingRight": true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
import { SvelteComponentTyped } from 'svelte';
let Component: typeof SvelteComponentTyped<{}, { click: MouseEvent }, {}>;
function log(message: any) {}
</script>

<Component on:click></Component>
<Component on:click={e => console.log(e)}></Component>
<Component on:click={e => log(e)}></Component>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[
{
"label": ": void",
"position": { "line": 1, "character": 33 },
"kind": 1,
"paddingLeft": true
},
{
"label": [
{
"value": "message",
"location": {
"range": {
"start": { "line": 1, "character": 17 },
"end": { "line": 1, "character": 24 }
},
"uri": "<workspaceUri>/disable-argument-name-match/input.svelte"
}
},
{ "value": ":" }
],
"position": { "line": 5, "character": 8 },
"kind": 2,
"paddingRight": true
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script lang="ts">
function log(message: string) {
}
let message: string = 'Hello World';
log(message);
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"label": ": number",
"position": { "line": 1, "character": 14 },
"kind": 1,
"paddingLeft": true
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<script lang="ts">
let number = 1;
</script>
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
[
{
"label": ": MouseEvent & { currentTarge...",
"position": {
"line": 4,
"character": 19
},
"position": { "line": 5, "character": 19 },
"kind": 1,
"paddingLeft": true
},
{
"label": "message:",
"position": {
"line": 4,
"character": 35
},
"label": [
{
"value": "message",
"location": {
"range": {
"start": { "line": 1, "character": 17 },
"end": { "line": 1, "character": 24 }
},
"uri": "<workspaceUri>/element-handler/input.svelte"
}
},
{ "value": ":" }
],
"position": { "line": 5, "character": 27 },
"kind": 2,
"paddingRight": true
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
function log(message: any): void {}
</script>

<button on:click></button>
<button on:click={e => console.log(e)}></button>
<button on:click={e => log(e)}></button>
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
[
{
"label": ": void",
"position": {
"line": 4,
"character": 29
},
"position": { "line": 4, "character": 29 },
"kind": 1,
"paddingLeft": true
},
{
"label": "name:",
"position": {
"line": 7,
"character": 20
},
"label": [
{
"value": "name",
"location": {
"range": {
"start": { "line": 4, "character": 16 },
"end": { "line": 4, "character": 20 }
},
"uri": "<workspaceUri>/function-call-in-props/input.svelte"
}
},
{ "value": ":" }
],
"position": { "line": 7, "character": 20 },
"kind": 2,
"paddingRight": true
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{ "label": ": number", "position": { "line": 2, "character": 9 }, "kind": 1, "paddingLeft": true }]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script lang="ts">
class A {
b = 1
}
</script>
Original file line number Diff line number Diff line change
@@ -1,29 +1,50 @@
[
{
"label": ": number",
"position": {
"line": 1,
"character": 12
},
"position": { "line": 1, "character": 12 },
"kind": 1,
"paddingLeft": true
},
{
"label": "message:",
"position": {
"line": 2,
"character": 19
},
"label": [
{
"value": "message",
"location": {
"range": {
"start": { "line": 10, "character": 17 },
"end": { "line": 10, "character": 24 }
},
"uri": "<workspaceUri>/reactive-block/input.svelte"
}
},
{ "value": ":" }
],
"position": { "line": 2, "character": 11 },
"kind": 2,
"paddingRight": true
},
{
"label": "message:",
"position": {
"line": 4,
"character": 20
},
"label": [
{
"value": "message",
"location": {
"range": {
"start": { "line": 10, "character": 17 },
"end": { "line": 10, "character": 24 }
},
"uri": "<workspaceUri>/reactive-block/input.svelte"
}
},
{ "value": ":" }
],
"position": { "line": 4, "character": 12 },
"kind": 2,
"paddingRight": true
},
{
"label": ": any",
"position": { "line": 10, "character": 24 },
"kind": 1,
"paddingLeft": true
}
]
Loading

0 comments on commit 582b76a

Please sign in to comment.