Merge pull request #32377 from minajevs/fix29666
Fix completion lists for 'readonly' and 'const' keywords
This commit is contained in:
commit
664671cf49
|
@ -865,7 +865,7 @@ namespace FourSlash {
|
|||
ts.zipWith(actual, expected, (completion, expectedCompletion, index) => {
|
||||
const name = typeof expectedCompletion === "string" ? expectedCompletion : expectedCompletion.name;
|
||||
if (completion.name !== name) {
|
||||
this.raiseError(`${marker ? JSON.stringify(marker) : "" } Expected completion at index ${index} to be ${name}, got ${completion.name}`);
|
||||
this.raiseError(`${marker ? JSON.stringify(marker) : ""} Expected completion at index ${index} to be ${name}, got ${completion.name}`);
|
||||
}
|
||||
this.verifyCompletionEntry(completion, expectedCompletion);
|
||||
});
|
||||
|
@ -3759,7 +3759,7 @@ namespace FourSlashInterface {
|
|||
}
|
||||
|
||||
export class Plugins {
|
||||
constructor (private state: FourSlash.TestState) {
|
||||
constructor(private state: FourSlash.TestState) {
|
||||
}
|
||||
|
||||
public configurePlugin(pluginName: string, configuration: any): void {
|
||||
|
@ -4582,7 +4582,7 @@ namespace FourSlashInterface {
|
|||
export const keywords: ReadonlyArray<ExpectedCompletionEntryObject> = keywordsWithUndefined.filter(k => k.name !== "undefined");
|
||||
|
||||
export const typeKeywords: ReadonlyArray<ExpectedCompletionEntryObject> =
|
||||
["false", "null", "true", "void", "any", "boolean", "keyof", "never", "number", "object", "string", "symbol", "undefined", "unique", "unknown", "bigint"].map(keywordEntry);
|
||||
["false", "null", "true", "void", "any", "boolean", "keyof", "never", "readonly", "number", "object", "string", "symbol", "undefined", "unique", "unknown", "bigint"].map(keywordEntry);
|
||||
|
||||
const globalTypeDecls: ReadonlyArray<ExpectedCompletionEntryObject> = [
|
||||
interfaceEntry("Symbol"),
|
||||
|
@ -4698,6 +4698,9 @@ namespace FourSlashInterface {
|
|||
];
|
||||
}
|
||||
|
||||
export const typeAssertionKeywords: ReadonlyArray<ExpectedCompletionEntry> =
|
||||
globalTypesPlus([keywordEntry("const")]);
|
||||
|
||||
function getInJsKeywords(keywords: ReadonlyArray<ExpectedCompletionEntryObject>): ReadonlyArray<ExpectedCompletionEntryObject> {
|
||||
return keywords.filter(keyword => {
|
||||
switch (keyword.name) {
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace ts.Completions {
|
|||
InterfaceElementKeywords, // Keywords inside interface body
|
||||
ConstructorParameterKeywords, // Keywords at constructor parameter
|
||||
FunctionLikeBodyKeywords, // Keywords at function like body
|
||||
TypeAssertionKeywords,
|
||||
TypeKeywords,
|
||||
Last = TypeKeywords
|
||||
}
|
||||
|
@ -441,7 +442,7 @@ namespace ts.Completions {
|
|||
(symbol.escapedName === InternalSymbolName.ExportEquals))
|
||||
// Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase.
|
||||
? firstDefined(symbol.declarations, d => isExportAssignment(d) && isIdentifier(d.expression) ? d.expression.text : undefined)
|
||||
|| codefix.moduleSymbolToValidIdentifier(origin.moduleSymbol, target)
|
||||
|| codefix.moduleSymbolToValidIdentifier(origin.moduleSymbol, target)
|
||||
: symbol.name;
|
||||
}
|
||||
|
||||
|
@ -632,9 +633,9 @@ namespace ts.Completions {
|
|||
// At `,`, treat this as the next argument after the comma.
|
||||
? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === SyntaxKind.CommaToken ? 1 : 0))
|
||||
: isEqualityOperatorKind(previousToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind)
|
||||
// completion at `x ===/**/` should be for the right side
|
||||
? checker.getTypeAtLocation(parent.left)
|
||||
: checker.getContextualType(previousToken as Expression);
|
||||
// completion at `x ===/**/` should be for the right side
|
||||
? checker.getTypeAtLocation(parent.left)
|
||||
: checker.getContextualType(previousToken as Expression);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1182,7 +1183,11 @@ namespace ts.Completions {
|
|||
function filterGlobalCompletion(symbols: Symbol[]): void {
|
||||
const isTypeOnly = isTypeOnlyCompletion();
|
||||
const allowTypes = isTypeOnly || !isContextTokenValueLocation(contextToken) && isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker);
|
||||
if (isTypeOnly) keywordFilters = KeywordCompletionFilters.TypeKeywords;
|
||||
if (isTypeOnly) {
|
||||
keywordFilters = isTypeAssertion()
|
||||
? KeywordCompletionFilters.TypeAssertionKeywords
|
||||
: KeywordCompletionFilters.TypeKeywords;
|
||||
}
|
||||
|
||||
filterMutate(symbols, symbol => {
|
||||
if (!isSourceFile(location)) {
|
||||
|
@ -1212,6 +1217,10 @@ namespace ts.Completions {
|
|||
});
|
||||
}
|
||||
|
||||
function isTypeAssertion(): boolean {
|
||||
return isAssertionExpression(contextToken.parent);
|
||||
}
|
||||
|
||||
function isTypeOnlyCompletion(): boolean {
|
||||
return insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken));
|
||||
}
|
||||
|
@ -1240,7 +1249,8 @@ namespace ts.Completions {
|
|||
return parentKind === SyntaxKind.AsExpression;
|
||||
|
||||
case SyntaxKind.LessThanToken:
|
||||
return parentKind === SyntaxKind.TypeReference;
|
||||
return parentKind === SyntaxKind.TypeReference ||
|
||||
parentKind === SyntaxKind.TypeAssertionExpression;
|
||||
|
||||
case SyntaxKind.ExtendsKeyword:
|
||||
return parentKind === SyntaxKind.TypeParameter;
|
||||
|
@ -1516,7 +1526,7 @@ namespace ts.Completions {
|
|||
// 3. at the end of a regular expression (due to trailing flags like '/foo/g').
|
||||
return (isRegularExpressionLiteral(contextToken) || isStringTextContainingNode(contextToken)) && (
|
||||
rangeContainsPositionExclusive(createTextRangeFromSpan(createTextSpanFromNode(contextToken)), position) ||
|
||||
position === contextToken.end && (!!contextToken.isUnterminated || isRegularExpressionLiteral(contextToken)));
|
||||
position === contextToken.end && (!!contextToken.isUnterminated || isRegularExpressionLiteral(contextToken)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2026,8 +2036,8 @@ namespace ts.Completions {
|
|||
|
||||
return baseSymbols.filter(propertySymbol =>
|
||||
!existingMemberNames.has(propertySymbol.escapedName) &&
|
||||
!!propertySymbol.declarations &&
|
||||
!(getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.Private));
|
||||
!!propertySymbol.declarations &&
|
||||
!(getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.Private));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2139,6 +2149,8 @@ namespace ts.Completions {
|
|||
return isParameterPropertyModifier(kind);
|
||||
case KeywordCompletionFilters.FunctionLikeBodyKeywords:
|
||||
return isFunctionLikeBodyKeyword(kind);
|
||||
case KeywordCompletionFilters.TypeAssertionKeywords:
|
||||
return isTypeKeyword(kind) || kind === SyntaxKind.ConstKeyword;
|
||||
case KeywordCompletionFilters.TypeKeywords:
|
||||
return isTypeKeyword(kind);
|
||||
default:
|
||||
|
|
|
@ -1224,6 +1224,7 @@ namespace ts {
|
|||
SyntaxKind.NullKeyword,
|
||||
SyntaxKind.NumberKeyword,
|
||||
SyntaxKind.ObjectKeyword,
|
||||
SyntaxKind.ReadonlyKeyword,
|
||||
SyntaxKind.StringKeyword,
|
||||
SyntaxKind.SymbolKeyword,
|
||||
SyntaxKind.TrueKeyword,
|
||||
|
@ -1734,8 +1735,8 @@ namespace ts {
|
|||
|
||||
function getSynthesizedDeepCloneWorker<T extends Node>(node: T, renameMap?: Map<Identifier>, checker?: TypeChecker, callback?: (originalNode: Node, clone: Node) => any): T {
|
||||
const visited = (renameMap || checker || callback) ?
|
||||
visitEachChild(node, wrapper, nullTransformationContext) :
|
||||
visitEachChild(node, getSynthesizedDeepClone, nullTransformationContext);
|
||||
visitEachChild(node, wrapper, nullTransformationContext) :
|
||||
visitEachChild(node, getSynthesizedDeepClone, nullTransformationContext);
|
||||
|
||||
if (visited === node) {
|
||||
// This only happens for leaf nodes - internal nodes always see their children change.
|
||||
|
|
13
tests/cases/fourslash/completionsTypeAssertionKeywords.ts
Normal file
13
tests/cases/fourslash/completionsTypeAssertionKeywords.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////const a = {
|
||||
//// b: 42 as /*0*/
|
||||
////};
|
||||
////
|
||||
////1 as /*1*/
|
||||
////
|
||||
////const b = 42 as /*2*/
|
||||
////
|
||||
////var c = </*3*/>42
|
||||
|
||||
verify.completions({ marker: test.markers(), exact: completion.typeAssertionKeywords });
|
|
@ -6,5 +6,5 @@
|
|||
////function f([|readonly|] p) {}
|
||||
|
||||
for (const r of test.ranges()) {
|
||||
verify.documentHighlightsOf(r, [r]);
|
||||
verify.documentHighlightsOf(r, test.ranges());
|
||||
}
|
||||
|
|
|
@ -696,6 +696,7 @@ declare namespace completion {
|
|||
export const typeKeywords: ReadonlyArray<Entry>;
|
||||
export const globalTypes: ReadonlyArray<Entry>;
|
||||
export function globalTypesPlus(plus: ReadonlyArray<FourSlashInterface.ExpectedCompletionEntry>): ReadonlyArray<Entry>;
|
||||
export const typeAssertionKeywords: ReadonlyArray<Entry>;
|
||||
export const classElementKeywords: ReadonlyArray<Entry>;
|
||||
export const classElementInJsKeywords: ReadonlyArray<Entry>;
|
||||
export const constructorParameterKeywords: ReadonlyArray<Entry>;
|
||||
|
|
Loading…
Reference in a new issue