mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Gabritto/semicolons (#46832)
* call formatter in completions * fixes * add test * update api baselines * fix createModifiersFromModifierFlag to not return empty array
This commit is contained in:
parent
f4e1efbc29
commit
404a7d602d
@ -1940,7 +1940,7 @@ namespace ts {
|
||||
emitPlaceholder(hint, node, snippet);
|
||||
break;
|
||||
case SnippetKind.TabStop:
|
||||
emitTabStop(snippet);
|
||||
emitTabStop(hint, node, snippet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1952,7 +1952,12 @@ namespace ts {
|
||||
// `${2:...}`
|
||||
}
|
||||
|
||||
function emitTabStop(snippet: TabStop) {
|
||||
function emitTabStop(hint: EmitHint, node: Node, snippet: TabStop) {
|
||||
// A tab stop should only be attached to an empty node, i.e. a node that doesn't emit any text.
|
||||
Debug.assert(node.kind === SyntaxKind.EmptyStatement,
|
||||
`A tab stop cannot be attached to a node of kind ${Debug.formatSyntaxKind(node.kind)}.`);
|
||||
Debug.assert(hint !== EmitHint.EmbeddedStatement,
|
||||
`A tab stop cannot be attached to an embedded statement.`);
|
||||
nonEscapingWrite(`\$${snippet.order}`);
|
||||
}
|
||||
|
||||
|
||||
@ -1075,7 +1075,7 @@ namespace ts {
|
||||
if (flags & ModifierFlags.Override) result.push(createModifier(SyntaxKind.OverrideKeyword));
|
||||
if (flags & ModifierFlags.Readonly) result.push(createModifier(SyntaxKind.ReadonlyKeyword));
|
||||
if (flags & ModifierFlags.Async) result.push(createModifier(SyntaxKind.AsyncKeyword));
|
||||
return result;
|
||||
return result.length ? result : undefined;
|
||||
}
|
||||
|
||||
//
|
||||
@ -6080,32 +6080,36 @@ namespace ts {
|
||||
|
||||
function updateModifiers<T extends HasModifiers>(node: T, modifiers: readonly Modifier[] | ModifierFlags): T;
|
||||
function updateModifiers(node: HasModifiers, modifiers: readonly Modifier[] | ModifierFlags) {
|
||||
let modifierArray;
|
||||
if (typeof modifiers === "number") {
|
||||
modifiers = createModifiersFromModifierFlags(modifiers);
|
||||
modifierArray = createModifiersFromModifierFlags(modifiers);
|
||||
}
|
||||
return isParameter(node) ? updateParameterDeclaration(node, node.decorators, modifiers, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) :
|
||||
isPropertySignature(node) ? updatePropertySignature(node, modifiers, node.name, node.questionToken, node.type) :
|
||||
isPropertyDeclaration(node) ? updatePropertyDeclaration(node, node.decorators, modifiers, node.name, node.questionToken ?? node.exclamationToken, node.type, node.initializer) :
|
||||
isMethodSignature(node) ? updateMethodSignature(node, modifiers, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) :
|
||||
isMethodDeclaration(node) ? updateMethodDeclaration(node, node.decorators, modifiers, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) :
|
||||
isConstructorDeclaration(node) ? updateConstructorDeclaration(node, node.decorators, modifiers, node.parameters, node.body) :
|
||||
isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.type, node.body) :
|
||||
isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.body) :
|
||||
isIndexSignatureDeclaration(node) ? updateIndexSignature(node, node.decorators, modifiers, node.parameters, node.type) :
|
||||
isFunctionExpression(node) ? updateFunctionExpression(node, modifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
|
||||
isArrowFunction(node) ? updateArrowFunction(node, modifiers, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body) :
|
||||
isClassExpression(node) ? updateClassExpression(node, node.decorators, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members) :
|
||||
isVariableStatement(node) ? updateVariableStatement(node, modifiers, node.declarationList) :
|
||||
isFunctionDeclaration(node) ? updateFunctionDeclaration(node, node.decorators, modifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
|
||||
isClassDeclaration(node) ? updateClassDeclaration(node, node.decorators, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members) :
|
||||
isInterfaceDeclaration(node) ? updateInterfaceDeclaration(node, node.decorators, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members) :
|
||||
isTypeAliasDeclaration(node) ? updateTypeAliasDeclaration(node, node.decorators, modifiers, node.name, node.typeParameters, node.type) :
|
||||
isEnumDeclaration(node) ? updateEnumDeclaration(node, node.decorators, modifiers, node.name, node.members) :
|
||||
isModuleDeclaration(node) ? updateModuleDeclaration(node, node.decorators, modifiers, node.name, node.body) :
|
||||
isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, node.decorators, modifiers, node.isTypeOnly, node.name, node.moduleReference) :
|
||||
isImportDeclaration(node) ? updateImportDeclaration(node, node.decorators, modifiers, node.importClause, node.moduleSpecifier, node.assertClause) :
|
||||
isExportAssignment(node) ? updateExportAssignment(node, node.decorators, modifiers, node.expression) :
|
||||
isExportDeclaration(node) ? updateExportDeclaration(node, node.decorators, modifiers, node.isTypeOnly, node.exportClause, node.moduleSpecifier, node.assertClause) :
|
||||
else {
|
||||
modifierArray = modifiers;
|
||||
}
|
||||
return isParameter(node) ? updateParameterDeclaration(node, node.decorators, modifierArray, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) :
|
||||
isPropertySignature(node) ? updatePropertySignature(node, modifierArray, node.name, node.questionToken, node.type) :
|
||||
isPropertyDeclaration(node) ? updatePropertyDeclaration(node, node.decorators, modifierArray, node.name, node.questionToken ?? node.exclamationToken, node.type, node.initializer) :
|
||||
isMethodSignature(node) ? updateMethodSignature(node, modifierArray, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) :
|
||||
isMethodDeclaration(node) ? updateMethodDeclaration(node, node.decorators, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) :
|
||||
isConstructorDeclaration(node) ? updateConstructorDeclaration(node, node.decorators, modifierArray, node.parameters, node.body) :
|
||||
isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.type, node.body) :
|
||||
isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.body) :
|
||||
isIndexSignatureDeclaration(node) ? updateIndexSignature(node, node.decorators, modifierArray, node.parameters, node.type) :
|
||||
isFunctionExpression(node) ? updateFunctionExpression(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
|
||||
isArrowFunction(node) ? updateArrowFunction(node, modifierArray, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body) :
|
||||
isClassExpression(node) ? updateClassExpression(node, node.decorators, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) :
|
||||
isVariableStatement(node) ? updateVariableStatement(node, modifierArray, node.declarationList) :
|
||||
isFunctionDeclaration(node) ? updateFunctionDeclaration(node, node.decorators, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
|
||||
isClassDeclaration(node) ? updateClassDeclaration(node, node.decorators, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) :
|
||||
isInterfaceDeclaration(node) ? updateInterfaceDeclaration(node, node.decorators, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) :
|
||||
isTypeAliasDeclaration(node) ? updateTypeAliasDeclaration(node, node.decorators, modifierArray, node.name, node.typeParameters, node.type) :
|
||||
isEnumDeclaration(node) ? updateEnumDeclaration(node, node.decorators, modifierArray, node.name, node.members) :
|
||||
isModuleDeclaration(node) ? updateModuleDeclaration(node, node.decorators, modifierArray, node.name, node.body) :
|
||||
isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, node.decorators, modifierArray, node.isTypeOnly, node.name, node.moduleReference) :
|
||||
isImportDeclaration(node) ? updateImportDeclaration(node, node.decorators, modifierArray, node.importClause, node.moduleSpecifier, node.assertClause) :
|
||||
isExportAssignment(node) ? updateExportAssignment(node, node.decorators, modifierArray, node.expression) :
|
||||
isExportDeclaration(node) ? updateExportDeclaration(node, node.decorators, modifierArray, node.isTypeOnly, node.exportClause, node.moduleSpecifier, node.assertClause) :
|
||||
Debug.assertNever(node);
|
||||
}
|
||||
|
||||
|
||||
@ -1610,7 +1610,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Elide "public" modifier, as it is the default
|
||||
function maskModifiers(node: Node, modifierMask?: ModifierFlags, modifierAdditions?: ModifierFlags): Modifier[] {
|
||||
function maskModifiers(node: Node, modifierMask?: ModifierFlags, modifierAdditions?: ModifierFlags): Modifier[] | undefined {
|
||||
return factory.createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions));
|
||||
}
|
||||
|
||||
|
||||
@ -7169,7 +7169,7 @@ namespace ts {
|
||||
//
|
||||
|
||||
createModifier<T extends ModifierSyntaxKind>(kind: T): ModifierToken<T>;
|
||||
createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[];
|
||||
createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[] | undefined;
|
||||
|
||||
//
|
||||
// Names
|
||||
@ -7841,7 +7841,7 @@ namespace ts {
|
||||
* - *DO NOT USE THIS* if a more appropriate function is available.
|
||||
*/
|
||||
/* @internal */ cloneNode<T extends Node | undefined>(node: T): T;
|
||||
/* @internal */ updateModifiers<T extends HasModifiers>(node: T, modifiers: readonly Modifier[] | ModifierFlags): T;
|
||||
/* @internal */ updateModifiers<T extends HasModifiers>(node: T, modifiers: readonly Modifier[] | ModifierFlags | undefined): T;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@ -1348,7 +1348,11 @@ namespace FourSlash {
|
||||
if (options) {
|
||||
this.configure(options);
|
||||
}
|
||||
return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, options);
|
||||
return this.languageService.getCompletionsAtPosition(
|
||||
this.activeFile.fileName,
|
||||
this.currentCaretPosition,
|
||||
options,
|
||||
this.formatCodeSettings);
|
||||
}
|
||||
|
||||
private getCompletionEntryDetails(entryName: string, source: string | undefined, data: ts.CompletionEntryData | undefined, preferences?: ts.UserPreferences): ts.CompletionEntryDetails | undefined {
|
||||
|
||||
@ -472,8 +472,8 @@ namespace Harness.LanguageService {
|
||||
const responseFormat = format || ts.SemanticClassificationFormat.Original;
|
||||
return unwrapJSONCallResult(this.shim.getEncodedSemanticClassifications(fileName, span.start, span.length, responseFormat));
|
||||
}
|
||||
getCompletionsAtPosition(fileName: string, position: number, preferences: ts.UserPreferences | undefined): ts.CompletionInfo {
|
||||
return unwrapJSONCallResult(this.shim.getCompletionsAtPosition(fileName, position, preferences));
|
||||
getCompletionsAtPosition(fileName: string, position: number, preferences: ts.UserPreferences | undefined, formattingSettings: ts.FormatCodeSettings | undefined): ts.CompletionInfo {
|
||||
return unwrapJSONCallResult(this.shim.getCompletionsAtPosition(fileName, position, preferences, formattingSettings));
|
||||
}
|
||||
getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: ts.FormatCodeOptions | undefined, source: string | undefined, preferences: ts.UserPreferences | undefined, data: ts.CompletionEntryData | undefined): ts.CompletionEntryDetails {
|
||||
return unwrapJSONCallResult(this.shim.getCompletionEntryDetails(fileName, position, entryName, JSON.stringify(formatOptions), source, preferences, data));
|
||||
|
||||
@ -1842,13 +1842,18 @@ namespace ts.server {
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
const position = this.getPosition(args, scriptInfo);
|
||||
|
||||
const completions = project.getLanguageService().getCompletionsAtPosition(file, position, {
|
||||
...convertUserPreferences(this.getPreferences(file)),
|
||||
triggerCharacter: args.triggerCharacter,
|
||||
triggerKind: args.triggerKind as CompletionTriggerKind | undefined,
|
||||
includeExternalModuleExports: args.includeExternalModuleExports,
|
||||
includeInsertTextCompletions: args.includeInsertTextCompletions
|
||||
});
|
||||
const completions = project.getLanguageService().getCompletionsAtPosition(
|
||||
file,
|
||||
position,
|
||||
{
|
||||
...convertUserPreferences(this.getPreferences(file)),
|
||||
triggerCharacter: args.triggerCharacter,
|
||||
triggerKind: args.triggerKind as CompletionTriggerKind | undefined,
|
||||
includeExternalModuleExports: args.includeExternalModuleExports,
|
||||
includeInsertTextCompletions: args.includeInsertTextCompletions,
|
||||
},
|
||||
project.projectService.getFormatCodeOptions(file),
|
||||
);
|
||||
if (completions === undefined) return undefined;
|
||||
|
||||
if (kind === protocol.CommandTypes.CompletionsFull) return completions;
|
||||
|
||||
@ -229,6 +229,7 @@ namespace ts.Completions {
|
||||
triggerCharacter: CompletionsTriggerCharacter | undefined,
|
||||
completionKind: CompletionTriggerKind | undefined,
|
||||
cancellationToken: CancellationToken,
|
||||
formatContext?: formatting.FormatContext,
|
||||
): CompletionInfo | undefined {
|
||||
const { previousToken } = getRelevantTokens(position, sourceFile);
|
||||
if (triggerCharacter && !isInString(sourceFile, position, previousToken) && !isValidTrigger(sourceFile, triggerCharacter, previousToken, position)) {
|
||||
@ -275,7 +276,7 @@ namespace ts.Completions {
|
||||
|
||||
switch (completionData.kind) {
|
||||
case CompletionDataKind.Data:
|
||||
const response = completionInfoFromData(sourceFile, host, program, compilerOptions, log, completionData, preferences);
|
||||
const response = completionInfoFromData(sourceFile, host, program, compilerOptions, log, completionData, preferences, formatContext);
|
||||
if (response?.isIncomplete) {
|
||||
incompleteCompletionsCache?.set(response);
|
||||
}
|
||||
@ -438,6 +439,7 @@ namespace ts.Completions {
|
||||
log: Log,
|
||||
completionData: CompletionData,
|
||||
preferences: UserPreferences,
|
||||
formatContext: formatting.FormatContext | undefined,
|
||||
): CompletionInfo | undefined {
|
||||
const {
|
||||
symbols,
|
||||
@ -485,6 +487,7 @@ namespace ts.Completions {
|
||||
completionKind,
|
||||
preferences,
|
||||
compilerOptions,
|
||||
formatContext,
|
||||
isTypeOnlyLocation,
|
||||
propertyAccessToConvert,
|
||||
isJsxIdentifierExpected,
|
||||
@ -515,6 +518,7 @@ namespace ts.Completions {
|
||||
completionKind,
|
||||
preferences,
|
||||
compilerOptions,
|
||||
formatContext,
|
||||
isTypeOnlyLocation,
|
||||
propertyAccessToConvert,
|
||||
isJsxIdentifierExpected,
|
||||
@ -664,6 +668,7 @@ namespace ts.Completions {
|
||||
options: CompilerOptions,
|
||||
preferences: UserPreferences,
|
||||
completionKind: CompletionKind,
|
||||
formatContext: formatting.FormatContext | undefined,
|
||||
): CompletionEntry | undefined {
|
||||
let insertText: string | undefined;
|
||||
let replacementSpan = getReplacementSpanForContextToken(replacementToken);
|
||||
@ -732,7 +737,7 @@ namespace ts.Completions {
|
||||
completionKind === CompletionKind.MemberLike &&
|
||||
isClassLikeMemberCompletion(symbol, location)) {
|
||||
let importAdder;
|
||||
({ insertText, isSnippet, importAdder } = getEntryForMemberCompletion(host, program, options, preferences, name, symbol, location, contextToken));
|
||||
({ insertText, isSnippet, importAdder } = getEntryForMemberCompletion(host, program, options, preferences, name, symbol, location, contextToken, formatContext));
|
||||
if (importAdder?.hasFixes()) {
|
||||
hasAction = true;
|
||||
source = CompletionSource.ClassMemberSnippet;
|
||||
@ -858,6 +863,7 @@ namespace ts.Completions {
|
||||
symbol: Symbol,
|
||||
location: Node,
|
||||
contextToken: Node | undefined,
|
||||
formatContext: formatting.FormatContext | undefined,
|
||||
): { insertText: string, isSnippet?: true, importAdder?: codefix.ImportAdder } {
|
||||
const classLikeDeclaration = findAncestor(location, isClassLike);
|
||||
if (!classLikeDeclaration) {
|
||||
@ -878,15 +884,16 @@ namespace ts.Completions {
|
||||
});
|
||||
const importAdder = codefix.createImportAdder(sourceFile, program, preferences, host);
|
||||
|
||||
// Create empty body for possible method implementation.
|
||||
let body;
|
||||
if (preferences.includeCompletionsWithSnippetText) {
|
||||
isSnippet = true;
|
||||
// We are adding a tabstop (i.e. `$0`) in the body of the suggested member,
|
||||
// if it has one, so that the cursor ends up in the body once the completion is inserted.
|
||||
// Note: this assumes we won't have more than one body in the completion nodes, which should be the case.
|
||||
const emptyStatement = factory.createExpressionStatement(factory.createIdentifier(""));
|
||||
setSnippetElement(emptyStatement, { kind: SnippetKind.TabStop, order: 0 });
|
||||
body = factory.createBlock([emptyStatement], /* multiline */ true);
|
||||
const emptyStmt = factory.createEmptyStatement();
|
||||
body = factory.createBlock([emptyStmt], /* multiline */ true);
|
||||
setSnippetElement(emptyStmt, { kind: SnippetKind.TabStop, order: 0 });
|
||||
}
|
||||
else {
|
||||
body = factory.createBlock([], /* multiline */ true);
|
||||
@ -937,7 +944,6 @@ namespace ts.Completions {
|
||||
modifiers = node.modifierFlagsCache | requiredModifiers | presentModifiers;
|
||||
}
|
||||
node = factory.updateModifiers(node, modifiers & (~presentModifiers));
|
||||
|
||||
completionNodes.push(node);
|
||||
},
|
||||
body,
|
||||
@ -945,10 +951,38 @@ namespace ts.Completions {
|
||||
isAbstract);
|
||||
|
||||
if (completionNodes.length) {
|
||||
insertText = printer.printSnippetList(
|
||||
ListFormat.MultiLine | ListFormat.NoTrailingNewLine,
|
||||
factory.createNodeArray(completionNodes),
|
||||
sourceFile);
|
||||
// If we have access to formatting settings, we print the nodes using the emitter,
|
||||
// and then format the printed text.
|
||||
if (formatContext) {
|
||||
const syntheticFile = {
|
||||
text: printer.printSnippetList(
|
||||
ListFormat.MultiLine | ListFormat.NoTrailingNewLine,
|
||||
factory.createNodeArray(completionNodes),
|
||||
sourceFile),
|
||||
getLineAndCharacterOfPosition(pos: number) {
|
||||
return getLineAndCharacterOfPosition(this, pos);
|
||||
},
|
||||
};
|
||||
|
||||
const formatOptions = getFormatCodeSettingsForWriting(formatContext, sourceFile);
|
||||
const changes = flatMap(completionNodes, node => {
|
||||
const nodeWithPos = textChanges.assignPositionsToNode(node);
|
||||
return formatting.formatNodeGivenIndentation(
|
||||
nodeWithPos,
|
||||
syntheticFile,
|
||||
sourceFile.languageVariant,
|
||||
/* indentation */ 0,
|
||||
/* delta */ 0,
|
||||
{ ...formatContext, options: formatOptions });
|
||||
});
|
||||
insertText = textChanges.applyChanges(syntheticFile.text, changes);
|
||||
}
|
||||
else { // Otherwise, just use emitter to print the new nodes.
|
||||
insertText = printer.printSnippetList(
|
||||
ListFormat.MultiLine | ListFormat.NoTrailingNewLine,
|
||||
factory.createNodeArray(completionNodes),
|
||||
sourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
return { insertText, isSnippet, importAdder };
|
||||
@ -998,8 +1032,8 @@ namespace ts.Completions {
|
||||
function createSnippetPrinter(
|
||||
printerOptions: PrinterOptions,
|
||||
) {
|
||||
const printer = createPrinter(printerOptions);
|
||||
const baseWriter = createTextWriter(getNewLineCharacter(printerOptions));
|
||||
const baseWriter = textChanges.createWriter(getNewLineCharacter(printerOptions));
|
||||
const printer = createPrinter(printerOptions, baseWriter);
|
||||
const writer: EmitTextWriter = {
|
||||
...baseWriter,
|
||||
write: s => baseWriter.write(escapeSnippetText(s)),
|
||||
@ -1143,6 +1177,7 @@ namespace ts.Completions {
|
||||
kind: CompletionKind,
|
||||
preferences: UserPreferences,
|
||||
compilerOptions: CompilerOptions,
|
||||
formatContext: formatting.FormatContext | undefined,
|
||||
isTypeOnlyLocation?: boolean,
|
||||
propertyAccessToConvert?: PropertyAccessExpression,
|
||||
jsxIdentifierExpected?: boolean,
|
||||
@ -1192,6 +1227,7 @@ namespace ts.Completions {
|
||||
compilerOptions,
|
||||
preferences,
|
||||
kind,
|
||||
formatContext,
|
||||
);
|
||||
if (!entry) {
|
||||
continue;
|
||||
@ -1470,7 +1506,8 @@ namespace ts.Completions {
|
||||
name,
|
||||
symbol,
|
||||
location,
|
||||
contextToken);
|
||||
contextToken,
|
||||
formatContext);
|
||||
if (importAdder) {
|
||||
const changes = textChanges.ChangeTracker.with(
|
||||
{ host, formatContext, preferences },
|
||||
|
||||
@ -1606,7 +1606,7 @@ namespace ts {
|
||||
return [...program.getOptionsDiagnostics(cancellationToken), ...program.getGlobalDiagnostics(cancellationToken)];
|
||||
}
|
||||
|
||||
function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = emptyOptions): CompletionInfo | undefined {
|
||||
function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = emptyOptions, formattingSettings?: FormatCodeSettings): CompletionInfo | undefined {
|
||||
// Convert from deprecated options names to new names
|
||||
const fullPreferences: UserPreferences = {
|
||||
...identity<UserPreferences>(options), // avoid excess property check
|
||||
@ -1623,7 +1623,8 @@ namespace ts {
|
||||
fullPreferences,
|
||||
options.triggerCharacter,
|
||||
options.triggerKind,
|
||||
cancellationToken);
|
||||
cancellationToken,
|
||||
formattingSettings && formatting.getFormatContext(formattingSettings, host));
|
||||
}
|
||||
|
||||
function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences = emptyOptions, data?: CompletionEntryData): CompletionEntryDetails | undefined {
|
||||
|
||||
@ -151,7 +151,7 @@ namespace ts {
|
||||
getEncodedSyntacticClassifications(fileName: string, start: number, length: number): string;
|
||||
getEncodedSemanticClassifications(fileName: string, start: number, length: number, format?: SemanticClassificationFormat): string;
|
||||
|
||||
getCompletionsAtPosition(fileName: string, position: number, preferences: UserPreferences | undefined): string;
|
||||
getCompletionsAtPosition(fileName: string, position: number, preferences: UserPreferences | undefined, formattingSettings: FormatCodeSettings | undefined): string;
|
||||
getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: string/*Services.FormatCodeOptions*/ | undefined, source: string | undefined, preferences: UserPreferences | undefined, data: CompletionEntryData | undefined): string;
|
||||
|
||||
getQuickInfoAtPosition(fileName: string, position: number): string;
|
||||
@ -956,10 +956,10 @@ namespace ts {
|
||||
* to provide at the given source position and providing a member completion
|
||||
* list if requested.
|
||||
*/
|
||||
public getCompletionsAtPosition(fileName: string, position: number, preferences: GetCompletionsAtPositionOptions | undefined) {
|
||||
public getCompletionsAtPosition(fileName: string, position: number, preferences: GetCompletionsAtPositionOptions | undefined, formattingSettings: FormatCodeSettings | undefined) {
|
||||
return this.forwardJSONCall(
|
||||
`getCompletionsAtPosition('${fileName}', ${position}, ${preferences})`,
|
||||
() => this.languageService.getCompletionsAtPosition(fileName, position, preferences)
|
||||
`getCompletionsAtPosition('${fileName}', ${position}, ${preferences}, ${formattingSettings})`,
|
||||
() => this.languageService.getCompletionsAtPosition(fileName, position, preferences, formattingSettings)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -54,6 +54,7 @@ namespace ts.Completions.StringCompletions {
|
||||
CompletionKind.String,
|
||||
preferences,
|
||||
options,
|
||||
/*formatContext*/ undefined,
|
||||
); // Target will not be used, so arbitrary
|
||||
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: completion.hasIndexSignature, optionalReplacementSpan, entries };
|
||||
}
|
||||
|
||||
@ -1052,15 +1052,6 @@ namespace ts.textChanges {
|
||||
? "" : options.suffix);
|
||||
}
|
||||
|
||||
function getFormatCodeSettingsForWriting({ options }: formatting.FormatContext, sourceFile: SourceFile): FormatCodeSettings {
|
||||
const shouldAutoDetectSemicolonPreference = !options.semicolons || options.semicolons === SemicolonPreference.Ignore;
|
||||
const shouldRemoveSemicolons = options.semicolons === SemicolonPreference.Remove || shouldAutoDetectSemicolonPreference && !probablyUsesSemicolons(sourceFile);
|
||||
return {
|
||||
...options,
|
||||
semicolons: shouldRemoveSemicolons ? SemicolonPreference.Remove : SemicolonPreference.Ignore,
|
||||
};
|
||||
}
|
||||
|
||||
/** Note: this may mutate `nodeIn`. */
|
||||
function getFormattedTextOfNode(nodeIn: Node, sourceFile: SourceFile, pos: number, { indentation, prefix, delta }: InsertNodeOptions, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string {
|
||||
const { node, text } = getNonformattedText(nodeIn, sourceFile, newLineCharacter);
|
||||
@ -1110,7 +1101,7 @@ namespace ts.textChanges {
|
||||
return skipTrivia(s, 0) === s.length;
|
||||
}
|
||||
|
||||
function assignPositionsToNode(node: Node): Node {
|
||||
export function assignPositionsToNode(node: Node): Node {
|
||||
const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode);
|
||||
// create proxy node for non synthesized nodes
|
||||
const newNode = nodeIsSynthesized(visited) ? visited : Object.create(visited) as Node;
|
||||
@ -1131,7 +1122,7 @@ namespace ts.textChanges {
|
||||
|
||||
interface TextChangesWriter extends EmitTextWriter, PrintHandlers {}
|
||||
|
||||
function createWriter(newLine: string): TextChangesWriter {
|
||||
export function createWriter(newLine: string): TextChangesWriter {
|
||||
let lastNonTriviaPosition = 0;
|
||||
|
||||
const writer = createTextWriter(newLine);
|
||||
|
||||
@ -416,8 +416,9 @@ namespace ts {
|
||||
* @param position A zero-based index of the character where you want the entries
|
||||
* @param options An object describing how the request was triggered and what kinds
|
||||
* of code actions can be returned with the completions.
|
||||
* @param formattingSettings settings needed for calling formatting functions.
|
||||
*/
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): WithMetadata<CompletionInfo> | undefined;
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined, formattingSettings?: FormatCodeSettings): WithMetadata<CompletionInfo> | undefined;
|
||||
|
||||
/**
|
||||
* Gets the extended details for a completion entry retrieved from `getCompletionsAtPosition`.
|
||||
|
||||
@ -3299,5 +3299,17 @@ namespace ts {
|
||||
: getLocaleSpecificMessage(diag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get format code settings for a code writing context (e.g. when formatting text changes or completions code).
|
||||
*/
|
||||
export function getFormatCodeSettingsForWriting({ options }: formatting.FormatContext, sourceFile: SourceFile): FormatCodeSettings {
|
||||
const shouldAutoDetectSemicolonPreference = !options.semicolons || options.semicolons === SemicolonPreference.Ignore;
|
||||
const shouldRemoveSemicolons = options.semicolons === SemicolonPreference.Remove || shouldAutoDetectSemicolonPreference && !probablyUsesSemicolons(sourceFile);
|
||||
return {
|
||||
...options,
|
||||
semicolons: shouldRemoveSemicolons ? SemicolonPreference.Remove : SemicolonPreference.Ignore,
|
||||
};
|
||||
}
|
||||
|
||||
// #endregion
|
||||
}
|
||||
|
||||
@ -3344,7 +3344,7 @@ declare namespace ts {
|
||||
createTrue(): TrueLiteral;
|
||||
createFalse(): FalseLiteral;
|
||||
createModifier<T extends ModifierSyntaxKind>(kind: T): ModifierToken<T>;
|
||||
createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[];
|
||||
createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[] | undefined;
|
||||
createQualifiedName(left: EntityName, right: string | Identifier): QualifiedName;
|
||||
updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName;
|
||||
createComputedPropertyName(expression: Expression): ComputedPropertyName;
|
||||
@ -5760,8 +5760,9 @@ declare namespace ts {
|
||||
* @param position A zero-based index of the character where you want the entries
|
||||
* @param options An object describing how the request was triggered and what kinds
|
||||
* of code actions can be returned with the completions.
|
||||
* @param formattingSettings settings needed for calling formatting functions.
|
||||
*/
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): WithMetadata<CompletionInfo> | undefined;
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined, formattingSettings?: FormatCodeSettings): WithMetadata<CompletionInfo> | undefined;
|
||||
/**
|
||||
* Gets the extended details for a completion entry retrieved from `getCompletionsAtPosition`.
|
||||
*
|
||||
@ -10671,7 +10672,7 @@ declare namespace ts {
|
||||
/** @deprecated Use `factory.createModifier` or the factory supplied by your transformation context instead. */
|
||||
const createModifier: <T extends ModifierSyntaxKind>(kind: T) => ModifierToken<T>;
|
||||
/** @deprecated Use `factory.createModifiersFromModifierFlags` or the factory supplied by your transformation context instead. */
|
||||
const createModifiersFromModifierFlags: (flags: ModifierFlags) => Modifier[];
|
||||
const createModifiersFromModifierFlags: (flags: ModifierFlags) => Modifier[] | undefined;
|
||||
/** @deprecated Use `factory.createQualifiedName` or the factory supplied by your transformation context instead. */
|
||||
const createQualifiedName: (left: EntityName, right: string | Identifier) => QualifiedName;
|
||||
/** @deprecated Use `factory.updateQualifiedName` or the factory supplied by your transformation context instead. */
|
||||
|
||||
@ -3344,7 +3344,7 @@ declare namespace ts {
|
||||
createTrue(): TrueLiteral;
|
||||
createFalse(): FalseLiteral;
|
||||
createModifier<T extends ModifierSyntaxKind>(kind: T): ModifierToken<T>;
|
||||
createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[];
|
||||
createModifiersFromModifierFlags(flags: ModifierFlags): Modifier[] | undefined;
|
||||
createQualifiedName(left: EntityName, right: string | Identifier): QualifiedName;
|
||||
updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName;
|
||||
createComputedPropertyName(expression: Expression): ComputedPropertyName;
|
||||
@ -5760,8 +5760,9 @@ declare namespace ts {
|
||||
* @param position A zero-based index of the character where you want the entries
|
||||
* @param options An object describing how the request was triggered and what kinds
|
||||
* of code actions can be returned with the completions.
|
||||
* @param formattingSettings settings needed for calling formatting functions.
|
||||
*/
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): WithMetadata<CompletionInfo> | undefined;
|
||||
getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined, formattingSettings?: FormatCodeSettings): WithMetadata<CompletionInfo> | undefined;
|
||||
/**
|
||||
* Gets the extended details for a completion entry retrieved from `getCompletionsAtPosition`.
|
||||
*
|
||||
@ -6862,7 +6863,7 @@ declare namespace ts {
|
||||
/** @deprecated Use `factory.createModifier` or the factory supplied by your transformation context instead. */
|
||||
const createModifier: <T extends ModifierSyntaxKind>(kind: T) => ModifierToken<T>;
|
||||
/** @deprecated Use `factory.createModifiersFromModifierFlags` or the factory supplied by your transformation context instead. */
|
||||
const createModifiersFromModifierFlags: (flags: ModifierFlags) => Modifier[];
|
||||
const createModifiersFromModifierFlags: (flags: ModifierFlags) => Modifier[] | undefined;
|
||||
/** @deprecated Use `factory.createQualifiedName` or the factory supplied by your transformation context instead. */
|
||||
const createQualifiedName: (left: EntityName, right: string | Identifier) => QualifiedName;
|
||||
/** @deprecated Use `factory.updateQualifiedName` or the factory supplied by your transformation context instead. */
|
||||
|
||||
69
tests/cases/fourslash/completionsOverridingMethod11.ts
Normal file
69
tests/cases/fourslash/completionsOverridingMethod11.ts
Normal file
@ -0,0 +1,69 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @Filename: a.ts
|
||||
// @newline: LF
|
||||
// Case: formatting: no semicolons
|
||||
////function foo() {
|
||||
//// const a = 1
|
||||
//// const b = 2
|
||||
//// foo()
|
||||
//// return a + b
|
||||
////}
|
||||
////
|
||||
////interface Base {
|
||||
//// a: string
|
||||
//// b(a: string): void
|
||||
//// c(a: string): string
|
||||
//// c(a: number): number
|
||||
////}
|
||||
////class Sub implements Base {
|
||||
//// /*a*/
|
||||
////}
|
||||
|
||||
verify.completions({
|
||||
marker: "a",
|
||||
isNewIdentifierLocation: true,
|
||||
preferences: {
|
||||
includeCompletionsWithInsertText: true,
|
||||
includeCompletionsWithSnippetText: false,
|
||||
includeCompletionsWithClassMemberSnippets: true,
|
||||
},
|
||||
includes: [
|
||||
{
|
||||
name: "a",
|
||||
sortText: completion.SortText.LocationPriority,
|
||||
replacementSpan: {
|
||||
fileName: "",
|
||||
pos: 0,
|
||||
end: 0,
|
||||
},
|
||||
insertText: "a: string",
|
||||
},
|
||||
{
|
||||
name: "b",
|
||||
sortText: completion.SortText.LocationPriority,
|
||||
replacementSpan: {
|
||||
fileName: "",
|
||||
pos: 0,
|
||||
end: 0,
|
||||
},
|
||||
insertText:
|
||||
`b(a: string): void {
|
||||
}`,
|
||||
},
|
||||
{
|
||||
name: "c",
|
||||
sortText: completion.SortText.LocationPriority,
|
||||
replacementSpan: {
|
||||
fileName: "",
|
||||
pos: 0,
|
||||
end: 0,
|
||||
},
|
||||
insertText:
|
||||
`c(a: string): string
|
||||
c(a: number): number
|
||||
c(a: any): string | number {
|
||||
}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user