Skip to content

Commit

Permalink
feat: support typescript 5.6 (#2545)
Browse files Browse the repository at this point in the history
* feat: support typescript 5.6

* fix build

* autoImportSpecifierExcludeRegexes and organizeImports preference

* what

* bumps typescript-auto-import-cache

* missed one

* use commit characters from typescript when possible

* format

* bump language server dep
  • Loading branch information
jasonlyu123 authored Nov 5, 2024
1 parent 01fbe14 commit 98f7229
Show file tree
Hide file tree
Showing 19 changed files with 244 additions and 67 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"lint": "prettier --check ."
},
"dependencies": {
"typescript": "^5.5.2"
"typescript": "^5.6.3"
},
"devDependencies": {
"cross-env": "^7.0.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/language-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@
"prettier-plugin-svelte": "^3.2.6",
"svelte": "^4.2.19",
"svelte2tsx": "workspace:~",
"typescript": "^5.5.2",
"typescript-auto-import-cache": "^0.3.3",
"typescript": "^5.6.3",
"typescript-auto-import-cache": "^0.3.5",
"vscode-css-languageservice": "~6.3.0",
"vscode-html-languageservice": "~5.3.0",
"vscode-languageserver": "9.0.1",
Expand Down
41 changes: 39 additions & 2 deletions packages/language-server/src/ls-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,20 @@ export interface TsUserPreferencesConfig {
includePackageJsonAutoImports?: ts.UserPreferences['includePackageJsonAutoImports'];

preferTypeOnlyAutoImports?: ts.UserPreferences['preferTypeOnlyAutoImports'];

autoImportSpecifierExcludeRegexes?: string[];

organizeImports?: TsOrganizeImportPreferencesConfig;
}

interface TsOrganizeImportPreferencesConfig {
accentCollation: ts.UserPreferences['organizeImportsAccentCollation'];
caseFirst: ts.UserPreferences['organizeImportsCaseFirst'] | 'default';
caseSensitivity: ts.UserPreferences['organizeImportsIgnoreCase'];
collation: ts.UserPreferences['organizeImportsCollation'];
locale: ts.UserPreferences['organizeImportsLocale'];
numericCollation: ts.UserPreferences['organizeImportsNumericCollation'];
typeOrder: ts.UserPreferences['organizeImportsTypeOrder'] | 'auto';
}

/**
Expand Down Expand Up @@ -473,11 +487,34 @@ export class LSConfigManager {
includeInlayPropertyDeclarationTypeHints: inlayHints?.propertyDeclarationTypes?.enabled,
includeInlayVariableTypeHintsWhenTypeMatchesName:
inlayHints?.variableTypes?.suppressWhenTypeMatchesName === false,

interactiveInlayHints: true
interactiveInlayHints: true,

autoImportSpecifierExcludeRegexes:
config.preferences?.autoImportSpecifierExcludeRegexes,

organizeImportsAccentCollation: config.preferences?.organizeImports?.accentCollation,
organizeImportsCollation: config.preferences?.organizeImports?.collation,
organizeImportsCaseFirst: this.withDefaultAsUndefined(
config.preferences?.organizeImports?.caseFirst,
'default'
),
organizeImportsIgnoreCase: this.withDefaultAsUndefined(
config.preferences?.organizeImports?.caseSensitivity,
'auto'
),
organizeImportsLocale: config.preferences?.organizeImports?.locale,
organizeImportsNumericCollation: config.preferences?.organizeImports?.numericCollation,
organizeImportsTypeOrder: this.withDefaultAsUndefined(
config.preferences?.organizeImports?.typeOrder,
'auto'
)
};
}

private withDefaultAsUndefined<T, O extends T>(value: T, def: O): Exclude<T, O> | undefined {
return value === def ? undefined : (value as Exclude<T, O>);
}

getTsUserPreferences(
lang: TsUserConfigLang,
normalizedWorkspacePath: string | null
Expand Down
21 changes: 20 additions & 1 deletion packages/language-server/src/plugins/PluginHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,22 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
});
}

let itemDefaults: CompletionList['itemDefaults'];
if (completions.length === 1) {
itemDefaults = completions[0]?.result.itemDefaults;
} else {
// don't apply items default to the result of other plugins
for (const completion of completions) {
const itemDefaults = completion.result.itemDefaults;
if (!itemDefaults) {
continue;
}
completion.result.items.forEach((item) => {
item.commitCharacters ??= itemDefaults.commitCharacters;
});
}
}

let flattenedCompletions = flatten(
completions.map((completion) => completion.result.items)
);
Expand All @@ -194,7 +210,10 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
);
}

return CompletionList.create(flattenedCompletions, isIncomplete);
const result = CompletionList.create(flattenedCompletions, isIncomplete);
result.itemDefaults = itemDefaults;

return result;
}

async resolveCompletion(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ type LastCompletion = {
completionList: AppCompletionList<CompletionResolveInfo> | null;
};

interface CommitCharactersOptions {
checkCommitCharacters: boolean;
defaultCommitCharacters?: string[];
isNewIdentifierLocation?: boolean;
}

export class CompletionsProviderImpl implements CompletionsProvider<CompletionResolveInfo> {
constructor(
private readonly lsAndTsDocResolver: LSAndTSDocResolver,
Expand Down Expand Up @@ -237,10 +243,8 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionRe
},
formatSettings
);
const addCommitCharacters =
// replicating VS Code behavior https://github.com/microsoft/vscode/blob/main/extensions/typescript-language-features/src/languageFeatures/completions.ts
response?.isNewIdentifierLocation !== true &&
(!tsDoc.parserError || isInScript(position, tsDoc));

const commitCharactersOptions = this.getCommitCharactersOptions(response, tsDoc, position);
let completions = response?.entries || [];

const customCompletions = eventAndSlotLetCompletions.concat(tagCompletions ?? []);
Expand Down Expand Up @@ -289,7 +293,7 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionRe
fileUrl,
position,
isCompletionInTag,
addCommitCharacters,
commitCharactersOptions,
asStore,
existingImports
);
Expand Down Expand Up @@ -376,6 +380,27 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionRe
}

const completionList = CompletionList.create(completionItems, !!tsDoc.parserError);
if (
commitCharactersOptions.checkCommitCharacters &&
commitCharactersOptions.defaultCommitCharacters?.length
) {
const clientSupportsItemsDefault = this.configManager
.getClientCapabilities()
?.textDocument?.completion?.completionList?.itemDefaults?.includes(
'commitCharacters'
);

if (clientSupportsItemsDefault) {
completionList.itemDefaults = {
commitCharacters: commitCharactersOptions.defaultCommitCharacters
};
} else {
completionList.items.forEach((item) => {
item.commitCharacters ??= commitCharactersOptions.defaultCommitCharacters;
});
}
}

this.lastCompletion = { key: document.getFilePath() || '', position, completionList };

return completionList;
Expand Down Expand Up @@ -578,6 +603,7 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionRe
sortText: '-1',
detail: info.name + ': ' + info.type,
documentation: info.doc && { kind: MarkupKind.Markdown, value: info.doc },
commitCharacters: [],
textEdit: defaultTextEditRange
? TextEdit.replace(this.cloneRange(defaultTextEditRange), name)
: undefined
Expand Down Expand Up @@ -623,7 +649,7 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionRe
uri: string,
position: Position,
isCompletionInTag: boolean,
addCommitCharacters: boolean,
commitCharactersOptions: CommitCharactersOptions,
asStore: boolean,
existingImports: Set<string>
): AppCompletionItem<CompletionResolveInfo> | null {
Expand Down Expand Up @@ -669,7 +695,7 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionRe
label,
insertText,
kind: scriptElementKindToCompletionItemKind(comp.kind),
commitCharacters: addCommitCharacters ? this.commitCharacters : undefined,
commitCharacters: this.getCommitCharacters(comp, commitCharactersOptions),
// Make sure svelte component and runes take precedence
sortText: isRunesCompletion || isSvelteComp ? '-1' : comp.sortText,
preselect: isRunesCompletion || isSvelteComp ? true : comp.isRecommended,
Expand Down Expand Up @@ -734,6 +760,60 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionRe
};
}

private getCommitCharactersOptions(
response: ts.CompletionInfo | undefined,
tsDoc: SvelteDocumentSnapshot,
position: Position
): CommitCharactersOptions {
if ((!isInScript(position, tsDoc) && tsDoc.parserError) || !response) {
return {
checkCommitCharacters: false
};
}

const isNewIdentifierLocation = response.isNewIdentifierLocation;
let defaultCommitCharacters = response.defaultCommitCharacters;
if (!isNewIdentifierLocation) {
// This actually always exists although it's optional in the type, at least in ts 5.6,
// so our commit characters are mostly fallback for older ts versions
if (defaultCommitCharacters) {
// this is controlled by a vscode setting that isn't available in the ts server so it isn't added to the language service
defaultCommitCharacters?.push('(');
} else {
defaultCommitCharacters = this.commitCharacters;
}
}

return {
checkCommitCharacters: true,
defaultCommitCharacters,
isNewIdentifierLocation
};
}

private getCommitCharacters(entry: ts.CompletionEntry, options: CommitCharactersOptions) {
// https://github.com/microsoft/vscode/blob/d012408e88ffabd6456c367df4d343654da2eb10/extensions/typescript-language-features/src/languageFeatures/completions.ts#L504
if (!options.checkCommitCharacters) {
return undefined;
}

const commitCharacters = entry.commitCharacters;
// Ambient JS word based suggestions
const skipCommitCharacters =
entry.kind === ts.ScriptElementKind.warning ||
entry.kind === ts.ScriptElementKind.string;

if (commitCharacters) {
if (!options.isNewIdentifierLocation && !skipCommitCharacters) {
return commitCharacters.concat('(');
}

return commitCharacters;
}

return skipCommitCharacters ? [] : undefined;
}

private isExistingSvelteComponentImport(
snapshot: SvelteDocumentSnapshot,
name: string,
Expand Down
Loading

0 comments on commit 98f7229

Please sign in to comment.