mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
completions: isNewIdentifierLocation = false for string literal where all legal values are known (#22933)
This commit is contained in:
parent
6118f211d1
commit
659dc03f68
@ -48,10 +48,10 @@ namespace ts.codefix {
|
||||
|
||||
const classType = checker.getTypeAtLocation(classDeclaration);
|
||||
|
||||
if (!checker.getIndexTypeOfType(classType, IndexKind.Number)) {
|
||||
if (!classType.getNumberIndexType()) {
|
||||
createMissingIndexSignatureDeclaration(implementedType, IndexKind.Number);
|
||||
}
|
||||
if (!checker.getIndexTypeOfType(classType, IndexKind.String)) {
|
||||
if (!classType.getStringIndexType()) {
|
||||
createMissingIndexSignatureDeclaration(implementedType, IndexKind.String);
|
||||
}
|
||||
|
||||
|
||||
@ -86,11 +86,11 @@ namespace ts.Completions {
|
||||
case StringLiteralCompletionKind.Properties: {
|
||||
const entries: CompletionEntry[] = [];
|
||||
getCompletionEntriesFromSymbols(completion.symbols, entries, sourceFile, sourceFile, checker, ScriptTarget.ESNext, log, CompletionKind.String, preferences); // Target will not be used, so arbitrary
|
||||
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: true, entries };
|
||||
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: completion.hasIndexSignature, entries };
|
||||
}
|
||||
case StringLiteralCompletionKind.Types: {
|
||||
const entries = completion.types.map(type => ({ name: type.value, kindModifiers: ScriptElementKindModifier.none, kind: ScriptElementKind.typeElement, sortText: "0" }));
|
||||
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: true, entries };
|
||||
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries };
|
||||
}
|
||||
default:
|
||||
return Debug.assertNever(completion);
|
||||
@ -360,9 +360,14 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
const enum StringLiteralCompletionKind { Paths, Properties, Types }
|
||||
interface StringLiteralCompletionsFromProperties {
|
||||
readonly kind: StringLiteralCompletionKind.Properties;
|
||||
readonly symbols: ReadonlyArray<Symbol>;
|
||||
readonly hasIndexSignature: boolean;
|
||||
}
|
||||
type StringLiteralCompletion =
|
||||
| { readonly kind: StringLiteralCompletionKind.Paths, readonly paths: ReadonlyArray<PathCompletions.PathCompletion> }
|
||||
| { readonly kind: StringLiteralCompletionKind.Properties, readonly symbols: ReadonlyArray<Symbol> }
|
||||
| StringLiteralCompletionsFromProperties
|
||||
| { readonly kind: StringLiteralCompletionKind.Types, readonly types: ReadonlyArray<StringLiteralType> };
|
||||
function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringLiteralLike, position: number, typeChecker: TypeChecker, compilerOptions: CompilerOptions, host: LanguageServiceHost): StringLiteralCompletion | undefined {
|
||||
switch (node.parent.kind) {
|
||||
@ -377,7 +382,7 @@ namespace ts.Completions {
|
||||
// bar: string;
|
||||
// }
|
||||
// let x: Foo["/*completion position*/"]
|
||||
return { kind: StringLiteralCompletionKind.Properties, symbols: typeChecker.getTypeFromTypeNode((node.parent.parent as IndexedAccessTypeNode).objectType).getApparentProperties() };
|
||||
return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode((node.parent.parent as IndexedAccessTypeNode).objectType));
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
@ -396,8 +401,7 @@ namespace ts.Completions {
|
||||
// foo({
|
||||
// '/*completion position*/'
|
||||
// });
|
||||
const type = typeChecker.getContextualType(node.parent.parent);
|
||||
return { kind: StringLiteralCompletionKind.Properties, symbols: type && type.getApparentProperties() };
|
||||
return stringLiteralCompletionsFromProperties(typeChecker.getContextualType(node.parent.parent));
|
||||
}
|
||||
return fromContextualType();
|
||||
|
||||
@ -410,7 +414,7 @@ namespace ts.Completions {
|
||||
// }
|
||||
// let a: A;
|
||||
// a['/*completion position*/']
|
||||
return { kind: StringLiteralCompletionKind.Properties, symbols: typeChecker.getTypeAtLocation(expression).getApparentProperties() };
|
||||
return stringLiteralCompletionsFromProperties(typeChecker.getTypeAtLocation(expression));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -454,6 +458,10 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
|
||||
function stringLiteralCompletionsFromProperties(type: Type | undefined): StringLiteralCompletionsFromProperties | undefined {
|
||||
return type && { kind: StringLiteralCompletionKind.Properties, symbols: type.getApparentProperties(), hasIndexSignature: hasIndexSignature(type) };
|
||||
}
|
||||
|
||||
function getStringLiteralTypes(type: Type, typeChecker: TypeChecker, uniques = createMap<true>()): ReadonlyArray<StringLiteralType> {
|
||||
if (type && type.flags & TypeFlags.TypeParameter) {
|
||||
type = type.getConstraint();
|
||||
@ -1051,7 +1059,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
function addTypeProperties(type: Type): void {
|
||||
isNewIdentifierLocation = !!type.getStringIndexType() || !!type.getNumberIndexType();
|
||||
isNewIdentifierLocation = hasIndexSignature(type);
|
||||
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
// In javascript files, for union types, we don't just get the members that
|
||||
@ -1454,11 +1462,9 @@ namespace ts.Completions {
|
||||
let existingMembers: ReadonlyArray<Declaration>;
|
||||
|
||||
if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
// We are completing on contextual types, but may also include properties
|
||||
// other than those within the declared type.
|
||||
isNewIdentifierLocation = true;
|
||||
const typeForObject = typeChecker.getContextualType(objectLikeContainer);
|
||||
if (!typeForObject) return GlobalsSearch.Fail;
|
||||
isNewIdentifierLocation = hasIndexSignature(typeForObject);
|
||||
typeMembers = getPropertiesForCompletion(typeForObject, typeChecker, /*isForAccess*/ false);
|
||||
existingMembers = objectLikeContainer.properties;
|
||||
}
|
||||
@ -2247,4 +2253,8 @@ namespace ts.Completions {
|
||||
function isFromObjectTypeDeclaration(node: Node): boolean {
|
||||
return node.parent && (isClassElement(node.parent) || isTypeElement(node.parent)) && isObjectTypeDeclaration(node.parent.parent);
|
||||
}
|
||||
|
||||
function hasIndexSignature(type: Type): boolean {
|
||||
return !!type.getStringIndexType() || !!type.getNumberIndexType();
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,5 +13,5 @@
|
||||
//// '/*1*/': ''
|
||||
//// }
|
||||
|
||||
verify.completionsAt("0", ["jspm", '"jspm:browser"', '"jspm:dev"', '"jspm:node"'], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("1", ["jspm", "jspm:browser", "jspm:dev", "jspm:node"], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("0", ["jspm", '"jspm:browser"', '"jspm:dev"', '"jspm:node"']);
|
||||
verify.completionsAt("1", ["jspm", "jspm:browser", "jspm:dev", "jspm:node"]);
|
||||
|
||||
@ -19,5 +19,5 @@
|
||||
//// }
|
||||
//// }
|
||||
|
||||
verify.completionsAt("0", ["jspm", '"jspm:browser"', '"jspm:dev"', '"jspm:node"'], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("1", ["jspm", "jspm:browser", "jspm:dev", "jspm:node"], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("0", ["jspm", '"jspm:browser"', '"jspm:dev"', '"jspm:node"']);
|
||||
verify.completionsAt("1", ["jspm", "jspm:browser", "jspm:dev", "jspm:node"]);
|
||||
|
||||
@ -15,5 +15,5 @@
|
||||
//// '/*1*/': ""
|
||||
//// }
|
||||
|
||||
verify.completionsAt("0", ["jspm", '"jspm:browser"'], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("1", ["jspm", "jspm:browser"], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("0", ["jspm", '"jspm:browser"']);
|
||||
verify.completionsAt("1", ["jspm", "jspm:browser"]);
|
||||
|
||||
@ -5,16 +5,11 @@
|
||||
//// bar: 0,
|
||||
//// "some other name": 1
|
||||
////};
|
||||
////declare const p: { [s: string]: any, a: number };
|
||||
////
|
||||
////o["/*1*/bar"];
|
||||
////o["/*2*/
|
||||
////o["/*2*/ ;
|
||||
////p["/*3*/"];
|
||||
|
||||
goTo.marker('1');
|
||||
verify.completionListContains("foo");
|
||||
verify.completionListAllowsNewIdentifier();
|
||||
verify.completionListCount(3);
|
||||
|
||||
goTo.marker('2');
|
||||
verify.completionListContains("some other name");
|
||||
verify.completionListAllowsNewIdentifier();
|
||||
verify.completionListCount(3);
|
||||
verify.completionsAt(["1", "2"], ["foo", "bar", "some other name"]);
|
||||
verify.completionsAt("3", ["a"], { isNewIdentifierLocation: true });
|
||||
|
||||
@ -9,12 +9,4 @@
|
||||
////
|
||||
////f("/*2*/
|
||||
|
||||
goTo.marker('1');
|
||||
verify.completionListContains("A");
|
||||
verify.completionListAllowsNewIdentifier();
|
||||
verify.completionListCount(3);
|
||||
|
||||
goTo.marker('2');
|
||||
verify.completionListContains("A");
|
||||
verify.completionListAllowsNewIdentifier();
|
||||
verify.completionListCount(3);
|
||||
verify.completionsAt(["1", "2"], ["A", "B", "C"]);
|
||||
|
||||
@ -5,8 +5,5 @@
|
||||
////function f(x: T, ...args: U[]) { };
|
||||
////f("/*1*/", "/*2*/", "/*3*/");
|
||||
|
||||
// TODO: GH#22907
|
||||
const options = { isNewIdentifierLocation: true };
|
||||
verify.completionsAt("1", ["foo", "bar"], options);
|
||||
verify.completionsAt("2", ["oof", "rab"], options);
|
||||
verify.completionsAt("3", ["oof", "rab"], options);
|
||||
verify.completionsAt("1", ["foo", "bar"]);
|
||||
verify.completionsAt(["2", "3"], ["oof", "rab"]);
|
||||
|
||||
@ -14,8 +14,7 @@
|
||||
////x[|./*a*/|];
|
||||
////x["/*b*/"];
|
||||
|
||||
// TODO: GH#22907
|
||||
verify.completionsAt("b", ["foo ", "bar", "break", "any", "#", "$", "b", "1b"], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("b", ["foo ", "bar", "break", "any", "#", "$", "b", "1b"]);
|
||||
|
||||
const replacementSpan = test.ranges()[0];
|
||||
verify.completionsAt("a", [
|
||||
|
||||
@ -7,5 +7,4 @@
|
||||
////const x = { p: "x" };
|
||||
////x.p = "/**/";
|
||||
|
||||
// TODO: GH#22907
|
||||
verify.completionsAt("", ["x", "y"], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("", ["x", "y"]);
|
||||
|
||||
@ -4,4 +4,4 @@
|
||||
// @Filename: /a.js
|
||||
////const x = /** @type {{ s: string }} */ ({ /**/ });
|
||||
|
||||
verify.completionsAt("", ["s", "x"], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("", ["s", "x"]);
|
||||
|
||||
@ -3,5 +3,4 @@
|
||||
////interface Foo { foo: string; bar: string; }
|
||||
////type T = Pick<Foo, "/**/">;
|
||||
|
||||
// TODO: GH#22907
|
||||
verify.completionsAt("", ["foo", "bar"], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("", ["foo", "bar"]);
|
||||
|
||||
@ -7,5 +7,4 @@
|
||||
|
||||
// We specifically filter out any array-like types.
|
||||
// Private members will be excluded by `createUnionOrIntersectionProperty`.
|
||||
// TODO: GH#22907
|
||||
verify.completionsAt("", ["x"], { isNewIdentifierLocation: true });
|
||||
verify.completionsAt("", ["x"]);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user