mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-22 12:03:44 -05:00
For getCompletionsAtPosition, require a flag to provide completions with code actions (#19687)
* For getCompletionsAtPosition, require a flag to provide completions with code actions * Change name * Increase API version * Update API baselines * Add comment * Update API baseline
This commit is contained in:
@@ -855,8 +855,8 @@ namespace FourSlash {
|
||||
});
|
||||
}
|
||||
|
||||
public verifyCompletionListContains(entryId: ts.Completions.CompletionEntryIdentifier, text?: string, documentation?: string, kind?: string, spanIndex?: number, hasAction?: boolean) {
|
||||
const completions = this.getCompletionListAtCaret();
|
||||
public verifyCompletionListContains(entryId: ts.Completions.CompletionEntryIdentifier, text?: string, documentation?: string, kind?: string, spanIndex?: number, hasAction?: boolean, options?: ts.GetCompletionsAtPositionOptions) {
|
||||
const completions = this.getCompletionListAtCaret(options);
|
||||
if (completions) {
|
||||
this.assertItemInCompletionList(completions.entries, entryId, text, documentation, kind, spanIndex, hasAction);
|
||||
}
|
||||
@@ -876,13 +876,13 @@ namespace FourSlash {
|
||||
* @param expectedKind the kind of symbol (see ScriptElementKind)
|
||||
* @param spanIndex the index of the range that the completion item's replacement text span should match
|
||||
*/
|
||||
public verifyCompletionListDoesNotContain(entryId: ts.Completions.CompletionEntryIdentifier, expectedText?: string, expectedDocumentation?: string, expectedKind?: string, spanIndex?: number) {
|
||||
public verifyCompletionListDoesNotContain(entryId: ts.Completions.CompletionEntryIdentifier, expectedText?: string, expectedDocumentation?: string, expectedKind?: string, spanIndex?: number, options?: ts.GetCompletionsAtPositionOptions) {
|
||||
let replacementSpan: ts.TextSpan;
|
||||
if (spanIndex !== undefined) {
|
||||
replacementSpan = this.getTextSpanForRangeAtIndex(spanIndex);
|
||||
}
|
||||
|
||||
const completions = this.getCompletionListAtCaret();
|
||||
const completions = this.getCompletionListAtCaret(options);
|
||||
if (completions) {
|
||||
let filterCompletions = completions.entries.filter(e => e.name === entryId.name && e.source === entryId.source);
|
||||
filterCompletions = expectedKind ? filterCompletions.filter(e => e.kind === expectedKind) : filterCompletions;
|
||||
@@ -1195,11 +1195,11 @@ Actual: ${stringify(fullActual)}`);
|
||||
this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(references)})`);
|
||||
}
|
||||
|
||||
private getCompletionListAtCaret() {
|
||||
return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
private getCompletionListAtCaret(options?: ts.GetCompletionsAtPositionOptions): ts.CompletionInfo {
|
||||
return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, options);
|
||||
}
|
||||
|
||||
private getCompletionEntryDetails(entryName: string, source?: string) {
|
||||
private getCompletionEntryDetails(entryName: string, source?: string): ts.CompletionEntryDetails {
|
||||
return this.languageService.getCompletionEntryDetails(this.activeFile.fileName, this.currentCaretPosition, entryName, this.formatCodeSettings, source);
|
||||
}
|
||||
|
||||
@@ -1790,7 +1790,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
}
|
||||
else if (prevChar === " " && /A-Za-z_/.test(ch)) {
|
||||
/* Completions */
|
||||
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset);
|
||||
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset, { includeExternalModuleExports: false });
|
||||
}
|
||||
|
||||
if (i % checkCadence === 0) {
|
||||
@@ -2365,7 +2365,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
public applyCodeActionFromCompletion(markerName: string, options: FourSlashInterface.VerifyCompletionActionOptions) {
|
||||
this.goToMarker(markerName);
|
||||
|
||||
const actualCompletion = this.getCompletionListAtCaret().entries.find(e => e.name === options.name && e.source === options.source);
|
||||
const actualCompletion = this.getCompletionListAtCaret({ includeExternalModuleExports: true }).entries.find(e => e.name === options.name && e.source === options.source);
|
||||
|
||||
if (!actualCompletion.hasAction) {
|
||||
this.raiseError(`Completion for ${options.name} does not have an associated action.`);
|
||||
@@ -3803,15 +3803,15 @@ namespace FourSlashInterface {
|
||||
|
||||
// Verifies the completion list contains the specified symbol. The
|
||||
// completion list is brought up if necessary
|
||||
public completionListContains(entryId: string | ts.Completions.CompletionEntryIdentifier, text?: string, documentation?: string, kind?: string, spanIndex?: number, hasAction?: boolean) {
|
||||
public completionListContains(entryId: string | ts.Completions.CompletionEntryIdentifier, text?: string, documentation?: string, kind?: string, spanIndex?: number, hasAction?: boolean, options?: ts.GetCompletionsAtPositionOptions) {
|
||||
if (typeof entryId === "string") {
|
||||
entryId = { name: entryId, source: undefined };
|
||||
}
|
||||
if (this.negative) {
|
||||
this.state.verifyCompletionListDoesNotContain(entryId, text, documentation, kind, spanIndex);
|
||||
this.state.verifyCompletionListDoesNotContain(entryId, text, documentation, kind, spanIndex, options);
|
||||
}
|
||||
else {
|
||||
this.state.verifyCompletionListContains(entryId, text, documentation, kind, spanIndex, hasAction);
|
||||
this.state.verifyCompletionListContains(entryId, text, documentation, kind, spanIndex, hasAction, options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -413,8 +413,8 @@ namespace Harness.LanguageService {
|
||||
getEncodedSemanticClassifications(fileName: string, span: ts.TextSpan): ts.Classifications {
|
||||
return unwrapJSONCallResult(this.shim.getEncodedSemanticClassifications(fileName, span.start, span.length));
|
||||
}
|
||||
getCompletionsAtPosition(fileName: string, position: number): ts.CompletionInfo {
|
||||
return unwrapJSONCallResult(this.shim.getCompletionsAtPosition(fileName, position));
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: ts.GetCompletionsAtPositionOptions | undefined): ts.CompletionInfo {
|
||||
return unwrapJSONCallResult(this.shim.getCompletionsAtPosition(fileName, position, options));
|
||||
}
|
||||
getCompletionEntryDetails(fileName: string, position: number, entryName: string, options: ts.FormatCodeOptions | undefined, source: string | undefined): ts.CompletionEntryDetails {
|
||||
return unwrapJSONCallResult(this.shim.getCompletionEntryDetails(fileName, position, entryName, JSON.stringify(options), source));
|
||||
|
||||
@@ -1248,13 +1248,13 @@ namespace ts.projectSystem {
|
||||
service.checkNumberOfProjects({ externalProjects: 1 });
|
||||
checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]);
|
||||
|
||||
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2);
|
||||
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, { includeExternalModuleExports: false });
|
||||
// should contain completions for string
|
||||
assert.isTrue(completions1.entries.some(e => e.name === "charAt"), "should contain 'charAt'");
|
||||
assert.isFalse(completions1.entries.some(e => e.name === "toExponential"), "should not contain 'toExponential'");
|
||||
|
||||
service.closeClientFile(f2.path);
|
||||
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2);
|
||||
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, { includeExternalModuleExports: false });
|
||||
// should contain completions for string
|
||||
assert.isFalse(completions2.entries.some(e => e.name === "charAt"), "should not contain 'charAt'");
|
||||
assert.isTrue(completions2.entries.some(e => e.name === "toExponential"), "should contain 'toExponential'");
|
||||
@@ -1280,11 +1280,11 @@ namespace ts.projectSystem {
|
||||
service.checkNumberOfProjects({ externalProjects: 1 });
|
||||
checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]);
|
||||
|
||||
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0);
|
||||
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, { includeExternalModuleExports: false });
|
||||
assert.isTrue(completions1.entries.some(e => e.name === "somelongname"), "should contain 'somelongname'");
|
||||
|
||||
service.closeClientFile(f2.path);
|
||||
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0);
|
||||
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, { includeExternalModuleExports: false });
|
||||
assert.isFalse(completions2.entries.some(e => e.name === "somelongname"), "should not contain 'somelongname'");
|
||||
const sf2 = service.externalProjects[0].getLanguageService().getProgram().getSourceFile(f2.path);
|
||||
assert.equal(sf2.text, "");
|
||||
@@ -1845,7 +1845,7 @@ namespace ts.projectSystem {
|
||||
|
||||
// Check identifiers defined in HTML content are available in .ts file
|
||||
const project = configuredProjectAt(projectService, 0);
|
||||
let completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 1);
|
||||
let completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 1, { includeExternalModuleExports: false });
|
||||
assert(completions && completions.entries[0].name === "hello", `expected entry hello to be in completion list`);
|
||||
|
||||
// Close HTML file
|
||||
@@ -1859,7 +1859,7 @@ namespace ts.projectSystem {
|
||||
checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]);
|
||||
|
||||
// Check identifiers defined in HTML content are not available in .ts file
|
||||
completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 5);
|
||||
completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 5, { includeExternalModuleExports: false });
|
||||
assert(completions && completions.entries[0].name !== "hello", `unexpected hello entry in completion list`);
|
||||
});
|
||||
|
||||
|
||||
@@ -170,8 +170,8 @@ namespace ts.server {
|
||||
};
|
||||
}
|
||||
|
||||
getCompletionsAtPosition(fileName: string, position: number): CompletionInfo {
|
||||
const args: protocol.CompletionsRequestArgs = this.createFileLocationRequestArgs(fileName, position);
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo {
|
||||
const args: protocol.CompletionsRequestArgs = { ...this.createFileLocationRequestArgs(fileName, position), ...options };
|
||||
|
||||
const request = this.processRequest<protocol.CompletionsRequest>(CommandNames.Completions, args);
|
||||
const response = this.processResponse<protocol.CompletionsResponse>(request);
|
||||
|
||||
@@ -1619,6 +1619,11 @@ namespace ts.server.protocol {
|
||||
* Optional prefix to apply to possible completions.
|
||||
*/
|
||||
prefix?: string;
|
||||
/**
|
||||
* If enabled, TypeScript will search through all external modules' exports and add them to the completions list.
|
||||
* This affects lone identifier completions but not completions on the right hand side of `obj.`.
|
||||
*/
|
||||
includeExternalModuleExports: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1200,10 +1200,10 @@ namespace ts.server {
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
|
||||
const position = this.getPosition(args, scriptInfo);
|
||||
|
||||
const completions = project.getLanguageService().getCompletionsAtPosition(file, position);
|
||||
const completions = project.getLanguageService().getCompletionsAtPosition(file, position, args);
|
||||
if (simplifiedResult) {
|
||||
return mapDefined<CompletionEntry, protocol.CompletionEntry>(completions && completions.entries, entry => {
|
||||
if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) === 0)) {
|
||||
if (completions.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) {
|
||||
const { name, kind, kindModifiers, sortText, replacementSpan, hasAction, source } = entry;
|
||||
const convertedSpan = replacementSpan ? this.toLocationTextSpan(replacementSpan, scriptInfo) : undefined;
|
||||
// Use `hasAction || undefined` to avoid serializing `false`.
|
||||
@@ -1831,10 +1831,10 @@ namespace ts.server {
|
||||
[CommandNames.FormatRangeFull]: (request: protocol.FormatRequest) => {
|
||||
return this.requiredResponse(this.getFormattingEditsForRangeFull(request.arguments));
|
||||
},
|
||||
[CommandNames.Completions]: (request: protocol.CompletionDetailsRequest) => {
|
||||
[CommandNames.Completions]: (request: protocol.CompletionsRequest) => {
|
||||
return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.CompletionsFull]: (request: protocol.CompletionDetailsRequest) => {
|
||||
[CommandNames.CompletionsFull]: (request: protocol.CompletionsRequest) => {
|
||||
return this.requiredResponse(this.getCompletions(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.CompletionDetails]: (request: protocol.CompletionDetailsRequest) => {
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace ts.Completions {
|
||||
sourceFile: SourceFile,
|
||||
position: number,
|
||||
allSourceFiles: ReadonlyArray<SourceFile>,
|
||||
options: GetCompletionsAtPositionOptions,
|
||||
): CompletionInfo | undefined {
|
||||
if (isInReferenceComment(sourceFile, position)) {
|
||||
const entries = PathCompletions.getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host);
|
||||
@@ -38,7 +39,7 @@ namespace ts.Completions {
|
||||
return getStringLiteralCompletionEntries(sourceFile, position, typeChecker, compilerOptions, host, log);
|
||||
}
|
||||
|
||||
const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles);
|
||||
const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, options);
|
||||
if (!completionData) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -380,7 +381,7 @@ namespace ts.Completions {
|
||||
{ name, source }: CompletionEntryIdentifier,
|
||||
allSourceFiles: ReadonlyArray<SourceFile>,
|
||||
): { type: "symbol", symbol: Symbol, location: Node, symbolToOriginInfoMap: SymbolOriginInfoMap } | { type: "request", request: Request } | { type: "none" } {
|
||||
const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles);
|
||||
const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, { includeExternalModuleExports: true });
|
||||
if (!completionData) {
|
||||
return { type: "none" };
|
||||
}
|
||||
@@ -521,6 +522,7 @@ namespace ts.Completions {
|
||||
sourceFile: SourceFile,
|
||||
position: number,
|
||||
allSourceFiles: ReadonlyArray<SourceFile>,
|
||||
options: GetCompletionsAtPositionOptions,
|
||||
): CompletionData | undefined {
|
||||
const isJavaScriptFile = isSourceFileJavaScript(sourceFile);
|
||||
|
||||
@@ -918,7 +920,9 @@ namespace ts.Completions {
|
||||
const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;
|
||||
|
||||
symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
|
||||
getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : "");
|
||||
if (options.includeExternalModuleExports) {
|
||||
getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : "");
|
||||
}
|
||||
filterGlobalCompletion(symbols);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
namespace ts {
|
||||
/** The version of the language service API */
|
||||
export const servicesVersion = "0.6";
|
||||
export const servicesVersion = "0.7";
|
||||
|
||||
/* @internal */
|
||||
let ruleProvider: formatting.RulesProvider;
|
||||
@@ -1326,9 +1326,17 @@ namespace ts {
|
||||
return [...program.getOptionsDiagnostics(cancellationToken), ...program.getGlobalDiagnostics(cancellationToken)];
|
||||
}
|
||||
|
||||
function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo {
|
||||
function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = { includeExternalModuleExports: false }): CompletionInfo {
|
||||
synchronizeHostData();
|
||||
return Completions.getCompletionsAtPosition(host, program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, program.getSourceFiles());
|
||||
return Completions.getCompletionsAtPosition(
|
||||
host,
|
||||
program.getTypeChecker(),
|
||||
log,
|
||||
program.getCompilerOptions(),
|
||||
getValidSourceFile(fileName),
|
||||
position,
|
||||
program.getSourceFiles(),
|
||||
options);
|
||||
}
|
||||
|
||||
function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions?: FormatCodeSettings, source?: string): CompletionEntryDetails {
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace ts {
|
||||
getEncodedSyntacticClassifications(fileName: string, start: number, length: number): string;
|
||||
getEncodedSemanticClassifications(fileName: string, start: number, length: number): string;
|
||||
|
||||
getCompletionsAtPosition(fileName: string, position: number): string;
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): string;
|
||||
getCompletionEntryDetails(fileName: string, position: number, entryName: string, options: string/*Services.FormatCodeOptions*/, source: string | undefined): string;
|
||||
|
||||
getQuickInfoAtPosition(fileName: string, position: number): string;
|
||||
@@ -898,10 +898,10 @@ namespace ts {
|
||||
* to provide at the given source position and providing a member completion
|
||||
* list if requested.
|
||||
*/
|
||||
public getCompletionsAtPosition(fileName: string, position: number) {
|
||||
public getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined) {
|
||||
return this.forwardJSONCall(
|
||||
`getCompletionsAtPosition('${fileName}', ${position})`,
|
||||
() => this.languageService.getCompletionsAtPosition(fileName, position)
|
||||
`getCompletionsAtPosition('${fileName}', ${position}, ${options})`,
|
||||
() => this.languageService.getCompletionsAtPosition(fileName, position, options)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace ts {
|
||||
getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications;
|
||||
getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications;
|
||||
|
||||
getCompletionsAtPosition(fileName: string, position: number): CompletionInfo;
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): CompletionInfo;
|
||||
// "options" and "source" are optional only for backwards-compatibility
|
||||
getCompletionEntryDetails(
|
||||
fileName: string,
|
||||
@@ -310,6 +310,10 @@ namespace ts {
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export interface GetCompletionsAtPositionOptions {
|
||||
includeExternalModuleExports: boolean;
|
||||
}
|
||||
|
||||
export interface ApplyCodeActionCommandResult {
|
||||
successMessage: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user