Add static index signature (#37797)

* Add static index

* fix lint

* make lint happy

* adjust test cases

* add more cases

* fix changes

* Add more case

* accept baseline

* fix error if extends others

* Update vfsUtil.ts

* use equal to empty array

* static signature of interface is an error

* Accept baseline

* Check index constraints for static signature

* Accpet baseline

* Fix crash

* fix crash

* Accept baseline

* Fix regression

* Fix crash

* always return new array
This commit is contained in:
Wenlu Wang
2021-03-27 06:30:09 +08:00
committed by GitHub
parent 2d6a490363
commit 41dc625b0a
43 changed files with 1490 additions and 70 deletions

View File

@@ -3891,6 +3891,12 @@ namespace ts {
return result || emptyArray;
}
function getNamedOrIndexSignatureMembers(members: SymbolTable): Symbol[] {
const result = getNamedMembers(members);
const index = getIndexSymbolFromSymbolTable(members);
return index ? concatenate(result, [index]) : result;
}
function setStructuredTypeMembers(type: StructuredType, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): ResolvedType {
const resolved = <ResolvedType>type;
resolved.members = members;
@@ -10764,6 +10770,7 @@ namespace ts {
// Combinations of function, class, enum and module
let members = emptySymbols;
let stringIndexInfo: IndexInfo | undefined;
let numberIndexInfo: IndexInfo | undefined;
if (symbol.exports) {
members = getExportsOfSymbol(symbol);
if (symbol === globalThisSymbol) {
@@ -10776,20 +10783,32 @@ namespace ts {
members = varsOnly;
}
}
let baseConstructorIndexInfo: IndexInfo | undefined;
setStructuredTypeMembers(type, members, emptyArray, emptyArray, undefined, undefined);
if (symbol.flags & SymbolFlags.Class) {
const classType = getDeclaredTypeOfClassOrInterface(symbol);
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
if (baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.TypeVariable)) {
members = createSymbolTable(getNamedMembers(members));
members = createSymbolTable(getNamedOrIndexSignatureMembers(members));
addInheritedMembers(members, getPropertiesOfType(baseConstructorType));
}
else if (baseConstructorType === anyType) {
stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
baseConstructorIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
}
}
const indexSymbol = getIndexSymbolFromSymbolTable(members);
if (indexSymbol) {
stringIndexInfo = getIndexInfoOfIndexSymbol(indexSymbol, IndexKind.String);
numberIndexInfo = getIndexInfoOfIndexSymbol(indexSymbol, IndexKind.Number);
}
else {
stringIndexInfo = baseConstructorIndexInfo;
if (symbol.flags & SymbolFlags.Enum && (getDeclaredTypeOfSymbol(symbol).flags & TypeFlags.Enum ||
some(type.properties, prop => !!(getTypeOfSymbol(prop).flags & TypeFlags.NumberLike)))) {
numberIndexInfo = enumNumberIndexInfo;
}
}
const numberIndexInfo = symbol.flags & SymbolFlags.Enum && (getDeclaredTypeOfSymbol(symbol).flags & TypeFlags.Enum ||
some(type.properties, prop => !!(getTypeOfSymbol(prop).flags & TypeFlags.NumberLike))) ? enumNumberIndexInfo : undefined;
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
// We resolve the members before computing the signatures because a signature may use
// typeof with a qualified name expression that circularly references the type we are
@@ -10817,6 +10836,13 @@ namespace ts {
}
}
function getIndexInfoOfIndexSymbol(indexSymbol: Symbol, indexKind: IndexKind) {
const declaration = getIndexDeclarationOfIndexSymbol(indexSymbol, indexKind);
if (!declaration) return undefined;
return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType,
hasEffectiveModifier(declaration, ModifierFlags.Readonly), declaration);
}
function resolveReverseMappedTypeMembers(type: ReverseMappedType) {
const indexInfo = getIndexInfoOfType(type.source, IndexKind.String);
const modifiers = getMappedTypeModifiers(type.mappedType);
@@ -12363,12 +12389,20 @@ namespace ts {
}
function getIndexSymbol(symbol: Symbol): Symbol | undefined {
return symbol.members!.get(InternalSymbolName.Index);
return symbol.members ? getIndexSymbolFromSymbolTable(symbol.members) : undefined;
}
function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): IndexSignatureDeclaration | undefined {
function getIndexSymbolFromSymbolTable(symbolTable: SymbolTable): Symbol | undefined {
return symbolTable.get(InternalSymbolName.Index);
}
function getIndexDeclarationOfSymbol(symbol: Symbol | undefined, kind: IndexKind): IndexSignatureDeclaration | undefined {
const indexSymbol = symbol && getIndexSymbol(symbol);
return indexSymbol && getIndexDeclarationOfIndexSymbol(indexSymbol, kind);
}
function getIndexDeclarationOfIndexSymbol(indexSymbol: Symbol, kind: IndexKind): IndexSignatureDeclaration | undefined {
const syntaxKind = kind === IndexKind.Number ? SyntaxKind.NumberKeyword : SyntaxKind.StringKeyword;
const indexSymbol = getIndexSymbol(symbol);
if (indexSymbol?.declarations) {
for (const decl of indexSymbol.declarations) {
const node = cast(decl, isIndexSignatureDeclaration);
@@ -36723,6 +36757,7 @@ namespace ts {
if (produceDiagnostics) {
checkIndexConstraints(type);
checkIndexConstraints(staticType);
checkTypeForDuplicateIndexSignatures(node);
checkPropertyInitialization(node);
}
@@ -40109,7 +40144,7 @@ namespace ts {
if (node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.MethodSignature) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_type_member, tokenToString(modifier.kind));
}
if (node.kind === SyntaxKind.IndexSignature) {
if (node.kind === SyntaxKind.IndexSignature && (modifier.kind !== SyntaxKind.StaticKeyword || !isClassLike(node.parent))) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_an_index_signature, tokenToString(modifier.kind));
}
}