Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 40 additions & 19 deletions packages/language-server/src/ls-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,20 @@ export interface LSSvelteConfig {
};
}

/**
* A subset of the JS/TS VS Code settings which
* are transformed to ts.UserPreferences.
* It may not be available in other IDEs, that's why the keys are optional.
*/
export interface TSUserConfig {
preferences?: TsUserPreferencesConfig;
suggest?: TSSuggestConfig;
}

/**
* A subset of the JS/TS VS Code settings which
* are transformed to ts.UserPreferences.
*/
export interface TsUserPreferencesConfig {
importModuleSpecifier: UserPreferences['importModuleSpecifierPreference'];
importModuleSpecifierEnding: UserPreferences['importModuleSpecifierEnding'];
Expand All @@ -177,6 +191,14 @@ export interface TsUserPreferencesConfig {
includePackageJsonAutoImports?: UserPreferences['includePackageJsonAutoImports'];
}

/**
* A subset of the JS/TS VS Code settings which
* are transformed to ts.UserPreferences.
*/
export interface TSSuggestConfig {
autoImports: UserPreferences['includeCompletionsForModuleExports'];
}

export type TsUserConfigLang = 'typescript' | 'javascript';

type DeepPartial<T> = T extends CompilerWarningsSettings
Expand All @@ -189,8 +211,12 @@ export class LSConfigManager {
private config: LSConfig = defaultLSConfig;
private listeners: Array<(config: LSConfigManager) => void> = [];
private tsUserPreferences: Record<TsUserConfigLang, UserPreferences> = {
typescript: {},
javascript: {}
typescript: {
includeCompletionsForModuleExports: true
},
javascript: {
includeCompletionsForModuleExports: true
}
};
private prettierConfig: any = {};
private emmetConfig: EmmetConfiguration = {};
Expand Down Expand Up @@ -258,28 +284,23 @@ export class LSConfigManager {
return this.prettierConfig;
}

updateTsJsUserPreferences(
config: Record<
TsUserConfigLang,
{
preferences: TsUserPreferencesConfig;
}
>
): void {
updateTsJsUserPreferences(config: Record<TsUserConfigLang, TSUserConfig>): void {
(['typescript', 'javascript'] as const).forEach((lang) => {
if (config[lang]?.preferences) {
this._updateTsUserPreferences(lang, config[lang].preferences);
if (config[lang]) {
this._updateTsUserPreferences(lang, config[lang]);
}
});
}

private _updateTsUserPreferences(lang: TsUserConfigLang, config: TsUserPreferencesConfig) {
this.tsUserPreferences[lang] = Object.assign(this.tsUserPreferences[lang], {
importModuleSpecifierPreference: config.importModuleSpecifier,
importModuleSpecifierEnding: config.importModuleSpecifierEnding,
includePackageJsonAutoImports: config.includePackageJsonAutoImports,
quotePreference: config.quoteStyle
} as UserPreferences);
private _updateTsUserPreferences(lang: TsUserConfigLang, config: TSUserConfig) {
this.tsUserPreferences[lang] = {
...this.tsUserPreferences[lang],
importModuleSpecifierPreference: config.preferences?.importModuleSpecifier,
importModuleSpecifierEnding: config.preferences?.importModuleSpecifierEnding,
includePackageJsonAutoImports: config.preferences?.includePackageJsonAutoImports,
quotePreference: config.preferences?.quoteStyle,
includeCompletionsForModuleExports: config.suggest?.autoImports ?? true
};
}

getTsUserPreferences(lang: TsUserConfigLang) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export interface CompletionEntryWithIdentifer extends ts.CompletionEntry, TextDo
type validTriggerCharacter = '.' | '"' | "'" | '`' | '/' | '@' | '<' | '#';

export class CompletionsProviderImpl implements CompletionsProvider<CompletionEntryWithIdentifer> {
constructor(private readonly lsAndTsDocResolver: LSAndTSDocResolver) { }
constructor(private readonly lsAndTsDocResolver: LSAndTSDocResolver) {}

/**
* The language service throws an error if the character is not a valid trigger character.
Expand All @@ -62,7 +62,7 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionEn
return null;
}

const { lang, tsDoc } = this.lsAndTsDocResolver.getLSAndTSDoc(document);
const { lang, tsDoc, userPreferences } = this.lsAndTsDocResolver.getLSAndTSDoc(document);

const filePath = tsDoc.filePath;
if (!filePath) {
Expand Down Expand Up @@ -115,7 +115,7 @@ export class CompletionsProviderImpl implements CompletionsProvider<CompletionEn

const completions =
lang.getCompletionsAtPosition(filePath, offset, {
includeCompletionsForModuleExports: true,
...userPreferences,
triggerCharacter: validTriggerCharacter
})?.entries || [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { CompletionsProviderImpl } from '../../../../src/plugins/typescript/feat
import { LSAndTSDocResolver } from '../../../../src/plugins/typescript/LSAndTSDocResolver';
import { pathToUrl } from '../../../../src/utils';
import { CodeActionsProviderImpl } from '../../../../src/plugins/typescript/features/CodeActionsProvider';
import { LSConfigManager, TsUserPreferencesConfig } from '../../../../src/ls-config';
import { LSConfigManager, TSUserConfig } from '../../../../src/ls-config';

const testFilesDir = join(__dirname, '..', 'testfiles', 'preferences');

Expand All @@ -35,19 +35,27 @@ describe('ts user preferences', () => {

const expectedImportEdit = "import { definition } from '~/definition/index';";

function getPreferences(): TsUserPreferencesConfig {
function getPreferences(): TSUserConfig {
return {
importModuleSpecifier: 'non-relative',
importModuleSpecifierEnding: 'index',
quoteStyle: 'single'
preferences: {
importModuleSpecifier: 'non-relative',
importModuleSpecifierEnding: 'index',
quoteStyle: 'single'
},
suggest: {
autoImports: true
}
};
}

function createLSAndTSDocResolver(docManager: DocumentManager) {
function createLSAndTSDocResolver(
docManager: DocumentManager,
preferences?: Partial<TSUserConfig>
) {
const configManager = new LSConfigManager();
configManager.updateTsJsUserPreferences({
typescript: { preferences: getPreferences() },
javascript: { preferences: {} as any }
typescript: { ...getPreferences(), ...preferences },
javascript: { ...getPreferences(), ...preferences }
});
return new LSAndTSDocResolver(docManager, [pathToUrl(testFilesDir)], configManager);
}
Expand Down Expand Up @@ -102,4 +110,20 @@ describe('ts user preferences', () => {
]
});
});

it('provides auto import suggestions according to preferences', async () => {
const { docManager, document } = setup('code-action.svelte');
const lsAndTsDocResolver = createLSAndTSDocResolver(docManager, {
suggest: { autoImports: false }
});
const completionProvider = new CompletionsProviderImpl(lsAndTsDocResolver);

const completions = await completionProvider.getCompletions(
document,
Position.create(1, 14)
);

const item = completions?.items.find((item) => item.label === 'definition');
assert.strictEqual(item, undefined, 'Expected no auto import suggestions');
});
});
2 changes: 1 addition & 1 deletion packages/svelte-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ function addRenameFileListener(getLS: () => LanguageClient) {
// In the meantime, just assume it's a single entry and simplify the
// rest of the logic that way.
{
oldUri: oldUri,
oldUri,
newUri: evt.files[0].newUri.toString(true)
}
);
Expand Down