mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-17 21:06:50 -05:00
Add exported members of all project files in the global completion list (#19069)
* checker.ts: Remove null check on symbols * tsserverProjectSystem.ts: add two tests * client.ts, completions.ts, types.ts: Add codeActions member to CompletionEntryDetails * protocol.ts, session.ts: Add codeActions member to CompletionEntryDetails protocol * protocol.ts, session.ts, types.ts: add hasAction to CompletionEntry * session.ts, services.ts, types.ts: Add formattingOptions parameter to getCompletionEntryDetails * completions.ts: define SymbolOriginInfo type * completions.ts, services.ts: Add allSourceFiles parameter to getCompletionsAtPosition * completions.ts, services.ts: Plumb allSourceFiles into new function getSymbolsFromOtherSourceFileExports inside getCompletionData * completions.ts: add symbolToOriginInfoMap parameter to getCompletionEntriesFromSymbols and to return value of getCompletionData * utilities.ts: Add getOtherModuleSymbols, getUniqueSymbolIdAsString, getUniqueSymbolId * completions.ts: Set CompletionEntry.hasAction when symbol is found in symbolToOriginInfoMap (meaning there's an import action) * completions.ts: Populate list with possible exports (implement getSymbolsFromOtherSourceFileExports) * completions.ts, services.ts: Plumb host and rulesProvider into getCompletionEntryDetails * completions.ts: Add TODO comment * importFixes.ts: Add types ImportDeclarationMap and ImportCodeFixContext * Move getImportDeclarations into getCodeActionForImport, immediately after the implementation * importFixes.ts: Move createChangeTracker into getCodeActionForImport, immediately after getImportDeclarations * importFixes.ts: Add convertToImportCodeFixContext function and reference it from the getCodeActions lambda * importFixes.ts: Add context: ImportCodeFixContext parameter to getCodeActionForImport, update call sites, destructure it, use compilerOptions in getModuleSpecifierForNewImport * importFixes.ts: Remove moduleSymbol parameter from getImportDeclarations and use the ambient one * importFixes.ts: Use cachedImportDeclarations from context in getCodeActionForImport * importFixes.ts: Move createCodeAction out, immediately above convertToImportCodeFixContext * Move the declaration for lastImportDeclaration out of the getCodeActions lambda into getCodeActionForImport * importFixes.ts: Use symbolToken in getCodeActionForImport * importFixes.ts: Remove useCaseSensitiveFileNames altogether from getCodeActions lambda * importFixes.ts: Remove local getUniqueSymbolId function and add checker parameter to calls to it * importFixes.ts: Move getCodeActionForImport out into an export, immediately below convertToImportCodeFixContext * completions.ts: In getCompletionEntryDetails, if there's symbolOriginInfo, call getCodeActionForImport * importFixes.ts: Create and use importFixContext within getCodeActions lambda * importFixes.ts: Use local newLineCharacter instead of context.newLineCharacter in getCodeActionForImport * importFixes.ts: Use local host instead of context.host in getCodeActionForImport * importFixes.ts: Remove dummy getCanonicalFileName line * Filter symbols after gathering exports instead of before * Lint * Test, fix bugs, refactor * Suggestions from code review * Update api baseline * Fix bug if previousToken is not an Identifier * Replace `startsWith` with `stringContainsCharactersInOrder`
This commit is contained in:
@@ -198,7 +198,9 @@ namespace ts.server {
|
||||
const request = this.processRequest<protocol.CompletionDetailsRequest>(CommandNames.CompletionDetails, args);
|
||||
const response = this.processResponse<protocol.CompletionDetailsResponse>(request);
|
||||
Debug.assert(response.body.length === 1, "Unexpected length of completion details response body.");
|
||||
return response.body[0];
|
||||
|
||||
const convertedCodeActions = map(response.body[0].codeActions, codeAction => this.convertCodeActions(codeAction, fileName));
|
||||
return { ...response.body[0], codeActions: convertedCodeActions };
|
||||
}
|
||||
|
||||
getCompletionEntrySymbol(_fileName: string, _position: number, _entryName: string): Symbol {
|
||||
|
||||
@@ -1658,6 +1658,11 @@ namespace ts.server.protocol {
|
||||
* this span should be used instead of the default one.
|
||||
*/
|
||||
replacementSpan?: TextSpan;
|
||||
/**
|
||||
* Indicates whether commiting this completion entry will require additional code actions to be
|
||||
* made to avoid errors. The CompletionEntryDetails will have these actions.
|
||||
*/
|
||||
hasAction?: true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1690,6 +1695,11 @@ namespace ts.server.protocol {
|
||||
* JSDoc tags for the symbol.
|
||||
*/
|
||||
tags: JSDocTagInfo[];
|
||||
|
||||
/**
|
||||
* The associated code actions for this entry
|
||||
*/
|
||||
codeActions?: CodeAction[];
|
||||
}
|
||||
|
||||
export interface CompletionsResponse extends Response {
|
||||
|
||||
@@ -1178,11 +1178,12 @@ namespace ts.server {
|
||||
|
||||
const completions = project.getLanguageService().getCompletionsAtPosition(file, position);
|
||||
if (simplifiedResult) {
|
||||
return mapDefined(completions && completions.entries, entry => {
|
||||
return mapDefined<CompletionEntry, protocol.CompletionEntry>(completions && completions.entries, entry => {
|
||||
if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) === 0)) {
|
||||
const { name, kind, kindModifiers, sortText, replacementSpan } = entry;
|
||||
const { name, kind, kindModifiers, sortText, replacementSpan, hasAction } = entry;
|
||||
const convertedSpan = replacementSpan ? this.decorateSpan(replacementSpan, scriptInfo) : undefined;
|
||||
return { name, kind, kindModifiers, sortText, replacementSpan: convertedSpan };
|
||||
// Use `hasAction || undefined` to avoid serializing `false`.
|
||||
return { name, kind, kindModifiers, sortText, replacementSpan: convertedSpan, hasAction: hasAction || undefined };
|
||||
}
|
||||
}).sort((a, b) => compareStrings(a.name, b.name));
|
||||
}
|
||||
@@ -1193,10 +1194,20 @@ namespace ts.server {
|
||||
|
||||
private getCompletionEntryDetails(args: protocol.CompletionDetailsRequestArgs): ReadonlyArray<protocol.CompletionEntryDetails> {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
|
||||
const position = this.getPosition(args, scriptInfo);
|
||||
const formattingOptions = project.projectService.getFormatCodeOptions(file);
|
||||
|
||||
return mapDefined(args.entryNames, entryName =>
|
||||
project.getLanguageService().getCompletionEntryDetails(file, position, entryName));
|
||||
return mapDefined(args.entryNames, entryName => {
|
||||
const details = project.getLanguageService().getCompletionEntryDetails(file, position, entryName, formattingOptions);
|
||||
if (details) {
|
||||
const mappedCodeActions = map(details.codeActions, action => this.mapCodeAction(action, scriptInfo));
|
||||
return { ...details, codeActions: mappedCodeActions };
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getCompileOnSaveAffectedFileList(args: protocol.FileRequestArgs): ReadonlyArray<protocol.CompileOnSaveAffectedFileListSingleProject> {
|
||||
|
||||
Reference in New Issue
Block a user