commit
5e4b8d66ff
|
@ -61,6 +61,7 @@ namespace ts {
|
||||||
const noImplicitThis = compilerOptions.noImplicitThis === undefined ? compilerOptions.strict : compilerOptions.noImplicitThis;
|
const noImplicitThis = compilerOptions.noImplicitThis === undefined ? compilerOptions.strict : compilerOptions.noImplicitThis;
|
||||||
|
|
||||||
const emitResolver = createResolver();
|
const emitResolver = createResolver();
|
||||||
|
const nodeBuilder = createNodeBuilder();
|
||||||
|
|
||||||
const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined");
|
const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined");
|
||||||
undefinedSymbol.declarations = [];
|
undefinedSymbol.declarations = [];
|
||||||
|
@ -106,6 +107,9 @@ namespace ts {
|
||||||
getParameterType: getTypeAtPosition,
|
getParameterType: getTypeAtPosition,
|
||||||
getReturnTypeOfSignature,
|
getReturnTypeOfSignature,
|
||||||
getNonNullableType,
|
getNonNullableType,
|
||||||
|
typeToTypeNode: nodeBuilder.typeToTypeNode,
|
||||||
|
indexInfoToIndexSignatureDeclaration: nodeBuilder.indexInfoToIndexSignatureDeclaration,
|
||||||
|
signatureToSignatureDeclaration: nodeBuilder.signatureToSignatureDeclaration,
|
||||||
getSymbolsInScope: (location, meaning) => {
|
getSymbolsInScope: (location, meaning) => {
|
||||||
location = getParseTreeNode(location);
|
location = getParseTreeNode(location);
|
||||||
return location ? getSymbolsInScope(location, meaning) : [];
|
return location ? getSymbolsInScope(location, meaning) : [];
|
||||||
|
@ -2198,6 +2202,584 @@ namespace ts {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createNodeBuilder() {
|
||||||
|
let context: NodeBuilderContext;
|
||||||
|
|
||||||
|
return {
|
||||||
|
typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => {
|
||||||
|
context = createNodeBuilderContext(enclosingDeclaration, flags);
|
||||||
|
const resultingNode = typeToTypeNodeHelper(type);
|
||||||
|
const result = context.encounteredError ? undefined : resultingNode;
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => {
|
||||||
|
context = createNodeBuilderContext(enclosingDeclaration, flags);
|
||||||
|
const resultingNode = indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind);
|
||||||
|
const result = context.encounteredError ? undefined : resultingNode;
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
signatureToSignatureDeclaration: (signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags) => {
|
||||||
|
context = createNodeBuilderContext(enclosingDeclaration, flags);
|
||||||
|
const resultingNode = signatureToSignatureDeclarationHelper(signature, kind);
|
||||||
|
const result = context.encounteredError ? undefined : resultingNode;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
interface NodeBuilderContext {
|
||||||
|
readonly enclosingDeclaration: Node | undefined;
|
||||||
|
readonly flags: NodeBuilderFlags | undefined;
|
||||||
|
encounteredError: boolean;
|
||||||
|
inObjectTypeLiteral: boolean;
|
||||||
|
checkAlias: boolean;
|
||||||
|
symbolStack: Symbol[] | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNodeBuilderContext(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): NodeBuilderContext {
|
||||||
|
return {
|
||||||
|
enclosingDeclaration,
|
||||||
|
flags,
|
||||||
|
encounteredError: false,
|
||||||
|
inObjectTypeLiteral: false,
|
||||||
|
checkAlias: true,
|
||||||
|
symbolStack: undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeToTypeNodeHelper(type: Type): TypeNode {
|
||||||
|
if (!type) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
// TODO(aozgaa): should we return implict any (undefined) or explicit any (keywordtypenode)?
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.flags & TypeFlags.Any) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.String) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.StringKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Number) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.NumberKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Boolean) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.BooleanKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Enum) {
|
||||||
|
const name = symbolToName(type.symbol, /*expectsIdentifier*/ false);
|
||||||
|
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
||||||
|
}
|
||||||
|
if (type.flags & (TypeFlags.StringLiteral)) {
|
||||||
|
return createLiteralTypeNode((createLiteral((<LiteralType>type).text)));
|
||||||
|
}
|
||||||
|
if (type.flags & (TypeFlags.NumberLiteral)) {
|
||||||
|
return createLiteralTypeNode((createNumericLiteral((<LiteralType>type).text)));
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.BooleanLiteral) {
|
||||||
|
return (<IntrinsicType>type).intrinsicName === "true" ? createTrue() : createFalse();
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.EnumLiteral) {
|
||||||
|
const name = symbolToName(type.symbol, /*expectsIdentifier*/ false);
|
||||||
|
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Void) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.VoidKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Undefined) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.UndefinedKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Null) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.NullKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.Never) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.NeverKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.ESSymbol) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.SymbolKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.NonPrimitive) {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.ObjectKeyword);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) {
|
||||||
|
if (context.inObjectTypeLiteral) {
|
||||||
|
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowThisInObjectLiteral)) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return createThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
const objectFlags = getObjectFlags(type);
|
||||||
|
|
||||||
|
if (objectFlags & ObjectFlags.Reference) {
|
||||||
|
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||||
|
return typeReferenceToTypeNode(<TypeReference>type);
|
||||||
|
}
|
||||||
|
if (objectFlags & ObjectFlags.ClassOrInterface) {
|
||||||
|
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||||
|
const name = symbolToName(type.symbol, /*expectsIdentifier*/ false);
|
||||||
|
// TODO(aozgaa): handle type arguments.
|
||||||
|
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.TypeParameter) {
|
||||||
|
const name = symbolToName(type.symbol, /*expectsIdentifier*/ false);
|
||||||
|
// Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter.
|
||||||
|
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.checkAlias && type.aliasSymbol) {
|
||||||
|
const name = symbolToName(type.aliasSymbol, /*expectsIdentifier*/ false);
|
||||||
|
const typeArgumentNodes = type.aliasTypeArguments && mapToTypeNodeArray(type.aliasTypeArguments);
|
||||||
|
return createTypeReferenceNode(name, typeArgumentNodes);
|
||||||
|
}
|
||||||
|
context.checkAlias = false;
|
||||||
|
|
||||||
|
if (type.flags & TypeFlags.Union) {
|
||||||
|
const formattedUnionTypes = formatUnionTypes((<UnionType>type).types);
|
||||||
|
const unionTypeNodes = formattedUnionTypes && mapToTypeNodeArray(formattedUnionTypes);
|
||||||
|
if (unionTypeNodes && unionTypeNodes.length > 0) {
|
||||||
|
return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, unionTypeNodes);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowEmptyUnionOrIntersection)) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.flags & TypeFlags.Intersection) {
|
||||||
|
return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, mapToTypeNodeArray((type as UnionType).types));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objectFlags & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) {
|
||||||
|
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||||
|
// The type is an object literal type.
|
||||||
|
return createAnonymousTypeNode(<ObjectType>type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.flags & TypeFlags.Index) {
|
||||||
|
const indexedType = (<IndexType>type).type;
|
||||||
|
const indexTypeNode = typeToTypeNodeHelper(indexedType);
|
||||||
|
return createTypeOperatorNode(indexTypeNode);
|
||||||
|
}
|
||||||
|
if (type.flags & TypeFlags.IndexedAccess) {
|
||||||
|
const objectTypeNode = typeToTypeNodeHelper((<IndexedAccessType>type).objectType);
|
||||||
|
const indexTypeNode = typeToTypeNodeHelper((<IndexedAccessType>type).indexType);
|
||||||
|
return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.fail("Should be unreachable.");
|
||||||
|
|
||||||
|
function mapToTypeNodeArray(types: Type[]): TypeNode[] {
|
||||||
|
const result = [];
|
||||||
|
for (const type of types) {
|
||||||
|
const typeNode = typeToTypeNodeHelper(type);
|
||||||
|
if (typeNode) {
|
||||||
|
result.push(typeNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMappedTypeNodeFromType(type: MappedType) {
|
||||||
|
Debug.assert(!!(type.flags & TypeFlags.Object));
|
||||||
|
const typeParameter = getTypeParameterFromMappedType(type);
|
||||||
|
const typeParameterNode = typeParameterToDeclaration(typeParameter);
|
||||||
|
|
||||||
|
const templateType = getTemplateTypeFromMappedType(type);
|
||||||
|
const templateTypeNode = typeToTypeNodeHelper(templateType);
|
||||||
|
const readonlyToken = type.declaration && type.declaration.readonlyToken ? createToken(SyntaxKind.ReadonlyKeyword) : undefined;
|
||||||
|
const questionToken = type.declaration && type.declaration.questionToken ? createToken(SyntaxKind.QuestionToken) : undefined;
|
||||||
|
|
||||||
|
return createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAnonymousTypeNode(type: ObjectType): TypeNode {
|
||||||
|
const symbol = type.symbol;
|
||||||
|
if (symbol) {
|
||||||
|
// Always use 'typeof T' for type of class, enum, and module objects
|
||||||
|
if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) ||
|
||||||
|
symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) ||
|
||||||
|
shouldWriteTypeOfFunctionSymbol()) {
|
||||||
|
return createTypeQueryNodeFromSymbol(symbol);
|
||||||
|
}
|
||||||
|
else if (contains(context.symbolStack, symbol)) {
|
||||||
|
// If type is an anonymous type literal in a type alias declaration, use type alias name
|
||||||
|
const typeAlias = getTypeAliasForTypeLiteral(type);
|
||||||
|
if (typeAlias) {
|
||||||
|
// The specified symbol flags need to be reinterpreted as type flags
|
||||||
|
const entityName = symbolToName(typeAlias, /*expectsIdentifier*/ false);
|
||||||
|
return createTypeReferenceNode(entityName, /*typeArguments*/ undefined);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
|
||||||
|
// of types allows us to catch circular references to instantiations of the same anonymous type
|
||||||
|
if (!context.symbolStack) {
|
||||||
|
context.symbolStack = [];
|
||||||
|
}
|
||||||
|
context.symbolStack.push(symbol);
|
||||||
|
const result = createTypeNodeFromObjectType(type);
|
||||||
|
context.symbolStack.pop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Anonymous types without a symbol are never circular.
|
||||||
|
return createTypeNodeFromObjectType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldWriteTypeOfFunctionSymbol() {
|
||||||
|
const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method && // typeof static method
|
||||||
|
forEach(symbol.declarations, declaration => getModifierFlags(declaration) & ModifierFlags.Static));
|
||||||
|
const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) &&
|
||||||
|
(symbol.parent || // is exported function symbol
|
||||||
|
forEach(symbol.declarations, declaration =>
|
||||||
|
declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
|
||||||
|
if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
|
||||||
|
// typeof is allowed only for static/non local functions
|
||||||
|
return contains(context.symbolStack, symbol); // it is type of the symbol uses itself recursively
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTypeNodeFromObjectType(type: ObjectType): TypeNode {
|
||||||
|
if (type.objectFlags & ObjectFlags.Mapped) {
|
||||||
|
if (getConstraintTypeFromMappedType(<MappedType>type).flags & (TypeFlags.TypeParameter | TypeFlags.Index)) {
|
||||||
|
return createMappedTypeNodeFromType(<MappedType>type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolved = resolveStructuredTypeMembers(type);
|
||||||
|
if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) {
|
||||||
|
if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
|
||||||
|
return createTypeLiteralNode(/*members*/ undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
|
||||||
|
const signature = resolved.callSignatures[0];
|
||||||
|
return <FunctionTypeNode>signatureToSignatureDeclarationHelper(signature, SyntaxKind.FunctionType);
|
||||||
|
}
|
||||||
|
if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) {
|
||||||
|
const signature = resolved.constructSignatures[0];
|
||||||
|
return <ConstructorTypeNode>signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructorType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveInObjectTypeLiteral = context.inObjectTypeLiteral;
|
||||||
|
context.inObjectTypeLiteral = true;
|
||||||
|
const members = createTypeNodesFromResolvedType(resolved);
|
||||||
|
context.inObjectTypeLiteral = saveInObjectTypeLiteral;
|
||||||
|
return createTypeLiteralNode(members);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTypeQueryNodeFromSymbol(symbol: Symbol) {
|
||||||
|
const entityName = symbolToName(symbol, /*expectsIdentifier*/ false);
|
||||||
|
return createTypeQueryNode(entityName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeReferenceToTypeNode(type: TypeReference) {
|
||||||
|
const typeArguments: Type[] = type.typeArguments || emptyArray;
|
||||||
|
if (type.target === globalArrayType) {
|
||||||
|
const elementType = typeToTypeNodeHelper(typeArguments[0]);
|
||||||
|
return createArrayTypeNode(elementType);
|
||||||
|
}
|
||||||
|
else if (type.target.objectFlags & ObjectFlags.Tuple) {
|
||||||
|
if (typeArguments.length > 0) {
|
||||||
|
const tupleConstituentNodes = mapToTypeNodeArray(typeArguments.slice(0, getTypeReferenceArity(type)));
|
||||||
|
if (tupleConstituentNodes && tupleConstituentNodes.length > 0) {
|
||||||
|
return createTupleTypeNode(tupleConstituentNodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowEmptyTuple)) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const outerTypeParameters = type.target.outerTypeParameters;
|
||||||
|
let i = 0;
|
||||||
|
let qualifiedName: QualifiedName | undefined = undefined;
|
||||||
|
if (outerTypeParameters) {
|
||||||
|
const length = outerTypeParameters.length;
|
||||||
|
while (i < length) {
|
||||||
|
// Find group of type arguments for type parameters with the same declaring container.
|
||||||
|
const start = i;
|
||||||
|
const parent = getParentSymbolOfTypeParameter(outerTypeParameters[i]);
|
||||||
|
do {
|
||||||
|
i++;
|
||||||
|
} while (i < length && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent);
|
||||||
|
// When type parameters are their own type arguments for the whole group (i.e. we have
|
||||||
|
// the default outer type arguments), we don't show the group.
|
||||||
|
if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) {
|
||||||
|
const qualifiedNamePart = symbolToName(parent, /*expectsIdentifier*/ true);
|
||||||
|
if (!qualifiedName) {
|
||||||
|
qualifiedName = createQualifiedName(qualifiedNamePart, /*right*/ undefined);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Debug.assert(!qualifiedName.right);
|
||||||
|
qualifiedName.right = qualifiedNamePart;
|
||||||
|
qualifiedName = createQualifiedName(qualifiedName, /*right*/ undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let entityName: EntityName = undefined;
|
||||||
|
const nameIdentifier = symbolToName(type.symbol, /*expectsIdentifier*/ true);
|
||||||
|
if (qualifiedName) {
|
||||||
|
Debug.assert(!qualifiedName.right);
|
||||||
|
qualifiedName.right = nameIdentifier;
|
||||||
|
entityName = qualifiedName;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entityName = nameIdentifier;
|
||||||
|
}
|
||||||
|
const typeParameterCount = (type.target.typeParameters || emptyArray).length;
|
||||||
|
const typeArgumentNodes = some(typeArguments) ? mapToTypeNodeArray(typeArguments.slice(i, typeParameterCount - i)) : undefined;
|
||||||
|
return createTypeReferenceNode(entityName, typeArgumentNodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] {
|
||||||
|
const typeElements: TypeElement[] = [];
|
||||||
|
for (const signature of resolvedType.callSignatures) {
|
||||||
|
typeElements.push(<CallSignatureDeclaration>signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature));
|
||||||
|
}
|
||||||
|
for (const signature of resolvedType.constructSignatures) {
|
||||||
|
typeElements.push(<ConstructSignatureDeclaration>signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructSignature));
|
||||||
|
}
|
||||||
|
if (resolvedType.stringIndexInfo) {
|
||||||
|
typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.stringIndexInfo, IndexKind.String));
|
||||||
|
}
|
||||||
|
if (resolvedType.numberIndexInfo) {
|
||||||
|
typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.numberIndexInfo, IndexKind.Number));
|
||||||
|
}
|
||||||
|
|
||||||
|
const properties = resolvedType.properties;
|
||||||
|
if (!properties) {
|
||||||
|
return typeElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const propertySymbol of properties) {
|
||||||
|
const propertyType = getTypeOfSymbol(propertySymbol);
|
||||||
|
const oldDeclaration = propertySymbol.declarations && propertySymbol.declarations[0] as TypeElement;
|
||||||
|
if (!oldDeclaration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const propertyName = oldDeclaration.name;
|
||||||
|
const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? createToken(SyntaxKind.QuestionToken) : undefined;
|
||||||
|
if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length) {
|
||||||
|
const signatures = getSignaturesOfType(propertyType, SignatureKind.Call);
|
||||||
|
for (const signature of signatures) {
|
||||||
|
const methodDeclaration = <MethodSignature>signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature);
|
||||||
|
methodDeclaration.name = propertyName;
|
||||||
|
methodDeclaration.questionToken = optionalToken;
|
||||||
|
typeElements.push(methodDeclaration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
// TODO(aozgaa): should we create a node with explicit or implict any?
|
||||||
|
const propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType) : createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||||
|
typeElements.push(createPropertySignature(
|
||||||
|
propertyName,
|
||||||
|
optionalToken,
|
||||||
|
propertyTypeNode,
|
||||||
|
/*initializer*/undefined));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return typeElements.length ? typeElements : undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, kind: IndexKind): IndexSignatureDeclaration {
|
||||||
|
const indexerTypeNode = createKeywordTypeNode(kind === IndexKind.String ? SyntaxKind.StringKeyword : SyntaxKind.NumberKeyword);
|
||||||
|
const name = getNameFromIndexInfo(indexInfo);
|
||||||
|
|
||||||
|
const indexingParameter = createParameter(
|
||||||
|
/*decorators*/ undefined,
|
||||||
|
/*modifiers*/ undefined,
|
||||||
|
/*dotDotDotToken*/ undefined,
|
||||||
|
name,
|
||||||
|
/*questionToken*/ undefined,
|
||||||
|
indexerTypeNode,
|
||||||
|
/*initializer*/ undefined);
|
||||||
|
const typeNode = typeToTypeNodeHelper(indexInfo.type);
|
||||||
|
return createIndexSignatureDeclaration(
|
||||||
|
/*decorators*/ undefined,
|
||||||
|
indexInfo.isReadonly ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined,
|
||||||
|
[indexingParameter],
|
||||||
|
typeNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function signatureToSignatureDeclarationHelper(signature: Signature, kind: SyntaxKind): SignatureDeclaration {
|
||||||
|
|
||||||
|
const typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter));
|
||||||
|
const parameters = signature.parameters.map(parameter => symbolToParameterDeclaration(parameter));
|
||||||
|
let returnTypeNode: TypeNode | TypePredicate;
|
||||||
|
if (signature.typePredicate) {
|
||||||
|
const typePredicate = signature.typePredicate;
|
||||||
|
const parameterName = typePredicate.kind === TypePredicateKind.Identifier ? createIdentifier((<IdentifierTypePredicate>typePredicate).parameterName) : createThisTypeNode();
|
||||||
|
const typeNode = typeToTypeNodeHelper(typePredicate.type);
|
||||||
|
returnTypeNode = createTypePredicateNode(parameterName, typeNode);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const returnType = getReturnTypeOfSignature(signature);
|
||||||
|
returnTypeNode = returnType && typeToTypeNodeHelper(returnType);
|
||||||
|
}
|
||||||
|
const returnTypeNodeExceptAny = returnTypeNode && returnTypeNode.kind !== SyntaxKind.AnyKeyword ? returnTypeNode : undefined;
|
||||||
|
|
||||||
|
return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNodeExceptAny);
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeParameterToDeclaration(type: TypeParameter): TypeParameterDeclaration {
|
||||||
|
const constraint = getConstraintFromTypeParameter(type);
|
||||||
|
const constraintNode = constraint && typeToTypeNodeHelper(constraint);
|
||||||
|
const defaultParameter = getDefaultFromTypeParameter(type);
|
||||||
|
const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter);
|
||||||
|
const name = symbolToName(type.symbol, /*expectsIdentifier*/ true);
|
||||||
|
return createTypeParameterDeclaration(name, constraintNode, defaultParameterNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function symbolToParameterDeclaration(parameterSymbol: Symbol): ParameterDeclaration {
|
||||||
|
const parameterDeclaration = <ParameterDeclaration>getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter);
|
||||||
|
const parameterType = getTypeOfSymbol(parameterSymbol);
|
||||||
|
const parameterTypeNode = typeToTypeNodeHelper(parameterType);
|
||||||
|
// TODO(aozgaa): In the future, check initializer accessibility.
|
||||||
|
const parameterNode = createParameter(
|
||||||
|
parameterDeclaration.decorators,
|
||||||
|
parameterDeclaration.modifiers,
|
||||||
|
parameterDeclaration.dotDotDotToken && createToken(SyntaxKind.DotDotDotToken),
|
||||||
|
// Clone name to remove trivia.
|
||||||
|
getSynthesizedClone(parameterDeclaration.name),
|
||||||
|
parameterDeclaration.questionToken && createToken(SyntaxKind.QuestionToken),
|
||||||
|
parameterTypeNode,
|
||||||
|
parameterDeclaration.initializer);
|
||||||
|
return parameterNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function symbolToName(symbol: Symbol, expectsIdentifier: true): Identifier;
|
||||||
|
function symbolToName(symbol: Symbol, expectsIdentifier: false): EntityName;
|
||||||
|
function symbolToName(symbol: Symbol, expectsIdentifier: boolean): EntityName {
|
||||||
|
|
||||||
|
// Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration.
|
||||||
|
let chain: Symbol[];
|
||||||
|
const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter;
|
||||||
|
if (!isTypeParameter && context.enclosingDeclaration) {
|
||||||
|
chain = getSymbolChain(symbol, SymbolFlags.None, /*endOfChain*/ true);
|
||||||
|
Debug.assert(chain && chain.length > 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chain = [symbol];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expectsIdentifier && chain.length !== 1
|
||||||
|
&& !context.encounteredError
|
||||||
|
&& !(context.flags & NodeBuilderFlags.allowQualifedNameInPlaceOfIdentifier)) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
}
|
||||||
|
return createEntityNameFromSymbolChain(chain, chain.length - 1);
|
||||||
|
|
||||||
|
function createEntityNameFromSymbolChain(chain: Symbol[], index: number): EntityName {
|
||||||
|
Debug.assert(chain && 0 <= index && index < chain.length);
|
||||||
|
// const parentIndex = index - 1;
|
||||||
|
const symbol = chain[index];
|
||||||
|
let typeParameterString = "";
|
||||||
|
if (index > 0) {
|
||||||
|
|
||||||
|
const parentSymbol = chain[index - 1];
|
||||||
|
let typeParameters: TypeParameter[];
|
||||||
|
if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
|
||||||
|
typeParameters = getTypeParametersOfClassOrInterface(parentSymbol);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const targetSymbol = getTargetSymbol(parentSymbol);
|
||||||
|
if (targetSymbol.flags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeAlias)) {
|
||||||
|
typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeParameters && typeParameters.length > 0) {
|
||||||
|
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowTypeParameterInQualifiedName)) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
}
|
||||||
|
const writer = getSingleLineStringWriter();
|
||||||
|
const displayBuilder = getSymbolDisplayBuilder();
|
||||||
|
displayBuilder.buildDisplayForTypeParametersAndDelimiters(typeParameters, writer, context.enclosingDeclaration, 0);
|
||||||
|
typeParameterString = writer.string();
|
||||||
|
releaseStringWriter(writer);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const symbolName = getNameOfSymbol(symbol);
|
||||||
|
const symbolNameWithTypeParameters = typeParameterString.length > 0 ? `${symbolName}<${typeParameterString}>` : symbolName;
|
||||||
|
const identifier = createIdentifier(symbolNameWithTypeParameters);
|
||||||
|
|
||||||
|
return index > 0 ? createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */
|
||||||
|
function getSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined {
|
||||||
|
let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, /*useOnlyExternalAliasing*/false);
|
||||||
|
let parentSymbol: Symbol;
|
||||||
|
|
||||||
|
if (!accessibleSymbolChain ||
|
||||||
|
needsQualification(accessibleSymbolChain[0], context.enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
|
||||||
|
|
||||||
|
// Go up and add our parent.
|
||||||
|
const parent = getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol);
|
||||||
|
if (parent) {
|
||||||
|
const parentChain = getSymbolChain(parent, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false);
|
||||||
|
if (parentChain) {
|
||||||
|
parentSymbol = parent;
|
||||||
|
accessibleSymbolChain = parentChain.concat(accessibleSymbolChain || [symbol]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accessibleSymbolChain) {
|
||||||
|
return accessibleSymbolChain;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
// If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols.
|
||||||
|
endOfChain ||
|
||||||
|
// If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.)
|
||||||
|
!(!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) &&
|
||||||
|
// If a parent symbol is an anonymous type, don't write it.
|
||||||
|
!(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral))) {
|
||||||
|
|
||||||
|
return [symbol];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNameOfSymbol(symbol: Symbol): string {
|
||||||
|
const declaration = firstOrUndefined(symbol.declarations);
|
||||||
|
if (declaration) {
|
||||||
|
if (declaration.name) {
|
||||||
|
return declarationNameToString(declaration.name);
|
||||||
|
}
|
||||||
|
if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) {
|
||||||
|
return declarationNameToString((<VariableDeclaration>declaration.parent).name);
|
||||||
|
}
|
||||||
|
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.allowAnonymousIdentifier)) {
|
||||||
|
context.encounteredError = true;
|
||||||
|
}
|
||||||
|
switch (declaration.kind) {
|
||||||
|
case SyntaxKind.ClassExpression:
|
||||||
|
return "(Anonymous class)";
|
||||||
|
case SyntaxKind.FunctionExpression:
|
||||||
|
case SyntaxKind.ArrowFunction:
|
||||||
|
return "(Anonymous function)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return symbol.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function typePredicateToString(typePredicate: TypePredicate, enclosingDeclaration?: Declaration, flags?: TypeFormatFlags): string {
|
function typePredicateToString(typePredicate: TypePredicate, enclosingDeclaration?: Declaration, flags?: TypeFormatFlags): string {
|
||||||
const writer = getSingleLineStringWriter();
|
const writer = getSingleLineStringWriter();
|
||||||
getSymbolDisplayBuilder().buildTypePredicateDisplay(typePredicate, writer, enclosingDeclaration, flags);
|
getSymbolDisplayBuilder().buildTypePredicateDisplay(typePredicate, writer, enclosingDeclaration, flags);
|
||||||
|
@ -2466,6 +3048,7 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function writeTypeList(types: Type[], delimiter: SyntaxKind) {
|
function writeTypeList(types: Type[], delimiter: SyntaxKind) {
|
||||||
for (let i = 0; i < types.length; i++) {
|
for (let i = 0; i < types.length; i++) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace ts {
|
||||||
* Creates a shallow, memberwise clone of a node with no source map location.
|
* Creates a shallow, memberwise clone of a node with no source map location.
|
||||||
*/
|
*/
|
||||||
/* @internal */
|
/* @internal */
|
||||||
export function getSynthesizedClone<T extends Node>(node: T): T {
|
export function getSynthesizedClone<T extends Node>(node: T | undefined): T {
|
||||||
// We don't use "clone" from core.ts here, as we need to preserve the prototype chain of
|
// We don't use "clone" from core.ts here, as we need to preserve the prototype chain of
|
||||||
// the original node. We also need to exclude specific properties and only include own-
|
// the original node. We also need to exclude specific properties and only include own-
|
||||||
// properties (to skip members already defined on the shared prototype).
|
// properties (to skip members already defined on the shared prototype).
|
||||||
|
@ -166,23 +166,23 @@ namespace ts {
|
||||||
// Reserved words
|
// Reserved words
|
||||||
|
|
||||||
export function createSuper() {
|
export function createSuper() {
|
||||||
return <PrimaryExpression>createSynthesizedNode(SyntaxKind.SuperKeyword);
|
return <SuperExpression>createSynthesizedNode(SyntaxKind.SuperKeyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createThis() {
|
export function createThis() {
|
||||||
return <PrimaryExpression>createSynthesizedNode(SyntaxKind.ThisKeyword);
|
return <ThisExpression & Token<SyntaxKind.ThisKeyword>>createSynthesizedNode(SyntaxKind.ThisKeyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createNull() {
|
export function createNull() {
|
||||||
return <PrimaryExpression>createSynthesizedNode(SyntaxKind.NullKeyword);
|
return <NullLiteral & Token<SyntaxKind.NullKeyword>>createSynthesizedNode(SyntaxKind.NullKeyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTrue() {
|
export function createTrue() {
|
||||||
return <BooleanLiteral>createSynthesizedNode(SyntaxKind.TrueKeyword);
|
return <BooleanLiteral & Token<SyntaxKind.TrueKeyword>>createSynthesizedNode(SyntaxKind.TrueKeyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createFalse() {
|
export function createFalse() {
|
||||||
return <BooleanLiteral>createSynthesizedNode(SyntaxKind.FalseKeyword);
|
return <BooleanLiteral & Token<SyntaxKind.FalseKeyword>>createSynthesizedNode(SyntaxKind.FalseKeyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Names
|
// Names
|
||||||
|
@ -213,6 +213,284 @@ namespace ts {
|
||||||
: node;
|
: node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type Elements
|
||||||
|
|
||||||
|
export function createSignatureDeclaration(kind: SyntaxKind, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) {
|
||||||
|
const signatureDeclaration = createSynthesizedNode(kind) as SignatureDeclaration;
|
||||||
|
signatureDeclaration.typeParameters = asNodeArray(typeParameters);
|
||||||
|
signatureDeclaration.parameters = asNodeArray(parameters);
|
||||||
|
signatureDeclaration.type = type;
|
||||||
|
return signatureDeclaration;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSignatureDeclaration(node: SignatureDeclaration, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined) {
|
||||||
|
return node.typeParameters !== typeParameters
|
||||||
|
|| node.parameters !== parameters
|
||||||
|
|| node.type !== type
|
||||||
|
? updateNode(createSignatureDeclaration(node.kind, typeParameters, parameters, type), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createFunctionTypeNode(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) {
|
||||||
|
return createSignatureDeclaration(SyntaxKind.FunctionType, typeParameters, parameters, type) as FunctionTypeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined) {
|
||||||
|
return <FunctionTypeNode>updateSignatureDeclaration(node, typeParameters, parameters, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createConstructorTypeNode(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) {
|
||||||
|
return createSignatureDeclaration(SyntaxKind.ConstructorType, typeParameters, parameters, type) as ConstructorTypeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined) {
|
||||||
|
return <ConstructorTypeNode>updateSignatureDeclaration(node, typeParameters, parameters, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createCallSignatureDeclaration(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) {
|
||||||
|
return createSignatureDeclaration(SyntaxKind.CallSignature, typeParameters, parameters, type) as CallSignatureDeclaration;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateCallSignatureDeclaration(node: CallSignatureDeclaration, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined) {
|
||||||
|
return <CallSignatureDeclaration>updateSignatureDeclaration(node, typeParameters, parameters, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createConstructSignatureDeclaration(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) {
|
||||||
|
return createSignatureDeclaration(SyntaxKind.ConstructSignature, typeParameters, parameters, type) as ConstructSignatureDeclaration;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateConstructSignatureDeclaration(node: ConstructSignatureDeclaration, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined) {
|
||||||
|
return <ConstructSignatureDeclaration>updateSignatureDeclaration(node, typeParameters, parameters, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createMethodSignature(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined) {
|
||||||
|
const methodSignature = createSignatureDeclaration(SyntaxKind.MethodSignature, typeParameters, parameters, type) as MethodSignature;
|
||||||
|
methodSignature.name = asName(name);
|
||||||
|
methodSignature.questionToken = questionToken;
|
||||||
|
return methodSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateMethodSignature(node: MethodSignature, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined, name: PropertyName, questionToken: QuestionToken | undefined) {
|
||||||
|
return node.typeParameters !== typeParameters
|
||||||
|
|| node.parameters !== parameters
|
||||||
|
|| node.type !== type
|
||||||
|
|| node.name !== name
|
||||||
|
|| node.questionToken !== questionToken
|
||||||
|
? updateNode(createMethodSignature(typeParameters, parameters, type, name, questionToken), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Types
|
||||||
|
|
||||||
|
export function createKeywordTypeNode(kind: KeywordTypeNode["kind"]) {
|
||||||
|
return <KeywordTypeNode>createSynthesizedNode(kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createThisTypeNode() {
|
||||||
|
return <ThisTypeNode>createSynthesizedNode(SyntaxKind.ThisType);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createLiteralTypeNode(literal: Expression) {
|
||||||
|
const literalTypeNode = createSynthesizedNode(SyntaxKind.LiteralType) as LiteralTypeNode;
|
||||||
|
literalTypeNode.literal = literal;
|
||||||
|
return literalTypeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateLiteralTypeNode(node: LiteralTypeNode, literal: Expression) {
|
||||||
|
return node.literal !== literal
|
||||||
|
? updateNode(createLiteralTypeNode(literal), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTypeReferenceNode(typeName: string | EntityName, typeArguments: TypeNode[] | undefined) {
|
||||||
|
const typeReference = createSynthesizedNode(SyntaxKind.TypeReference) as TypeReferenceNode;
|
||||||
|
typeReference.typeName = asName(typeName);
|
||||||
|
typeReference.typeArguments = asNodeArray(typeArguments);
|
||||||
|
return typeReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray<TypeNode> | undefined) {
|
||||||
|
return node.typeName !== typeName
|
||||||
|
|| node.typeArguments !== typeArguments
|
||||||
|
? updateNode(createTypeReferenceNode(typeName, typeArguments), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode) {
|
||||||
|
const typePredicateNode = createSynthesizedNode(SyntaxKind.TypePredicate) as TypePredicateNode;
|
||||||
|
typePredicateNode.parameterName = asName(parameterName);
|
||||||
|
typePredicateNode.type = type;
|
||||||
|
return typePredicateNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode) {
|
||||||
|
return node.parameterName !== parameterName
|
||||||
|
|| node.type !== type
|
||||||
|
? updateNode(createTypePredicateNode(parameterName, type), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTypeQueryNode(exprName: EntityName) {
|
||||||
|
const typeQueryNode = createSynthesizedNode(SyntaxKind.TypeQuery) as TypeQueryNode;
|
||||||
|
typeQueryNode.exprName = exprName;
|
||||||
|
return typeQueryNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName) {
|
||||||
|
return node.exprName !== exprName ? updateNode(createTypeQueryNode(exprName), node) : node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createArrayTypeNode(elementType: TypeNode) {
|
||||||
|
const arrayTypeNode = createSynthesizedNode(SyntaxKind.ArrayType) as ArrayTypeNode;
|
||||||
|
arrayTypeNode.elementType = elementType;
|
||||||
|
return arrayTypeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode {
|
||||||
|
return node.elementType !== elementType
|
||||||
|
? updateNode(createArrayTypeNode(elementType), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType, types: TypeNode[]): UnionTypeNode;
|
||||||
|
export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.IntersectionType, types: TypeNode[]): IntersectionTypeNode;
|
||||||
|
export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: TypeNode[]): UnionOrIntersectionTypeNode;
|
||||||
|
export function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: TypeNode[]) {
|
||||||
|
const unionTypeNode = createSynthesizedNode(kind) as UnionTypeNode | IntersectionTypeNode;
|
||||||
|
unionTypeNode.types = createNodeArray(types);
|
||||||
|
return unionTypeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateUnionOrIntersectionTypeNode(node: UnionOrIntersectionTypeNode, types: NodeArray<TypeNode>) {
|
||||||
|
return node.types !== types
|
||||||
|
? updateNode(createUnionOrIntersectionTypeNode(node.kind, types), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTypeLiteralNode(members: TypeElement[]) {
|
||||||
|
const typeLiteralNode = createSynthesizedNode(SyntaxKind.TypeLiteral) as TypeLiteralNode;
|
||||||
|
typeLiteralNode.members = createNodeArray(members);
|
||||||
|
return typeLiteralNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray<TypeElement>) {
|
||||||
|
return node.members !== members
|
||||||
|
? updateNode(createTypeLiteralNode(members), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTupleTypeNode(elementTypes: TypeNode[]) {
|
||||||
|
const tupleTypeNode = createSynthesizedNode(SyntaxKind.TupleType) as TupleTypeNode;
|
||||||
|
tupleTypeNode.elementTypes = createNodeArray(elementTypes);
|
||||||
|
return tupleTypeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateTypleTypeNode(node: TupleTypeNode, elementTypes: TypeNode[]) {
|
||||||
|
return node.elementTypes !== elementTypes
|
||||||
|
? updateNode(createTupleTypeNode(elementTypes), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createMappedTypeNode(readonlyToken: ReadonlyToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | undefined, type: TypeNode | undefined): MappedTypeNode {
|
||||||
|
const mappedTypeNode = createSynthesizedNode(SyntaxKind.MappedType) as MappedTypeNode;
|
||||||
|
mappedTypeNode.readonlyToken = readonlyToken;
|
||||||
|
mappedTypeNode.typeParameter = typeParameter;
|
||||||
|
mappedTypeNode.questionToken = questionToken;
|
||||||
|
mappedTypeNode.type = type;
|
||||||
|
return mappedTypeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | undefined, type: TypeNode | undefined): MappedTypeNode {
|
||||||
|
return node.readonlyToken !== readonlyToken
|
||||||
|
|| node.typeParameter !== typeParameter
|
||||||
|
|| node.questionToken !== questionToken
|
||||||
|
|| node.type !== type
|
||||||
|
? updateNode(createMappedTypeNode(readonlyToken, typeParameter, questionToken, type), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTypeOperatorNode(type: TypeNode) {
|
||||||
|
const typeOperatorNode = createSynthesizedNode(SyntaxKind.TypeOperator) as TypeOperatorNode;
|
||||||
|
typeOperatorNode.operator = SyntaxKind.KeyOfKeyword;
|
||||||
|
typeOperatorNode.type = type;
|
||||||
|
return typeOperatorNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode) {
|
||||||
|
return node.type !== type ? updateNode(createTypeOperatorNode(type), node) : node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) {
|
||||||
|
const indexedAccessTypeNode = createSynthesizedNode(SyntaxKind.IndexedAccessType) as IndexedAccessTypeNode;
|
||||||
|
indexedAccessTypeNode.objectType = objectType;
|
||||||
|
indexedAccessTypeNode.indexType = indexType;
|
||||||
|
return indexedAccessTypeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) {
|
||||||
|
return node.objectType !== objectType
|
||||||
|
|| node.indexType !== indexType
|
||||||
|
? updateNode(createIndexedAccessTypeNode(objectType, indexType), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type Declarations
|
||||||
|
|
||||||
|
export function createTypeParameterDeclaration(name: string | Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) {
|
||||||
|
const typeParameter = createSynthesizedNode(SyntaxKind.TypeParameter) as TypeParameterDeclaration;
|
||||||
|
typeParameter.name = asName(name);
|
||||||
|
typeParameter.constraint = constraint;
|
||||||
|
typeParameter.default = defaultType;
|
||||||
|
|
||||||
|
return typeParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) {
|
||||||
|
return node.name !== name
|
||||||
|
|| node.constraint !== constraint
|
||||||
|
|| node.default !== defaultType
|
||||||
|
? updateNode(createTypeParameterDeclaration(name, constraint, defaultType), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signature elements
|
||||||
|
|
||||||
|
export function createPropertySignature(name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined): PropertySignature {
|
||||||
|
const propertySignature = createSynthesizedNode(SyntaxKind.PropertySignature) as PropertySignature;
|
||||||
|
propertySignature.name = asName(name);
|
||||||
|
propertySignature.questionToken = questionToken;
|
||||||
|
propertySignature.type = type;
|
||||||
|
propertySignature.initializer = initializer;
|
||||||
|
return propertySignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updatePropertySignature(node: PropertySignature, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) {
|
||||||
|
return node.name !== name
|
||||||
|
|| node.questionToken !== questionToken
|
||||||
|
|| node.type !== type
|
||||||
|
|| node.initializer !== initializer
|
||||||
|
? updateNode(createPropertySignature(name, questionToken, type, initializer), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createIndexSignatureDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, parameters: ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration {
|
||||||
|
const indexSignature = createSynthesizedNode(SyntaxKind.IndexSignature) as IndexSignatureDeclaration;
|
||||||
|
indexSignature.decorators = asNodeArray(decorators);
|
||||||
|
indexSignature.modifiers = asNodeArray(modifiers);
|
||||||
|
indexSignature.parameters = createNodeArray(parameters);
|
||||||
|
indexSignature.type = type;
|
||||||
|
return indexSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateIndexSignatureDeclaration(node: IndexSignatureDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, parameters: ParameterDeclaration[], type: TypeNode) {
|
||||||
|
return node.parameters !== parameters
|
||||||
|
|| node.type !== type
|
||||||
|
|| node.decorators !== decorators
|
||||||
|
|| node.modifiers !== modifiers
|
||||||
|
? updateNode(createIndexSignatureDeclaration(decorators, modifiers, parameters, type), node)
|
||||||
|
: node;
|
||||||
|
}
|
||||||
|
|
||||||
// Signature elements
|
// Signature elements
|
||||||
|
|
||||||
export function createParameter(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression) {
|
export function createParameter(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression) {
|
||||||
|
@ -227,11 +505,12 @@ namespace ts {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateParameter(node: ParameterDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined) {
|
export function updateParameter(node: ParameterDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) {
|
||||||
return node.decorators !== decorators
|
return node.decorators !== decorators
|
||||||
|| node.modifiers !== modifiers
|
|| node.modifiers !== modifiers
|
||||||
|| node.dotDotDotToken !== dotDotDotToken
|
|| node.dotDotDotToken !== dotDotDotToken
|
||||||
|| node.name !== name
|
|| node.name !== name
|
||||||
|
|| node.questionToken !== questionToken
|
||||||
|| node.type !== type
|
|| node.type !== type
|
||||||
|| node.initializer !== initializer
|
|| node.initializer !== initializer
|
||||||
? updateNode(createParameter(decorators, modifiers, dotDotDotToken, name, node.questionToken, type, initializer), node)
|
? updateNode(createParameter(decorators, modifiers, dotDotDotToken, name, node.questionToken, type, initializer), node)
|
||||||
|
@ -273,12 +552,13 @@ namespace ts {
|
||||||
: node;
|
: node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createMethod(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
export function createMethodDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
||||||
const node = <MethodDeclaration>createSynthesizedNode(SyntaxKind.MethodDeclaration);
|
const node = <MethodDeclaration>createSynthesizedNode(SyntaxKind.MethodDeclaration);
|
||||||
node.decorators = asNodeArray(decorators);
|
node.decorators = asNodeArray(decorators);
|
||||||
node.modifiers = asNodeArray(modifiers);
|
node.modifiers = asNodeArray(modifiers);
|
||||||
node.asteriskToken = asteriskToken;
|
node.asteriskToken = asteriskToken;
|
||||||
node.name = asName(name);
|
node.name = asName(name);
|
||||||
|
node.questionToken = questionToken;
|
||||||
node.typeParameters = asNodeArray(typeParameters);
|
node.typeParameters = asNodeArray(typeParameters);
|
||||||
node.parameters = createNodeArray(parameters);
|
node.parameters = createNodeArray(parameters);
|
||||||
node.type = type;
|
node.type = type;
|
||||||
|
@ -286,7 +566,7 @@ namespace ts {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateMethod(node: MethodDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
export function updateMethod(node: MethodDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
||||||
return node.decorators !== decorators
|
return node.decorators !== decorators
|
||||||
|| node.modifiers !== modifiers
|
|| node.modifiers !== modifiers
|
||||||
|| node.asteriskToken !== asteriskToken
|
|| node.asteriskToken !== asteriskToken
|
||||||
|
@ -295,7 +575,7 @@ namespace ts {
|
||||||
|| node.parameters !== parameters
|
|| node.parameters !== parameters
|
||||||
|| node.type !== type
|
|| node.type !== type
|
||||||
|| node.body !== body
|
|| node.body !== body
|
||||||
? updateNode(createMethod(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body), node)
|
? updateNode(createMethodDeclaration(decorators, modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body), node)
|
||||||
: node;
|
: node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,10 +1379,6 @@ namespace ts {
|
||||||
: node;
|
: node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createKeywordTypeNode(kind: KeywordTypeNode["kind"]): KeywordTypeNode {
|
|
||||||
return <KeywordTypeNode>createSynthesizedNode(kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createFunctionDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
export function createFunctionDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
||||||
const node = <FunctionDeclaration>createSynthesizedNode(SyntaxKind.FunctionDeclaration);
|
const node = <FunctionDeclaration>createSynthesizedNode(SyntaxKind.FunctionDeclaration);
|
||||||
node.decorators = asNodeArray(decorators);
|
node.decorators = asNodeArray(decorators);
|
||||||
|
@ -1793,7 +2069,9 @@ namespace ts {
|
||||||
function asName(name: string | Identifier): Identifier;
|
function asName(name: string | Identifier): Identifier;
|
||||||
function asName(name: string | BindingName): BindingName;
|
function asName(name: string | BindingName): BindingName;
|
||||||
function asName(name: string | PropertyName): PropertyName;
|
function asName(name: string | PropertyName): PropertyName;
|
||||||
function asName(name: string | Identifier | BindingName | PropertyName) {
|
function asName(name: string | EntityName): EntityName;
|
||||||
|
function asName(name: string | Identifier | ThisTypeNode): Identifier | ThisTypeNode;
|
||||||
|
function asName(name: string | Identifier | BindingName | PropertyName | QualifiedName | ThisTypeNode) {
|
||||||
return typeof name === "string" ? createIdentifier(name) : name;
|
return typeof name === "string" ? createIdentifier(name) : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,7 @@ namespace ts {
|
||||||
visitNodes(node.modifiers, visitor, isModifier),
|
visitNodes(node.modifiers, visitor, isModifier),
|
||||||
node.asteriskToken,
|
node.asteriskToken,
|
||||||
node.name,
|
node.name,
|
||||||
|
/*questionToken*/ undefined,
|
||||||
/*typeParameters*/ undefined,
|
/*typeParameters*/ undefined,
|
||||||
visitParameterList(node.parameters, visitor, context),
|
visitParameterList(node.parameters, visitor, context),
|
||||||
/*type*/ undefined,
|
/*type*/ undefined,
|
||||||
|
|
|
@ -475,6 +475,7 @@ namespace ts {
|
||||||
/*modifiers*/ undefined,
|
/*modifiers*/ undefined,
|
||||||
node.dotDotDotToken,
|
node.dotDotDotToken,
|
||||||
getGeneratedNameForNode(node),
|
getGeneratedNameForNode(node),
|
||||||
|
/*questionToken*/ undefined,
|
||||||
/*type*/ undefined,
|
/*type*/ undefined,
|
||||||
visitNode(node.initializer, visitor, isExpression)
|
visitNode(node.initializer, visitor, isExpression)
|
||||||
);
|
);
|
||||||
|
@ -540,6 +541,7 @@ namespace ts {
|
||||||
? undefined
|
? undefined
|
||||||
: node.asteriskToken,
|
: node.asteriskToken,
|
||||||
visitNode(node.name, visitor, isPropertyName),
|
visitNode(node.name, visitor, isPropertyName),
|
||||||
|
visitNode(/*questionToken*/ undefined, visitor, isToken),
|
||||||
/*typeParameters*/ undefined,
|
/*typeParameters*/ undefined,
|
||||||
visitParameterList(node.parameters, visitor, context),
|
visitParameterList(node.parameters, visitor, context),
|
||||||
/*type*/ undefined,
|
/*type*/ undefined,
|
||||||
|
|
|
@ -2049,6 +2049,7 @@ namespace ts {
|
||||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||||
node.asteriskToken,
|
node.asteriskToken,
|
||||||
visitPropertyNameOfClassElement(node),
|
visitPropertyNameOfClassElement(node),
|
||||||
|
/*questionToken*/ undefined,
|
||||||
/*typeParameters*/ undefined,
|
/*typeParameters*/ undefined,
|
||||||
visitParameterList(node.parameters, visitor, context),
|
visitParameterList(node.parameters, visitor, context),
|
||||||
/*type*/ undefined,
|
/*type*/ undefined,
|
||||||
|
|
|
@ -819,7 +819,7 @@ namespace ts {
|
||||||
body?: FunctionBody;
|
body?: FunctionBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For when we encounter a semicolon in a class declaration. ES6 allows these as class elements.
|
/** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements.*/
|
||||||
export interface SemicolonClassElement extends ClassElement {
|
export interface SemicolonClassElement extends ClassElement {
|
||||||
kind: SyntaxKind.SemicolonClassElement;
|
kind: SyntaxKind.SemicolonClassElement;
|
||||||
parent?: ClassDeclaration | ClassExpression;
|
parent?: ClassDeclaration | ClassExpression;
|
||||||
|
@ -861,7 +861,11 @@ namespace ts {
|
||||||
| SyntaxKind.BooleanKeyword
|
| SyntaxKind.BooleanKeyword
|
||||||
| SyntaxKind.StringKeyword
|
| SyntaxKind.StringKeyword
|
||||||
| SyntaxKind.SymbolKeyword
|
| SyntaxKind.SymbolKeyword
|
||||||
| SyntaxKind.VoidKeyword;
|
| SyntaxKind.ThisKeyword
|
||||||
|
| SyntaxKind.VoidKeyword
|
||||||
|
| SyntaxKind.UndefinedKeyword
|
||||||
|
| SyntaxKind.NullKeyword
|
||||||
|
| SyntaxKind.NeverKeyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ThisTypeNode extends TypeNode {
|
export interface ThisTypeNode extends TypeNode {
|
||||||
|
@ -1030,15 +1034,15 @@ namespace ts {
|
||||||
_primaryExpressionBrand: any;
|
_primaryExpressionBrand: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NullLiteral extends PrimaryExpression {
|
export interface NullLiteral extends PrimaryExpression, TypeNode {
|
||||||
kind: SyntaxKind.NullKeyword;
|
kind: SyntaxKind.NullKeyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BooleanLiteral extends PrimaryExpression {
|
export interface BooleanLiteral extends PrimaryExpression, TypeNode {
|
||||||
kind: SyntaxKind.TrueKeyword | SyntaxKind.FalseKeyword;
|
kind: SyntaxKind.TrueKeyword | SyntaxKind.FalseKeyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ThisExpression extends PrimaryExpression {
|
export interface ThisExpression extends PrimaryExpression, KeywordTypeNode {
|
||||||
kind: SyntaxKind.ThisKeyword;
|
kind: SyntaxKind.ThisKeyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2472,6 +2476,14 @@ namespace ts {
|
||||||
/* @internal */ getParameterType(signature: Signature, parameterIndex: number): Type;
|
/* @internal */ getParameterType(signature: Signature, parameterIndex: number): Type;
|
||||||
getNonNullableType(type: Type): Type;
|
getNonNullableType(type: Type): Type;
|
||||||
|
|
||||||
|
/** Note that the resulting nodes cannot be checked. */
|
||||||
|
|
||||||
|
typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode;
|
||||||
|
/** Note that the resulting nodes cannot be checked. */
|
||||||
|
signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): SignatureDeclaration;
|
||||||
|
/** Note that the resulting nodes cannot be checked. */
|
||||||
|
indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): IndexSignatureDeclaration;
|
||||||
|
|
||||||
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
|
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
|
||||||
getSymbolAtLocation(node: Node): Symbol;
|
getSymbolAtLocation(node: Node): Symbol;
|
||||||
getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[];
|
getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[];
|
||||||
|
@ -2523,6 +2535,16 @@ namespace ts {
|
||||||
/* @internal */ getTypeCount(): number;
|
/* @internal */ getTypeCount(): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum NodeBuilderFlags {
|
||||||
|
None = 0,
|
||||||
|
allowThisInObjectLiteral = 1 << 0,
|
||||||
|
allowQualifedNameInPlaceOfIdentifier = 1 << 1,
|
||||||
|
allowTypeParameterInQualifiedName = 1 << 2,
|
||||||
|
allowAnonymousIdentifier = 1 << 3,
|
||||||
|
allowEmptyUnionOrIntersection = 1 << 4,
|
||||||
|
allowEmptyTuple = 1 << 5
|
||||||
|
}
|
||||||
|
|
||||||
export interface SymbolDisplayBuilder {
|
export interface SymbolDisplayBuilder {
|
||||||
buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||||
buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
|
buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
|
||||||
|
@ -4073,7 +4095,7 @@ namespace ts {
|
||||||
export type Transformer<T extends Node> = (node: T) => T;
|
export type Transformer<T extends Node> = (node: T) => T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function that accepts and possible transforms a node.
|
* A function that accepts and possibly transforms a node.
|
||||||
*/
|
*/
|
||||||
export type Visitor = (node: Node) => VisitResult<Node>;
|
export type Visitor = (node: Node) => VisitResult<Node>;
|
||||||
|
|
||||||
|
|
|
@ -525,6 +525,10 @@ namespace ts {
|
||||||
return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
|
return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getNameFromIndexInfo(info: IndexInfo) {
|
||||||
|
return info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export function getTextOfPropertyName(name: PropertyName): string {
|
export function getTextOfPropertyName(name: PropertyName): string {
|
||||||
switch (name.kind) {
|
switch (name.kind) {
|
||||||
case SyntaxKind.Identifier:
|
case SyntaxKind.Identifier:
|
||||||
|
@ -740,8 +744,8 @@ namespace ts {
|
||||||
//
|
//
|
||||||
// let a: A.B.C;
|
// let a: A.B.C;
|
||||||
//
|
//
|
||||||
// Calling isPartOfTypeNode would consider the qualified name A.B a type node. Only C or
|
// Calling isPartOfTypeNode would consider the qualified name A.B a type node.
|
||||||
// A.B.C is a type node.
|
// Only C and A.B.C are type nodes.
|
||||||
if (SyntaxKind.FirstTypeNode <= parent.kind && parent.kind <= SyntaxKind.LastTypeNode) {
|
if (SyntaxKind.FirstTypeNode <= parent.kind && parent.kind <= SyntaxKind.LastTypeNode) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3713,10 +3717,14 @@ namespace ts {
|
||||||
return (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode)
|
return (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode)
|
||||||
|| kind === SyntaxKind.AnyKeyword
|
|| kind === SyntaxKind.AnyKeyword
|
||||||
|| kind === SyntaxKind.NumberKeyword
|
|| kind === SyntaxKind.NumberKeyword
|
||||||
|
|| kind === SyntaxKind.ObjectKeyword
|
||||||
|| kind === SyntaxKind.BooleanKeyword
|
|| kind === SyntaxKind.BooleanKeyword
|
||||||
|| kind === SyntaxKind.StringKeyword
|
|| kind === SyntaxKind.StringKeyword
|
||||||
|| kind === SyntaxKind.SymbolKeyword
|
|| kind === SyntaxKind.SymbolKeyword
|
||||||
|
|| kind === SyntaxKind.ThisKeyword
|
||||||
|| kind === SyntaxKind.VoidKeyword
|
|| kind === SyntaxKind.VoidKeyword
|
||||||
|
|| kind === SyntaxKind.UndefinedKeyword
|
||||||
|
|| kind === SyntaxKind.NullKeyword
|
||||||
|| kind === SyntaxKind.NeverKeyword
|
|| kind === SyntaxKind.NeverKeyword
|
||||||
|| kind === SyntaxKind.ExpressionWithTypeArguments;
|
|| kind === SyntaxKind.ExpressionWithTypeArguments;
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,21 +204,17 @@ namespace ts {
|
||||||
* @param visitor The callback used to visit each child.
|
* @param visitor The callback used to visit each child.
|
||||||
* @param context A lexical environment context for the visitor.
|
* @param context A lexical environment context for the visitor.
|
||||||
*/
|
*/
|
||||||
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): T | undefined;
|
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined;
|
||||||
|
|
||||||
export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes): Node {
|
export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor): Node {
|
||||||
if (node === undefined) {
|
if (node === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const kind = node.kind;
|
const kind = node.kind;
|
||||||
// No need to visit nodes with no children.
|
|
||||||
if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken)) {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We do not yet support types.
|
// No need to visit nodes with no children.
|
||||||
if ((kind >= SyntaxKind.TypePredicate && kind <= SyntaxKind.LiteralType)) {
|
if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken) || kind === SyntaxKind.ThisType) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +223,8 @@ namespace ts {
|
||||||
case SyntaxKind.EmptyStatement:
|
case SyntaxKind.EmptyStatement:
|
||||||
case SyntaxKind.OmittedExpression:
|
case SyntaxKind.OmittedExpression:
|
||||||
case SyntaxKind.DebuggerStatement:
|
case SyntaxKind.DebuggerStatement:
|
||||||
|
case SyntaxKind.EndOfDeclarationMarker:
|
||||||
|
case SyntaxKind.MissingDeclaration:
|
||||||
// No need to visit nodes with no children.
|
// No need to visit nodes with no children.
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
|
@ -240,13 +238,53 @@ namespace ts {
|
||||||
return updateComputedPropertyName(<ComputedPropertyName>node,
|
return updateComputedPropertyName(<ComputedPropertyName>node,
|
||||||
visitNode((<ComputedPropertyName>node).expression, visitor, isExpression));
|
visitNode((<ComputedPropertyName>node).expression, visitor, isExpression));
|
||||||
|
|
||||||
// Signature elements
|
// Signatures and Signature Elements
|
||||||
|
case SyntaxKind.FunctionType:
|
||||||
|
return updateFunctionTypeNode(<FunctionTypeNode>node,
|
||||||
|
nodesVisitor((<FunctionTypeNode>node).typeParameters, visitor, isTypeParameter),
|
||||||
|
visitParameterList((<FunctionTypeNode>node).parameters, visitor, context, nodesVisitor),
|
||||||
|
visitNode((<FunctionTypeNode>node).type, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.ConstructorType:
|
||||||
|
return updateConstructorTypeNode(<ConstructorTypeNode>node,
|
||||||
|
nodesVisitor((<ConstructorTypeNode>node).typeParameters, visitor, isTypeParameter),
|
||||||
|
visitParameterList((<ConstructorTypeNode>node).parameters, visitor, context, nodesVisitor),
|
||||||
|
visitNode((<ConstructorTypeNode>node).type, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.CallSignature:
|
||||||
|
return updateCallSignatureDeclaration(<CallSignatureDeclaration>node,
|
||||||
|
nodesVisitor((<CallSignatureDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||||
|
visitParameterList((<CallSignatureDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||||
|
visitNode((<CallSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.ConstructSignature:
|
||||||
|
return updateConstructSignatureDeclaration(<ConstructSignatureDeclaration>node,
|
||||||
|
nodesVisitor((<ConstructSignatureDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||||
|
visitParameterList((<ConstructSignatureDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||||
|
visitNode((<ConstructSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.MethodSignature:
|
||||||
|
return updateMethodSignature(<MethodSignature>node,
|
||||||
|
nodesVisitor((<MethodSignature>node).typeParameters, visitor, isTypeParameter),
|
||||||
|
visitParameterList((<MethodSignature>node).parameters, visitor, context, nodesVisitor),
|
||||||
|
visitNode((<MethodSignature>node).type, visitor, isTypeNode),
|
||||||
|
visitNode((<MethodSignature>node).name, visitor, isPropertyName),
|
||||||
|
visitNode((<MethodSignature>node).questionToken, tokenVisitor, isToken));
|
||||||
|
|
||||||
|
case SyntaxKind.IndexSignature:
|
||||||
|
return updateIndexSignatureDeclaration(<IndexSignatureDeclaration>node,
|
||||||
|
nodesVisitor((<IndexSignatureDeclaration>node).decorators, visitor, isDecorator),
|
||||||
|
nodesVisitor((<IndexSignatureDeclaration>node).modifiers, visitor, isModifier),
|
||||||
|
visitParameterList((<IndexSignatureDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||||
|
visitNode((<IndexSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||||
|
|
||||||
case SyntaxKind.Parameter:
|
case SyntaxKind.Parameter:
|
||||||
return updateParameter(<ParameterDeclaration>node,
|
return updateParameter(<ParameterDeclaration>node,
|
||||||
nodesVisitor((<ParameterDeclaration>node).decorators, visitor, isDecorator),
|
nodesVisitor((<ParameterDeclaration>node).decorators, visitor, isDecorator),
|
||||||
nodesVisitor((<ParameterDeclaration>node).modifiers, visitor, isModifier),
|
nodesVisitor((<ParameterDeclaration>node).modifiers, visitor, isModifier),
|
||||||
(<ParameterDeclaration>node).dotDotDotToken,
|
visitNode((<ParameterDeclaration>node).dotDotDotToken, tokenVisitor, isToken),
|
||||||
visitNode((<ParameterDeclaration>node).name, visitor, isBindingName),
|
visitNode((<ParameterDeclaration>node).name, visitor, isBindingName),
|
||||||
|
visitNode((<ParameterDeclaration>node).questionToken, tokenVisitor, isToken),
|
||||||
visitNode((<ParameterDeclaration>node).type, visitor, isTypeNode),
|
visitNode((<ParameterDeclaration>node).type, visitor, isTypeNode),
|
||||||
visitNode((<ParameterDeclaration>node).initializer, visitor, isExpression));
|
visitNode((<ParameterDeclaration>node).initializer, visitor, isExpression));
|
||||||
|
|
||||||
|
@ -254,7 +292,74 @@ namespace ts {
|
||||||
return updateDecorator(<Decorator>node,
|
return updateDecorator(<Decorator>node,
|
||||||
visitNode((<Decorator>node).expression, visitor, isExpression));
|
visitNode((<Decorator>node).expression, visitor, isExpression));
|
||||||
|
|
||||||
// Type member
|
// Types
|
||||||
|
|
||||||
|
case SyntaxKind.TypeReference:
|
||||||
|
return updateTypeReferenceNode(<TypeReferenceNode>node,
|
||||||
|
visitNode((<TypeReferenceNode>node).typeName, visitor, isEntityName),
|
||||||
|
nodesVisitor((<TypeReferenceNode>node).typeArguments, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.TypePredicate:
|
||||||
|
return updateTypePredicateNode(<TypePredicateNode>node,
|
||||||
|
visitNode((<TypePredicateNode>node).parameterName, visitor),
|
||||||
|
visitNode((<TypePredicateNode>node).type, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.TypeQuery:
|
||||||
|
return updateTypeQueryNode((<TypeQueryNode>node), visitNode((<TypeQueryNode>node).exprName, visitor, isEntityName));
|
||||||
|
|
||||||
|
case SyntaxKind.TypeLiteral:
|
||||||
|
return updateTypeLiteralNode((<TypeLiteralNode>node), nodesVisitor((<TypeLiteralNode>node).members, visitor));
|
||||||
|
|
||||||
|
case SyntaxKind.ArrayType:
|
||||||
|
return updateArrayTypeNode(<ArrayTypeNode>node, visitNode((<ArrayTypeNode>node).elementType, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.TupleType:
|
||||||
|
return updateTypleTypeNode((<TupleTypeNode>node), nodesVisitor((<TupleTypeNode>node).elementTypes, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.UnionType:
|
||||||
|
case SyntaxKind.IntersectionType:
|
||||||
|
return updateUnionOrIntersectionTypeNode(<UnionOrIntersectionTypeNode>node,
|
||||||
|
nodesVisitor((<UnionOrIntersectionTypeNode>node).types, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.ParenthesizedType:
|
||||||
|
Debug.fail("not implemented.");
|
||||||
|
|
||||||
|
case SyntaxKind.TypeOperator:
|
||||||
|
return updateTypeOperatorNode(<TypeOperatorNode>node, visitNode((<TypeOperatorNode>node).type, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.IndexedAccessType:
|
||||||
|
return updateIndexedAccessTypeNode((<IndexedAccessTypeNode>node),
|
||||||
|
visitNode((<IndexedAccessTypeNode>node).objectType, visitor, isTypeNode),
|
||||||
|
visitNode((<IndexedAccessTypeNode>node).indexType, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.MappedType:
|
||||||
|
return updateMappedTypeNode((<MappedTypeNode>node),
|
||||||
|
visitNode((<MappedTypeNode>node).readonlyToken, tokenVisitor, isToken),
|
||||||
|
visitNode((<MappedTypeNode>node).typeParameter, visitor, isTypeParameter),
|
||||||
|
visitNode((<MappedTypeNode>node).questionToken, tokenVisitor, isToken),
|
||||||
|
visitNode((<MappedTypeNode>node).type, visitor, isTypeNode));
|
||||||
|
|
||||||
|
case SyntaxKind.LiteralType:
|
||||||
|
return updateLiteralTypeNode(<LiteralTypeNode>node,
|
||||||
|
visitNode((<LiteralTypeNode>node).literal, visitor, isExpression));
|
||||||
|
|
||||||
|
// Type Declarations
|
||||||
|
|
||||||
|
case SyntaxKind.TypeParameter:
|
||||||
|
return updateTypeParameterDeclaration(<TypeParameterDeclaration>node,
|
||||||
|
visitNode((<TypeParameterDeclaration>node).name, visitor, isIdentifier),
|
||||||
|
visitNode((<TypeParameterDeclaration>node).constraint, visitor, isTypeNode),
|
||||||
|
visitNode((<TypeParameterDeclaration>node).default, visitor, isTypeNode));
|
||||||
|
|
||||||
|
// Type members
|
||||||
|
|
||||||
|
case SyntaxKind.PropertySignature:
|
||||||
|
return updatePropertySignature((<PropertySignature>node),
|
||||||
|
visitNode((<PropertySignature>node).name, visitor, isPropertyName),
|
||||||
|
visitNode((<PropertySignature>node).questionToken, tokenVisitor, isToken),
|
||||||
|
visitNode((<PropertySignature>node).type, visitor, isTypeNode),
|
||||||
|
visitNode((<PropertySignature>node).initializer, visitor, isExpression));
|
||||||
|
|
||||||
case SyntaxKind.PropertyDeclaration:
|
case SyntaxKind.PropertyDeclaration:
|
||||||
return updateProperty(<PropertyDeclaration>node,
|
return updateProperty(<PropertyDeclaration>node,
|
||||||
nodesVisitor((<PropertyDeclaration>node).decorators, visitor, isDecorator),
|
nodesVisitor((<PropertyDeclaration>node).decorators, visitor, isDecorator),
|
||||||
|
@ -267,8 +372,9 @@ namespace ts {
|
||||||
return updateMethod(<MethodDeclaration>node,
|
return updateMethod(<MethodDeclaration>node,
|
||||||
nodesVisitor((<MethodDeclaration>node).decorators, visitor, isDecorator),
|
nodesVisitor((<MethodDeclaration>node).decorators, visitor, isDecorator),
|
||||||
nodesVisitor((<MethodDeclaration>node).modifiers, visitor, isModifier),
|
nodesVisitor((<MethodDeclaration>node).modifiers, visitor, isModifier),
|
||||||
(<MethodDeclaration>node).asteriskToken,
|
visitNode((<MethodDeclaration>node).asteriskToken, tokenVisitor, isToken),
|
||||||
visitNode((<MethodDeclaration>node).name, visitor, isPropertyName),
|
visitNode((<MethodDeclaration>node).name, visitor, isPropertyName),
|
||||||
|
visitNode((<MethodDeclaration>node).questionToken, tokenVisitor, isToken),
|
||||||
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
|
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||||
visitParameterList((<MethodDeclaration>node).parameters, visitor, context, nodesVisitor),
|
visitParameterList((<MethodDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||||
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode),
|
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode),
|
||||||
|
@ -309,7 +415,7 @@ namespace ts {
|
||||||
|
|
||||||
case SyntaxKind.BindingElement:
|
case SyntaxKind.BindingElement:
|
||||||
return updateBindingElement(<BindingElement>node,
|
return updateBindingElement(<BindingElement>node,
|
||||||
(<BindingElement>node).dotDotDotToken,
|
visitNode((<BindingElement>node).dotDotDotToken, tokenVisitor, isToken),
|
||||||
visitNode((<BindingElement>node).propertyName, visitor, isPropertyName),
|
visitNode((<BindingElement>node).propertyName, visitor, isPropertyName),
|
||||||
visitNode((<BindingElement>node).name, visitor, isBindingName),
|
visitNode((<BindingElement>node).name, visitor, isBindingName),
|
||||||
visitNode((<BindingElement>node).initializer, visitor, isExpression));
|
visitNode((<BindingElement>node).initializer, visitor, isExpression));
|
||||||
|
@ -362,7 +468,7 @@ namespace ts {
|
||||||
case SyntaxKind.FunctionExpression:
|
case SyntaxKind.FunctionExpression:
|
||||||
return updateFunctionExpression(<FunctionExpression>node,
|
return updateFunctionExpression(<FunctionExpression>node,
|
||||||
nodesVisitor((<FunctionExpression>node).modifiers, visitor, isModifier),
|
nodesVisitor((<FunctionExpression>node).modifiers, visitor, isModifier),
|
||||||
(<FunctionExpression>node).asteriskToken,
|
visitNode((<FunctionExpression>node).asteriskToken, tokenVisitor, isToken),
|
||||||
visitNode((<FunctionExpression>node).name, visitor, isIdentifier),
|
visitNode((<FunctionExpression>node).name, visitor, isIdentifier),
|
||||||
nodesVisitor((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
|
nodesVisitor((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
|
||||||
visitParameterList((<FunctionExpression>node).parameters, visitor, context, nodesVisitor),
|
visitParameterList((<FunctionExpression>node).parameters, visitor, context, nodesVisitor),
|
||||||
|
@ -419,7 +525,7 @@ namespace ts {
|
||||||
|
|
||||||
case SyntaxKind.YieldExpression:
|
case SyntaxKind.YieldExpression:
|
||||||
return updateYield(<YieldExpression>node,
|
return updateYield(<YieldExpression>node,
|
||||||
(<YieldExpression>node).asteriskToken,
|
visitNode((<YieldExpression>node).asteriskToken, tokenVisitor, isToken),
|
||||||
visitNode((<YieldExpression>node).expression, visitor, isExpression));
|
visitNode((<YieldExpression>node).expression, visitor, isExpression));
|
||||||
|
|
||||||
case SyntaxKind.SpreadElement:
|
case SyntaxKind.SpreadElement:
|
||||||
|
@ -555,7 +661,7 @@ namespace ts {
|
||||||
return updateFunctionDeclaration(<FunctionDeclaration>node,
|
return updateFunctionDeclaration(<FunctionDeclaration>node,
|
||||||
nodesVisitor((<FunctionDeclaration>node).decorators, visitor, isDecorator),
|
nodesVisitor((<FunctionDeclaration>node).decorators, visitor, isDecorator),
|
||||||
nodesVisitor((<FunctionDeclaration>node).modifiers, visitor, isModifier),
|
nodesVisitor((<FunctionDeclaration>node).modifiers, visitor, isModifier),
|
||||||
(<FunctionDeclaration>node).asteriskToken,
|
visitNode((<FunctionDeclaration>node).asteriskToken, tokenVisitor, isToken),
|
||||||
visitNode((<FunctionDeclaration>node).name, visitor, isIdentifier),
|
visitNode((<FunctionDeclaration>node).name, visitor, isIdentifier),
|
||||||
nodesVisitor((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameter),
|
nodesVisitor((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||||
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context, nodesVisitor),
|
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||||
|
|
|
@ -31,37 +31,55 @@ namespace ts.codefix {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let typeString = "any";
|
let typeNode: TypeNode;
|
||||||
|
|
||||||
if (token.parent.parent.kind === SyntaxKind.BinaryExpression) {
|
if (token.parent.parent.kind === SyntaxKind.BinaryExpression) {
|
||||||
const binaryExpression = token.parent.parent as BinaryExpression;
|
const binaryExpression = token.parent.parent as BinaryExpression;
|
||||||
|
|
||||||
const checker = context.program.getTypeChecker();
|
const checker = context.program.getTypeChecker();
|
||||||
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(binaryExpression.right)));
|
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(binaryExpression.right)));
|
||||||
typeString = checker.typeToString(widenedType);
|
typeNode = checker.typeToTypeNode(widenedType, classDeclaration) || typeNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const startPos = classDeclaration.members.pos;
|
typeNode = typeNode ? typeNode : createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||||
|
|
||||||
|
const openBrace = getOpenBraceOfClassLike(classDeclaration, sourceFile);
|
||||||
|
|
||||||
|
const property = createProperty(
|
||||||
|
/*decorators*/undefined,
|
||||||
|
/*modifiers*/ undefined,
|
||||||
|
token.getText(sourceFile),
|
||||||
|
/*questionToken*/ undefined,
|
||||||
|
typeNode,
|
||||||
|
/*initializer*/ undefined);
|
||||||
|
const propertyChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||||
|
propertyChangeTracker.insertNodeAfter(sourceFile, openBrace, property, { suffix: context.newLineCharacter });
|
||||||
|
|
||||||
|
const stringTypeNode = createKeywordTypeNode(SyntaxKind.StringKeyword);
|
||||||
|
const indexingParameter = createParameter(
|
||||||
|
/*decorators*/ undefined,
|
||||||
|
/*modifiers*/ undefined,
|
||||||
|
/*dotDotDotToken*/ undefined,
|
||||||
|
"x",
|
||||||
|
/*questionToken*/ undefined,
|
||||||
|
stringTypeNode,
|
||||||
|
/*initializer*/ undefined);
|
||||||
|
const indexSignature = createIndexSignatureDeclaration(
|
||||||
|
/*decorators*/undefined,
|
||||||
|
/*modifiers*/ undefined,
|
||||||
|
[indexingParameter],
|
||||||
|
typeNode);
|
||||||
|
|
||||||
|
const indexSignatureChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||||
|
indexSignatureChangeTracker.insertNodeAfter(sourceFile, openBrace, indexSignature, { suffix: context.newLineCharacter });
|
||||||
|
|
||||||
return [{
|
return [{
|
||||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]),
|
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]),
|
||||||
changes: [{
|
changes: propertyChangeTracker.getChanges()
|
||||||
fileName: sourceFile.fileName,
|
|
||||||
textChanges: [{
|
|
||||||
span: { start: startPos, length: 0 },
|
|
||||||
newText: `${token.getFullText(sourceFile)}: ${typeString};`
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_missing_property_0), [token.getText()]),
|
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_missing_property_0), [token.getText()]),
|
||||||
changes: [{
|
changes: indexSignatureChangeTracker.getChanges()
|
||||||
fileName: sourceFile.fileName,
|
|
||||||
textChanges: [{
|
|
||||||
span: { start: startPos, length: 0 },
|
|
||||||
newText: `[name: string]: ${typeString};`
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,10 +19,9 @@ namespace ts.codefix {
|
||||||
const checker = context.program.getTypeChecker();
|
const checker = context.program.getTypeChecker();
|
||||||
|
|
||||||
if (isClassLike(token.parent)) {
|
if (isClassLike(token.parent)) {
|
||||||
const classDecl = token.parent as ClassLikeDeclaration;
|
const classDeclaration = token.parent as ClassLikeDeclaration;
|
||||||
const startPos = classDecl.members.pos;
|
|
||||||
|
|
||||||
const extendsNode = getClassExtendsHeritageClauseElement(classDecl);
|
const extendsNode = getClassExtendsHeritageClauseElement(classDeclaration);
|
||||||
const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode);
|
const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode);
|
||||||
|
|
||||||
// Note that this is ultimately derived from a map indexed by symbol names,
|
// Note that this is ultimately derived from a map indexed by symbol names,
|
||||||
|
@ -30,18 +29,12 @@ namespace ts.codefix {
|
||||||
const extendsSymbols = checker.getPropertiesOfType(instantiatedExtendsType);
|
const extendsSymbols = checker.getPropertiesOfType(instantiatedExtendsType);
|
||||||
const abstractAndNonPrivateExtendsSymbols = extendsSymbols.filter(symbolPointsToNonPrivateAndAbstractMember);
|
const abstractAndNonPrivateExtendsSymbols = extendsSymbols.filter(symbolPointsToNonPrivateAndAbstractMember);
|
||||||
|
|
||||||
const insertion = getMissingMembersInsertion(classDecl, abstractAndNonPrivateExtendsSymbols, checker, context.newLineCharacter);
|
const newNodes = createMissingMemberNodes(classDeclaration, abstractAndNonPrivateExtendsSymbols, checker);
|
||||||
|
const changes = newNodesToChanges(newNodes, getOpenBraceOfClassLike(classDeclaration, sourceFile), context);
|
||||||
if (insertion.length) {
|
if (changes && changes.length > 0) {
|
||||||
return [{
|
return [{
|
||||||
description: getLocaleSpecificMessage(Diagnostics.Implement_inherited_abstract_class),
|
description: getLocaleSpecificMessage(Diagnostics.Implement_inherited_abstract_class),
|
||||||
changes: [{
|
changes
|
||||||
fileName: sourceFile.fileName,
|
|
||||||
textChanges: [{
|
|
||||||
span: { start: startPos, length: 0 },
|
|
||||||
newText: insertion
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,14 @@ namespace ts.codefix {
|
||||||
const token = getTokenAtPosition(sourceFile, start);
|
const token = getTokenAtPosition(sourceFile, start);
|
||||||
const checker = context.program.getTypeChecker();
|
const checker = context.program.getTypeChecker();
|
||||||
|
|
||||||
const classDecl = getContainingClass(token);
|
const classDeclaration = getContainingClass(token);
|
||||||
if (!classDecl) {
|
if (!classDeclaration) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const startPos: number = classDecl.members.pos;
|
const openBrace = getOpenBraceOfClassLike(classDeclaration, sourceFile);
|
||||||
const classType = checker.getTypeAtLocation(classDecl) as InterfaceType;
|
const classType = checker.getTypeAtLocation(classDeclaration) as InterfaceType;
|
||||||
const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl);
|
const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDeclaration);
|
||||||
|
|
||||||
const hasNumericIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.Number);
|
const hasNumericIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.Number);
|
||||||
const hasStringIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.String);
|
const hasStringIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.String);
|
||||||
|
@ -31,43 +31,36 @@ namespace ts.codefix {
|
||||||
const implementedTypeSymbols = checker.getPropertiesOfType(implementedType);
|
const implementedTypeSymbols = checker.getPropertiesOfType(implementedType);
|
||||||
const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private));
|
const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private));
|
||||||
|
|
||||||
let insertion = getMissingIndexSignatureInsertion(implementedType, IndexKind.Number, classDecl, hasNumericIndexSignature);
|
let newNodes: Node[] = [];
|
||||||
insertion += getMissingIndexSignatureInsertion(implementedType, IndexKind.String, classDecl, hasStringIndexSignature);
|
createAndAddMissingIndexSignatureDeclaration(implementedType, IndexKind.Number, hasNumericIndexSignature, newNodes);
|
||||||
insertion += getMissingMembersInsertion(classDecl, nonPrivateMembers, checker, context.newLineCharacter);
|
createAndAddMissingIndexSignatureDeclaration(implementedType, IndexKind.String, hasStringIndexSignature, newNodes);
|
||||||
|
newNodes = newNodes.concat(createMissingMemberNodes(classDeclaration, nonPrivateMembers, checker));
|
||||||
const message = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Implement_interface_0), [implementedTypeNode.getText()]);
|
const message = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Implement_interface_0), [implementedTypeNode.getText()]);
|
||||||
if (insertion) {
|
if (newNodes.length > 0) {
|
||||||
pushAction(result, insertion, message);
|
pushAction(result, newNodes, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
function getMissingIndexSignatureInsertion(type: InterfaceType, kind: IndexKind, enclosingDeclaration: ClassLikeDeclaration, hasIndexSigOfKind: boolean) {
|
function createAndAddMissingIndexSignatureDeclaration(type: InterfaceType, kind: IndexKind, hasIndexSigOfKind: boolean, newNodes: Node[]): void {
|
||||||
if (!hasIndexSigOfKind) {
|
if (hasIndexSigOfKind) {
|
||||||
const IndexInfoOfKind = checker.getIndexInfoOfType(type, kind);
|
return;
|
||||||
if (IndexInfoOfKind) {
|
|
||||||
const writer = getSingleLineStringWriter();
|
|
||||||
checker.getSymbolDisplayBuilder().buildIndexSignatureDisplay(IndexInfoOfKind, writer, kind, enclosingDeclaration);
|
|
||||||
const result = writer.string();
|
|
||||||
releaseStringWriter(writer);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return "";
|
|
||||||
|
const indexInfoOfKind = checker.getIndexInfoOfType(type, kind);
|
||||||
|
|
||||||
|
if (!indexInfoOfKind) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newIndexSignatureDeclaration = checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration);
|
||||||
|
newNodes.push(newIndexSignatureDeclaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
function pushAction(result: CodeAction[], insertion: string, description: string): void {
|
function pushAction(result: CodeAction[], newNodes: Node[], description: string): void {
|
||||||
const newAction: CodeAction = {
|
const newAction: CodeAction = {
|
||||||
description: description,
|
description: description,
|
||||||
changes: [{
|
changes: newNodesToChanges(newNodes, openBrace, context)
|
||||||
fileName: sourceFile.fileName,
|
|
||||||
textChanges: [{
|
|
||||||
span: { start: startPos, length: 0 },
|
|
||||||
newText: insertion
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
};
|
};
|
||||||
result.push(newAction);
|
result.push(newAction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace ts.codefix {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// figure out if the this access is actuall inside the supercall
|
// figure out if the `this` access is actually inside the supercall
|
||||||
// i.e. super(this.a), since in that case we won't suggest a fix
|
// i.e. super(this.a), since in that case we won't suggest a fix
|
||||||
if (superCall.expression && superCall.expression.kind == SyntaxKind.CallExpression) {
|
if (superCall.expression && superCall.expression.kind == SyntaxKind.CallExpression) {
|
||||||
const arguments = (<CallExpression>superCall.expression).arguments;
|
const arguments = (<CallExpression>superCall.expression).arguments;
|
||||||
|
|
|
@ -1,47 +1,88 @@
|
||||||
/* @internal */
|
/* @internal */
|
||||||
namespace ts.codefix {
|
namespace ts.codefix {
|
||||||
|
|
||||||
|
export function newNodesToChanges(newNodes: Node[], insertAfter: Node, context: CodeFixContext) {
|
||||||
|
const sourceFile = context.sourceFile;
|
||||||
|
|
||||||
|
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||||
|
|
||||||
|
for (const newNode of newNodes) {
|
||||||
|
changeTracker.insertNodeAfter(sourceFile, insertAfter, newNode, { suffix: context.newLineCharacter });
|
||||||
|
}
|
||||||
|
|
||||||
|
const changes = changeTracker.getChanges();
|
||||||
|
if (!some(changes)) {
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.assert(changes.length === 1);
|
||||||
|
const consolidatedChanges: FileTextChanges[] = [{
|
||||||
|
fileName: changes[0].fileName,
|
||||||
|
textChanges: [{
|
||||||
|
span: changes[0].textChanges[0].span,
|
||||||
|
newText: changes[0].textChanges.reduce((prev, cur) => prev + cur.newText, "")
|
||||||
|
}]
|
||||||
|
|
||||||
|
}];
|
||||||
|
return consolidatedChanges;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds members of the resolved type that are missing in the class pointed to by class decl
|
* Finds members of the resolved type that are missing in the class pointed to by class decl
|
||||||
* and generates source code for the missing members.
|
* and generates source code for the missing members.
|
||||||
* @param possiblyMissingSymbols The collection of symbols to filter and then get insertions for.
|
* @param possiblyMissingSymbols The collection of symbols to filter and then get insertions for.
|
||||||
* @returns Empty string iff there are no member insertions.
|
* @returns Empty string iff there are no member insertions.
|
||||||
*/
|
*/
|
||||||
export function getMissingMembersInsertion(classDeclaration: ClassLikeDeclaration, possiblyMissingSymbols: Symbol[], checker: TypeChecker, newlineChar: string): string {
|
export function createMissingMemberNodes(classDeclaration: ClassLikeDeclaration, possiblyMissingSymbols: Symbol[], checker: TypeChecker): Node[] {
|
||||||
const classMembers = classDeclaration.symbol.members;
|
const classMembers = classDeclaration.symbol.members;
|
||||||
const missingMembers = possiblyMissingSymbols.filter(symbol => !classMembers.has(symbol.getName()));
|
const missingMembers = possiblyMissingSymbols.filter(symbol => !classMembers.has(symbol.getName()));
|
||||||
|
|
||||||
let insertion = "";
|
let newNodes: Node[] = [];
|
||||||
|
|
||||||
for (const symbol of missingMembers) {
|
for (const symbol of missingMembers) {
|
||||||
insertion = insertion.concat(getInsertionForMemberSymbol(symbol, classDeclaration, checker, newlineChar));
|
const newNode = createNewNodeForMemberSymbol(symbol, classDeclaration, checker);
|
||||||
|
if (newNode) {
|
||||||
|
if (Array.isArray(newNode)) {
|
||||||
|
newNodes = newNodes.concat(newNode);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newNodes.push(newNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return insertion;
|
return newNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns Empty string iff there we can't figure out a representation for `symbol` in `enclosingDeclaration`.
|
* @returns Empty string iff there we can't figure out a representation for `symbol` in `enclosingDeclaration`.
|
||||||
*/
|
*/
|
||||||
function getInsertionForMemberSymbol(symbol: Symbol, enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker, newlineChar: string): string {
|
function createNewNodeForMemberSymbol(symbol: Symbol, enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker): Node[] | Node | undefined {
|
||||||
const declarations = symbol.getDeclarations();
|
const declarations = symbol.getDeclarations();
|
||||||
if (!(declarations && declarations.length)) {
|
if (!(declarations && declarations.length)) {
|
||||||
return "";
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const declaration = declarations[0] as Declaration;
|
const declaration = declarations[0] as Declaration;
|
||||||
const name = declaration.name ? declaration.name.getText() : undefined;
|
// Clone name to remove leading trivia.
|
||||||
const visibility = getVisibilityPrefixWithSpace(getModifierFlags(declaration));
|
const name = getSynthesizedClone(<PropertyName>declaration.name);
|
||||||
|
const visibilityModifier = createVisibilityModifier(getModifierFlags(declaration));
|
||||||
const type = checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration);
|
const modifiers = visibilityModifier ? createNodeArray([visibilityModifier]) : undefined;
|
||||||
|
const type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration));
|
||||||
|
const optional = !!(symbol.flags & SymbolFlags.Optional);
|
||||||
|
|
||||||
switch (declaration.kind) {
|
switch (declaration.kind) {
|
||||||
case SyntaxKind.GetAccessor:
|
case SyntaxKind.GetAccessor:
|
||||||
case SyntaxKind.SetAccessor:
|
case SyntaxKind.SetAccessor:
|
||||||
case SyntaxKind.PropertySignature:
|
case SyntaxKind.PropertySignature:
|
||||||
case SyntaxKind.PropertyDeclaration:
|
case SyntaxKind.PropertyDeclaration:
|
||||||
const typeString = checker.typeToString(type, enclosingDeclaration, TypeFormatFlags.None);
|
const typeNode = checker.typeToTypeNode(type, enclosingDeclaration);
|
||||||
return `${visibility}${name}: ${typeString};${newlineChar}`;
|
const property = createProperty(
|
||||||
|
/*decorators*/undefined,
|
||||||
|
modifiers,
|
||||||
|
name,
|
||||||
|
optional ? createToken(SyntaxKind.QuestionToken) : undefined,
|
||||||
|
typeNode,
|
||||||
|
/*initializer*/ undefined);
|
||||||
|
return property;
|
||||||
case SyntaxKind.MethodSignature:
|
case SyntaxKind.MethodSignature:
|
||||||
case SyntaxKind.MethodDeclaration:
|
case SyntaxKind.MethodDeclaration:
|
||||||
// The signature for the implementation appears as an entry in `signatures` iff
|
// The signature for the implementation appears as an entry in `signatures` iff
|
||||||
|
@ -52,109 +93,142 @@ namespace ts.codefix {
|
||||||
// (eg: an abstract method or interface declaration), there is a 1-1
|
// (eg: an abstract method or interface declaration), there is a 1-1
|
||||||
// correspondence of declarations and signatures.
|
// correspondence of declarations and signatures.
|
||||||
const signatures = checker.getSignaturesOfType(type, SignatureKind.Call);
|
const signatures = checker.getSignaturesOfType(type, SignatureKind.Call);
|
||||||
if (!(signatures && signatures.length > 0)) {
|
if (!some(signatures)) {
|
||||||
return "";
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declarations.length === 1) {
|
if (declarations.length === 1) {
|
||||||
Debug.assert(signatures.length === 1);
|
Debug.assert(signatures.length === 1);
|
||||||
const sigString = checker.signatureToString(signatures[0], enclosingDeclaration, TypeFormatFlags.SuppressAnyReturnType, SignatureKind.Call);
|
const signature = signatures[0];
|
||||||
return getStubbedMethod(visibility, name, sigString, newlineChar);
|
return signatureToMethodDeclaration(signature, enclosingDeclaration, createStubbedMethodBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = "";
|
const signatureDeclarations: MethodDeclaration[] = [];
|
||||||
for (let i = 0; i < signatures.length; i++) {
|
for (let i = 0; i < signatures.length; i++) {
|
||||||
const sigString = checker.signatureToString(signatures[i], enclosingDeclaration, TypeFormatFlags.SuppressAnyReturnType, SignatureKind.Call);
|
const signature = signatures[i];
|
||||||
result += `${visibility}${name}${sigString};${newlineChar}`;
|
const methodDeclaration = signatureToMethodDeclaration(signature, enclosingDeclaration);
|
||||||
|
if (methodDeclaration) {
|
||||||
|
signatureDeclarations.push(methodDeclaration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a declaration with a body, it is the last declaration,
|
|
||||||
// and it isn't caught by `getSignaturesOfType`.
|
|
||||||
let bodySig: Signature | undefined = undefined;
|
|
||||||
if (declarations.length > signatures.length) {
|
if (declarations.length > signatures.length) {
|
||||||
bodySig = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration);
|
const signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration);
|
||||||
|
const methodDeclaration = signatureToMethodDeclaration(signature, enclosingDeclaration, createStubbedMethodBody());
|
||||||
|
if (methodDeclaration) {
|
||||||
|
signatureDeclarations.push(methodDeclaration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Debug.assert(declarations.length === signatures.length);
|
Debug.assert(declarations.length === signatures.length);
|
||||||
bodySig = createBodySignatureWithAnyTypes(signatures, enclosingDeclaration, checker);
|
const methodImplementingSignatures = createMethodImplementingSignatures(signatures, name, optional, modifiers);
|
||||||
|
signatureDeclarations.push(methodImplementingSignatures);
|
||||||
}
|
}
|
||||||
const sigString = checker.signatureToString(bodySig, enclosingDeclaration, TypeFormatFlags.SuppressAnyReturnType, SignatureKind.Call);
|
return signatureDeclarations;
|
||||||
result += getStubbedMethod(visibility, name, sigString, newlineChar);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
default:
|
default:
|
||||||
return "";
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function signatureToMethodDeclaration(signature: Signature, enclosingDeclaration: Node, body?: Block) {
|
||||||
|
const signatureDeclaration = <MethodDeclaration>checker.signatureToSignatureDeclaration(signature, SyntaxKind.MethodDeclaration, enclosingDeclaration);
|
||||||
|
if (signatureDeclaration) {
|
||||||
|
signatureDeclaration.decorators = undefined;
|
||||||
|
signatureDeclaration.modifiers = modifiers;
|
||||||
|
signatureDeclaration.name = name;
|
||||||
|
signatureDeclaration.questionToken = optional ? createToken(SyntaxKind.QuestionToken) : undefined;
|
||||||
|
signatureDeclaration.body = body;
|
||||||
|
}
|
||||||
|
return signatureDeclaration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBodySignatureWithAnyTypes(signatures: Signature[], enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker): Signature {
|
function createMethodImplementingSignatures(signatures: Signature[], name: PropertyName, optional: boolean, modifiers: Modifier[] | undefined): MethodDeclaration {
|
||||||
const newSignatureDeclaration = createNode(SyntaxKind.CallSignature) as SignatureDeclaration;
|
/** This is *a* signature with the maximal number of arguments,
|
||||||
newSignatureDeclaration.parent = enclosingDeclaration;
|
* such that if there is a "maximal" signature without rest arguments,
|
||||||
newSignatureDeclaration.name = signatures[0].getDeclaration().name;
|
* this is one of them.
|
||||||
|
*/
|
||||||
let maxNonRestArgs = -1;
|
let maxArgsSignature = signatures[0];
|
||||||
let maxArgsIndex = 0;
|
|
||||||
let minArgumentCount = signatures[0].minArgumentCount;
|
let minArgumentCount = signatures[0].minArgumentCount;
|
||||||
let hasRestParameter = false;
|
let someSigHasRestParameter = false;
|
||||||
for (let i = 0; i < signatures.length; i++) {
|
for (let i = 0; i < signatures.length; i++) {
|
||||||
const sig = signatures[i];
|
const sig = signatures[i];
|
||||||
minArgumentCount = Math.min(sig.minArgumentCount, minArgumentCount);
|
minArgumentCount = Math.min(sig.minArgumentCount, minArgumentCount);
|
||||||
hasRestParameter = hasRestParameter || sig.hasRestParameter;
|
if (sig.hasRestParameter) {
|
||||||
const nonRestLength = sig.parameters.length - (sig.hasRestParameter ? 1 : 0);
|
someSigHasRestParameter = true;
|
||||||
if (nonRestLength > maxNonRestArgs) {
|
}
|
||||||
maxNonRestArgs = nonRestLength;
|
if (sig.parameters.length >= maxArgsSignature.parameters.length && (!sig.hasRestParameter || maxArgsSignature.hasRestParameter)) {
|
||||||
maxArgsIndex = i;
|
maxArgsSignature = sig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const maxArgsParameterSymbolNames = signatures[maxArgsIndex].getParameters().map(symbol => symbol.getName());
|
const maxNonRestArgs = maxArgsSignature.parameters.length - (maxArgsSignature.hasRestParameter ? 1 : 0);
|
||||||
|
const maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(symbol => symbol.getName());
|
||||||
|
|
||||||
const optionalToken = createToken(SyntaxKind.QuestionToken);
|
const parameters: ParameterDeclaration[] = [];
|
||||||
|
|
||||||
newSignatureDeclaration.parameters = createNodeArray<ParameterDeclaration>();
|
|
||||||
for (let i = 0; i < maxNonRestArgs; i++) {
|
for (let i = 0; i < maxNonRestArgs; i++) {
|
||||||
const newParameter = createParameterDeclarationWithoutType(i, minArgumentCount, newSignatureDeclaration);
|
const anyType = createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||||
newSignatureDeclaration.parameters.push(newParameter);
|
const newParameter = createParameter(
|
||||||
|
/*decorators*/ undefined,
|
||||||
|
/*modifiers*/ undefined,
|
||||||
|
/*dotDotDotToken*/ undefined,
|
||||||
|
maxArgsParameterSymbolNames[i],
|
||||||
|
/*questionToken*/ i >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined,
|
||||||
|
anyType,
|
||||||
|
/*initializer*/ undefined);
|
||||||
|
parameters.push(newParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasRestParameter) {
|
if (someSigHasRestParameter) {
|
||||||
const restParameter = createParameterDeclarationWithoutType(maxNonRestArgs, minArgumentCount, newSignatureDeclaration);
|
const anyArrayType = createArrayTypeNode(createKeywordTypeNode(SyntaxKind.AnyKeyword));
|
||||||
restParameter.dotDotDotToken = createToken(SyntaxKind.DotDotDotToken);
|
const restParameter = createParameter(
|
||||||
newSignatureDeclaration.parameters.push(restParameter);
|
/*decorators*/ undefined,
|
||||||
|
/*modifiers*/ undefined,
|
||||||
|
createToken(SyntaxKind.DotDotDotToken),
|
||||||
|
maxArgsParameterSymbolNames[maxNonRestArgs] || "rest",
|
||||||
|
/*questionToken*/ maxNonRestArgs >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined,
|
||||||
|
anyArrayType,
|
||||||
|
/*initializer*/ undefined);
|
||||||
|
parameters.push(restParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
return checker.getSignatureFromDeclaration(newSignatureDeclaration);
|
return createStubbedMethod(
|
||||||
|
modifiers,
|
||||||
function createParameterDeclarationWithoutType(index: number, minArgCount: number, enclosingSignatureDeclaration: SignatureDeclaration): ParameterDeclaration {
|
name,
|
||||||
const newParameter = createNode(SyntaxKind.Parameter) as ParameterDeclaration;
|
optional,
|
||||||
|
/*typeParameters*/undefined,
|
||||||
newParameter.symbol = new SymbolConstructor(SymbolFlags.FunctionScopedVariable, maxArgsParameterSymbolNames[index] || "rest");
|
parameters,
|
||||||
newParameter.symbol.valueDeclaration = newParameter;
|
/*returnType*/ undefined);
|
||||||
newParameter.symbol.declarations = [newParameter];
|
|
||||||
newParameter.parent = enclosingSignatureDeclaration;
|
|
||||||
if (index >= minArgCount) {
|
|
||||||
newParameter.questionToken = optionalToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newParameter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getStubbedMethod(visibility: string, name: string, sigString = "()", newlineChar: string): string {
|
export function createStubbedMethod(modifiers: Modifier[], name: PropertyName, optional: boolean, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], returnType: TypeNode | undefined) {
|
||||||
return `${visibility}${name}${sigString}${getMethodBodyStub(newlineChar)}`;
|
return createMethodDeclaration(
|
||||||
|
/*decorators*/ undefined,
|
||||||
|
modifiers,
|
||||||
|
/*asteriskToken*/ undefined,
|
||||||
|
name,
|
||||||
|
optional ? createToken(SyntaxKind.QuestionToken) : undefined,
|
||||||
|
typeParameters,
|
||||||
|
parameters,
|
||||||
|
returnType,
|
||||||
|
createStubbedMethodBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMethodBodyStub(newlineChar: string) {
|
function createStubbedMethodBody() {
|
||||||
return ` {${newlineChar}throw new Error('Method not implemented.');${newlineChar}}${newlineChar}`;
|
return createBlock(
|
||||||
|
[createThrow(
|
||||||
|
createNew(
|
||||||
|
createIdentifier("Error"),
|
||||||
|
/*typeArguments*/undefined,
|
||||||
|
[createLiteral("Method not implemented.")]))],
|
||||||
|
/*multiline*/true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVisibilityPrefixWithSpace(flags: ModifierFlags): string {
|
function createVisibilityModifier(flags: ModifierFlags) {
|
||||||
if (flags & ModifierFlags.Public) {
|
if (flags & ModifierFlags.Public) {
|
||||||
return "public ";
|
return createToken(SyntaxKind.PublicKeyword);
|
||||||
}
|
}
|
||||||
else if (flags & ModifierFlags.Protected) {
|
else if (flags & ModifierFlags.Protected) {
|
||||||
return "protected ";
|
return createToken(SyntaxKind.ProtectedKeyword);
|
||||||
}
|
}
|
||||||
return "";
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SymbolConstructor = objectAllocator.getSymbolConstructor();
|
|
||||||
}
|
}
|
|
@ -274,9 +274,9 @@ namespace ts.textChanges {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function should be used to insert nodes in lists when nodes don't carry separators as the part of the node range,
|
* This function should be used to insert nodes in lists when nodes don't carry separators as the part of the node range,
|
||||||
* i.e. arguments in arguments lists, parameters in parameter lists etc. Statements or class elements are different in sense that
|
* i.e. arguments in arguments lists, parameters in parameter lists etc.
|
||||||
* for them separators are treated as the part of the node.
|
* Note that separators are part of the node in statements and class elements.
|
||||||
*/
|
*/
|
||||||
public insertNodeInListAfter(sourceFile: SourceFile, after: Node, newNode: Node) {
|
public insertNodeInListAfter(sourceFile: SourceFile, after: Node, newNode: Node) {
|
||||||
const containingList = formatting.SmartIndenter.getContainingList(after, sourceFile);
|
const containingList = formatting.SmartIndenter.getContainingList(after, sourceFile);
|
||||||
|
@ -484,7 +484,7 @@ namespace ts.textChanges {
|
||||||
private static normalize(changes: Change[]) {
|
private static normalize(changes: Change[]) {
|
||||||
// order changes by start position
|
// order changes by start position
|
||||||
const normalized = stableSort(changes, (a, b) => a.range.pos - b.range.pos);
|
const normalized = stableSort(changes, (a, b) => a.range.pos - b.range.pos);
|
||||||
// verify that end position of the change is less than start position of the next change
|
// verify that change intervals do not overlap, except possibly at end points.
|
||||||
for (let i = 0; i < normalized.length - 2; i++) {
|
for (let i = 0; i < normalized.length - 2; i++) {
|
||||||
Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos);
|
Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos);
|
||||||
}
|
}
|
||||||
|
@ -549,7 +549,7 @@ namespace ts.textChanges {
|
||||||
};
|
};
|
||||||
|
|
||||||
function assignPositionsToNode(node: Node): Node {
|
function assignPositionsToNode(node: Node): Node {
|
||||||
const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray);
|
const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode);
|
||||||
// create proxy node for non synthesized nodes
|
// create proxy node for non synthesized nodes
|
||||||
const newNode = nodeIsSynthesized(visited)
|
const newNode = nodeIsSynthesized(visited)
|
||||||
? visited
|
? visited
|
||||||
|
|
|
@ -1384,4 +1384,8 @@ namespace ts {
|
||||||
// First token is the open curly, this is where we want to put the 'super' call.
|
// First token is the open curly, this is where we want to put the 'super' call.
|
||||||
return constructor.body.getFirstToken(sourceFile);
|
return constructor.body.getFirstToken(sourceFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getOpenBraceOfClassLike(declaration: ClassLikeDeclaration, sourceFile: SourceFile) {
|
||||||
|
return getTokenAtPosition(sourceFile, declaration.members.pos - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,6 @@
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
f(): void{
|
f(): void{
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -28,4 +28,4 @@ verify.rangeAfterCodeFix(`
|
||||||
e: this;
|
e: this;
|
||||||
f: A;
|
f: A;
|
||||||
g: string;
|
g: string;
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
//// abstract f(a: number, b: string): this;
|
//// abstract f(a: number, b: string): this;
|
||||||
//// abstract f(a: string, b: number): Function;
|
//// abstract f(a: string, b: number): Function;
|
||||||
//// abstract f(a: string): Function;
|
//// abstract f(a: string): Function;
|
||||||
|
//// abstract foo(): number;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C extends A {[| |]}
|
//// class C extends A {[| |]}
|
||||||
|
@ -15,6 +16,9 @@ verify.rangeAfterCodeFix(`
|
||||||
f(a: string, b: number): Function;
|
f(a: string, b: number): Function;
|
||||||
f(a: string): Function;
|
f(a: string): Function;
|
||||||
f(a: any, b?: any) {
|
f(a: any, b?: any) {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
foo(): number {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -8,6 +8,6 @@
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
f(): this {
|
f(): this {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -4,10 +4,9 @@
|
||||||
//// abstract f(x: T): T;
|
//// abstract f(x: T): T;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C extends A<number> {[|
|
//// class C extends A<number> {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`f(x: number): number{
|
verify.rangeAfterCodeFix(`f(x: number): number{
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
|
@ -4,10 +4,9 @@
|
||||||
//// abstract f(x: T): T;
|
//// abstract f(x: T): T;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C<U> extends A<U> {[|
|
//// class C<U> extends A<U> {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`f(x: U): U{
|
verify.rangeAfterCodeFix(`f(x: U): U{
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
|
@ -4,8 +4,7 @@
|
||||||
//// private abstract x: number;
|
//// private abstract x: number;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C extends A {[|
|
//// class C extends A {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
// We don't know how to fix this problem. We can:
|
// We don't know how to fix this problem. We can:
|
||||||
// 1) Make x protected, and then insert.
|
// 1) Make x protected, and then insert.
|
||||||
|
|
|
@ -4,17 +4,12 @@
|
||||||
//// abstract x: number;
|
//// abstract x: number;
|
||||||
//// abstract y: this;
|
//// abstract y: this;
|
||||||
//// abstract z: A;
|
//// abstract z: A;
|
||||||
//// abstract foo(): number;
|
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C extends A {[|
|
//// class C extends A {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
x: number;
|
x: number;
|
||||||
y: this;
|
y: this;
|
||||||
z: A;
|
z: A;
|
||||||
foo(): number {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
//// protected abstract x: number;
|
//// protected abstract x: number;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C extends A {[|
|
//// class C extends A {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
protected x: number;
|
protected x: number;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
//// public abstract x: number;
|
//// public abstract x: number;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C extends A {[|
|
//// class C extends A {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
public x: number;
|
public x: number;
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
//// abstract z: number;
|
//// abstract z: number;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C extends A {[| |]
|
//// class C extends A {[|
|
||||||
//// constructor(public x: number) { super(); }
|
//// |]constructor(public x: number) { super(); }
|
||||||
//// y: number;
|
//// y: number;
|
||||||
//// }
|
//// }
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,6 @@
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
f(): void{
|
f(): void{
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// class A {
|
||||||
|
//// foo() {
|
||||||
|
//// return class { x: number; }
|
||||||
|
//// }
|
||||||
|
//// bar() {
|
||||||
|
//// return new class { x: number; }
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// class C implements A {[| |]}
|
||||||
|
|
||||||
|
verify.not.codeFixAvailable();
|
|
@ -8,11 +8,11 @@
|
||||||
////
|
////
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C3 implements C2 {[|
|
//// class C3 implements C2 {[|
|
||||||
//// |]f2(){}
|
//// |]f2(){}
|
||||||
//// }
|
//// }
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`f1(): void{
|
verify.rangeAfterCodeFix(`f1(): void{
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
method(a: number, b: string): boolean;
|
method(a: number, b: string): boolean;
|
||||||
method(a: string | number, b?: string | number): boolean | Function {
|
method(a: string | number, b?: string | number): boolean | Function {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -13,6 +13,6 @@ verify.rangeAfterCodeFix(`
|
||||||
method(a: string, b: number): Function;
|
method(a: string, b: number): Function;
|
||||||
method(a: string): Function;
|
method(a: string): Function;
|
||||||
method(a: string | number, b?: string | number): boolean | Function {
|
method(a: string | number, b?: string | number): boolean | Function {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// class A {
|
||||||
|
//// A: typeof A;
|
||||||
|
//// }
|
||||||
|
//// class D implements A {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
A: typeof A;
|
||||||
|
`);
|
|
@ -24,8 +24,7 @@
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// interface I6 extends C4 {}
|
//// interface I6 extends C4 {}
|
||||||
//// class C5 implements I6 {[|
|
//// class C5 implements I6 {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
/// <reference path='fourslash.ts' />
|
|
||||||
|
|
||||||
//// abstract class C1 {
|
|
||||||
////
|
|
||||||
//// }
|
|
||||||
////
|
|
||||||
//// abstract class C2 {
|
|
||||||
//// abstract f1<T extends number>();
|
|
||||||
//// }
|
|
||||||
////
|
|
||||||
//// interface I1 extends C1, C2 {}
|
|
||||||
////
|
|
||||||
//// class C3 implements I1 {[|
|
|
||||||
////
|
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`f1<T extends number>(){
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
`);
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// interface I {
|
||||||
|
//// x: number[];
|
||||||
|
//// y: Array<number>;
|
||||||
|
//// z: [number, string, I];
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// class C implements I {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
x: number[];
|
||||||
|
y: number[];
|
||||||
|
z: [number, string, I];
|
||||||
|
`);
|
|
@ -0,0 +1,10 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// interface I {
|
||||||
|
//// (x: number, b: string): number;
|
||||||
|
//// }
|
||||||
|
//// class C implements I {[| |]}
|
||||||
|
|
||||||
|
verify.not.codeFixAvailable();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
// @lib: es2017
|
||||||
|
|
||||||
|
//// namespace N {
|
||||||
|
//// /**enum prefix */
|
||||||
|
//// export enum /**enum identifier prefix */ E /**open-brace prefix*/ {
|
||||||
|
//// /* literal prefix */ a /** comma prefix */,
|
||||||
|
//// /* literal prefix */ b /** comma prefix */,
|
||||||
|
//// /* literal prefix */ c
|
||||||
|
//// /** close brace prefix */ }
|
||||||
|
//// /** interface prefix */
|
||||||
|
//// export interface /**interface name prefix */ I /**open-brace prefix*/ {
|
||||||
|
//// /** property prefix */ a /** colon prefix */: /** enum literal prefix 1*/ E /** dot prefix */. /** enum literal prefix 2*/a;
|
||||||
|
//// /** property prefix */ b /** colon prefix */: /** enum prefix */ E;
|
||||||
|
//// /**method signature prefix */foo /**open angle prefix */< /**type parameter name prefix */ X /** closing angle prefix */> /**open paren prefix */(/** parameter prefix */ a/** colon prefix */: /** parameter type prefix */ X /** close paren prefix */) /** colon prefix */: /** return type prefix */ string /** semicolon prefix */;
|
||||||
|
//// /**close-brace prefix*/ }
|
||||||
|
//// /**close-brace prefix*/ }
|
||||||
|
//// class C implements N.I {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
a: N.E.a;
|
||||||
|
b: N.E;
|
||||||
|
foo<X>(a: X): string {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
`);
|
|
@ -7,15 +7,15 @@
|
||||||
//// [2]: boolean;
|
//// [2]: boolean;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C implements I {[| |]}
|
//// class C implements I {[| |]}
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
["foo"](o: any): boolean {
|
["foo"](o: any): boolean {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
["x"]: boolean;
|
["x"]: boolean;
|
||||||
[1](): string {
|
[1](): string {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
[2]: boolean;
|
[2]: boolean;
|
||||||
`);
|
`);
|
|
@ -17,35 +17,34 @@
|
||||||
//// [Symbol.toStringTag]: string;
|
//// [Symbol.toStringTag]: string;
|
||||||
//// [Symbol.unscopables]: any;
|
//// [Symbol.unscopables]: any;
|
||||||
//// }
|
//// }
|
||||||
////
|
|
||||||
//// class C implements I<number> {[| |]}
|
//// class C implements I<number> {[| |]}
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
[Symbol.hasInstance](o: any): boolean {
|
[Symbol.hasInstance](o: any): boolean {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
[Symbol.isConcatSpreadable]: boolean;
|
[Symbol.isConcatSpreadable]: boolean;
|
||||||
[Symbol.iterator]() {
|
[Symbol.iterator]() {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
[Symbol.match]: boolean;
|
[Symbol.match]: boolean;
|
||||||
[Symbol.replace](...args: {}) {
|
[Symbol.replace](...args: {}) {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
[Symbol.search](str: string): number {
|
[Symbol.search](str: string): number {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
[Symbol.species](): number {
|
[Symbol.species](): number {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
[Symbol.split](str: string, limit?: number): {} {
|
[Symbol.split](str: string, limit?: number): {} {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
[Symbol.toPrimitive](hint: "number"): number;
|
[Symbol.toPrimitive](hint: "number"): number;
|
||||||
[Symbol.toPrimitive](hint: "default"): number;
|
[Symbol.toPrimitive](hint: "default"): number;
|
||||||
[Symbol.toPrimitive](hint: "string"): string;
|
[Symbol.toPrimitive](hint: "string"): string;
|
||||||
[Symbol.toPrimitive](hint: any) {
|
[Symbol.toPrimitive](hint: any) {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
[Symbol.toStringTag]: string;
|
[Symbol.toStringTag]: string;
|
||||||
[Symbol.unscopables]: any;
|
[Symbol.unscopables]: any;
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// interface I {
|
||||||
|
//// new (x: number, b: string);
|
||||||
|
//// }
|
||||||
|
//// class C implements I {[| |]}
|
||||||
|
|
||||||
|
verify.not.codeFixAvailable();
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
//// x: number;
|
//// x: number;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C implements I1,I2 {[|
|
//// class C implements I1,I2 {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.codeFixAvailable();
|
verify.codeFixAvailable();
|
|
@ -0,0 +1,13 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// interface I {
|
||||||
|
//// x: {};
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// class C implements I {[|
|
||||||
|
//// |]constructor() { }
|
||||||
|
//// }
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
x: {};
|
||||||
|
`);
|
|
@ -9,10 +9,9 @@
|
||||||
//// f1();
|
//// f1();
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C1 implements N1.I1 {[|
|
//// class C1 implements N1.I1 {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`f1(): string{
|
verify.rangeAfterCodeFix(`f1(): string{
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
|
@ -3,9 +3,7 @@
|
||||||
//// interface I {
|
//// interface I {
|
||||||
//// [x: number]: I;
|
//// [x: number]: I;
|
||||||
//// }
|
//// }
|
||||||
////
|
//// class C implements I {[| |]}
|
||||||
//// class C implements I {[|
|
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
[x: number]: I;
|
[x: number]: I;
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// interface I<X> {
|
||||||
|
//// x: keyof X;
|
||||||
|
//// }
|
||||||
|
//// class C<Y> implements I<Y> {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
x: keyof Y;
|
||||||
|
`);
|
|
@ -0,0 +1,13 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// abstract class C1 { }
|
||||||
|
//// abstract class C2 {
|
||||||
|
//// abstract f1<T extends number>();
|
||||||
|
//// }
|
||||||
|
//// interface I1 extends C1, C2 { }
|
||||||
|
//// class C3 implements I1 {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`f1<T extends number>(){
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
`);
|
|
@ -0,0 +1,10 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// interface I<X> {
|
||||||
|
//// x: { readonly [K in keyof X]: X[K] };
|
||||||
|
//// }
|
||||||
|
//// class C<Y> implements I<Y> {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
x: { readonly [K in keyof X]: Y[K]; };
|
||||||
|
`);
|
|
@ -0,0 +1,58 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
// @lib: es2017
|
||||||
|
|
||||||
|
//// /** asdf */
|
||||||
|
//// interface I {
|
||||||
|
//// 1;
|
||||||
|
//// 2;
|
||||||
|
//// 3;
|
||||||
|
//// 4;
|
||||||
|
//// 5;
|
||||||
|
//// 6;
|
||||||
|
//// 7;
|
||||||
|
//// 8;
|
||||||
|
//// 9;
|
||||||
|
//// 10;
|
||||||
|
//// 11;
|
||||||
|
//// 12;
|
||||||
|
//// 13;
|
||||||
|
//// 14;
|
||||||
|
//// 15;
|
||||||
|
//// 16;
|
||||||
|
//// 17;
|
||||||
|
//// 18;
|
||||||
|
//// 19;
|
||||||
|
//// 20;
|
||||||
|
//// 21;
|
||||||
|
//// 22;
|
||||||
|
//// /** a nice safe prime */
|
||||||
|
//// 23;
|
||||||
|
//// }
|
||||||
|
//// class C implements I {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
1: any;
|
||||||
|
2: any;
|
||||||
|
3: any;
|
||||||
|
4: any;
|
||||||
|
5: any;
|
||||||
|
6: any;
|
||||||
|
7: any;
|
||||||
|
8: any;
|
||||||
|
9: any;
|
||||||
|
10: any;
|
||||||
|
11: any;
|
||||||
|
12: any;
|
||||||
|
13: any;
|
||||||
|
14: any;
|
||||||
|
15: any;
|
||||||
|
16: any;
|
||||||
|
17: any;
|
||||||
|
18: any;
|
||||||
|
19: any;
|
||||||
|
20: any;
|
||||||
|
21: any;
|
||||||
|
22: any;
|
||||||
|
23: any;
|
||||||
|
`);
|
|
@ -4,11 +4,10 @@
|
||||||
//// f(x: number, y: this): I
|
//// f(x: number, y: this): I
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C implements I {[|
|
//// class C implements I {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
f(x: number,y: this): I {
|
f(x: number,y: this): I {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// interface I {
|
||||||
|
//// f(i: any): i is I;
|
||||||
|
//// f(): this is I;
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// class C implements I {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
f(i: any): i is I;
|
||||||
|
f(): this is I;
|
||||||
|
f(i?: any) {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
`);
|
|
@ -8,12 +8,11 @@
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C implements I1,I2 {[|
|
//// class C implements I1,I2 {[|
|
||||||
//// y: number;
|
//// |]y: number;
|
||||||
//// |]}
|
//// }
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
|
||||||
`);
|
`);
|
||||||
|
|
||||||
verify.not.codeFixAvailable();
|
verify.not.codeFixAvailable();
|
||||||
|
|
|
@ -8,12 +8,11 @@
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C implements I1,I2 {[|
|
//// class C implements I1,I2 {[|
|
||||||
//// x: number;
|
//// |]x: number;
|
||||||
//// |]}
|
//// }
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
y: number;
|
y: number;
|
||||||
x: number;
|
|
||||||
`);
|
`);
|
||||||
|
|
||||||
verify.not.codeFixAvailable();
|
verify.not.codeFixAvailable();
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
//// x: string;
|
//// x: string;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C implements I1,I2 {[|
|
//// class C implements I1,I2 {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.codeFixAvailable();
|
verify.codeFixAvailable();
|
|
@ -9,20 +9,19 @@
|
||||||
//// h();
|
//// h();
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C1 implements I1 {[|
|
//// class C1 implements I1 {[| |]}
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
z: number;
|
z: number;
|
||||||
f() {
|
f() {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
g() {
|
g() {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
h() {
|
h() {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
|
@ -13,6 +13,6 @@ verify.rangeAfterCodeFix(`
|
||||||
method(a: string, b: number): Function;
|
method(a: string, b: number): Function;
|
||||||
method(a: string): Function;
|
method(a: string): Function;
|
||||||
method(a: any, b?: any) {
|
method(a: any, b?: any) {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -13,6 +13,6 @@ verify.rangeAfterCodeFix(`
|
||||||
method(a: string, ...b: number[]): Function;
|
method(a: string, ...b: number[]): Function;
|
||||||
method(a: string): Function;
|
method(a: string): Function;
|
||||||
method(a: any, ...b?: any[]) {
|
method(a: any, ...b?: any[]) {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -13,6 +13,6 @@ verify.rangeAfterCodeFix(`
|
||||||
method(a: string, b: number): Function;
|
method(a: string, b: number): Function;
|
||||||
method(a: string): Function;
|
method(a: string): Function;
|
||||||
method(a: any, b?: any, ...rest?: any[]) {
|
method(a: any, b?: any, ...rest?: any[]) {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -8,9 +8,7 @@
|
||||||
//// interface I1 {
|
//// interface I1 {
|
||||||
//// f1();
|
//// f1();
|
||||||
//// }
|
//// }
|
||||||
////
|
//// class C1 implements N1.I1 {[| |]}
|
||||||
//// class C1 implements N1.I1 {[|
|
|
||||||
//// |]}
|
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
x: number;
|
x: number;
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
// @lib: es2017
|
||||||
|
|
||||||
|
//// enum E { a,b,c }
|
||||||
|
//// interface I {
|
||||||
|
//// x: E;
|
||||||
|
//// y: E.a
|
||||||
|
//// z: symbol;
|
||||||
|
//// w: object;
|
||||||
|
//// }
|
||||||
|
//// class C implements I {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
x: E;
|
||||||
|
y: E.a;
|
||||||
|
z: symbol;
|
||||||
|
w: object;
|
||||||
|
`);
|
|
@ -4,7 +4,7 @@
|
||||||
//// constructor(public x: number) { }
|
//// constructor(public x: number) { }
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class B implements A {[| |]}
|
//// class B implements A {[| |]}
|
||||||
|
|
||||||
verify.not.codeFixAvailable();
|
verify.not.codeFixAvailable();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// interface I {
|
||||||
|
//// a0: {};
|
||||||
|
//// a1: { (b1: number, c1: string): number; };
|
||||||
|
//// a2: (b2: number, c2: string) => number;
|
||||||
|
//// a3: { (b3: number, c3: string): number, x: number };
|
||||||
|
////
|
||||||
|
//// a4: { new (b1: number, c1: string): number; };
|
||||||
|
//// a5: new (b2: number, c2: string) => number;
|
||||||
|
//// a6: { new (b3: number, c3: string): number, x: number };
|
||||||
|
////
|
||||||
|
//// a7: { foo(b7: number, c7: string): number };
|
||||||
|
////
|
||||||
|
//// a8: { (b81: number, c81: string): number, new (b82: number, c82: string): number; };
|
||||||
|
////
|
||||||
|
//// a9: { (b9: number, c9: string): number; [d9: number]: I };
|
||||||
|
//// a10: { (b10: number, c10: string): number; [d10: string]: I };
|
||||||
|
//// }
|
||||||
|
//// class C implements I {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
a0: {};
|
||||||
|
a1: (b1: number, c1: string) => number;
|
||||||
|
a2: (b2: number, c2: string) => number;
|
||||||
|
a3: { (b3: number, c3: string): number; x: number; };
|
||||||
|
a4: new (b1: number, c1: string) => number;
|
||||||
|
a5: new (b2: number, c2: string) => number;
|
||||||
|
a6: { new (b3: number, c3: string): number; x: number; };
|
||||||
|
a7: { foo(b7: number, c7: string): number; };
|
||||||
|
a8: { (b81: number, c81: string): number; new (b82: number, c82: string): number; };
|
||||||
|
a9: { (b9: number, c9: string): number; [d9: number]: I; };
|
||||||
|
a10: { (b10: number, c10: string): number; [d10: string]: I; };
|
||||||
|
`);
|
|
@ -0,0 +1,12 @@
|
||||||
|
/// <reference path='fourslash.ts' />
|
||||||
|
|
||||||
|
//// namespace N {
|
||||||
|
//// export interface I {
|
||||||
|
//// y: I;
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// class C1 implements N.I {[| |]}
|
||||||
|
|
||||||
|
verify.rangeAfterCodeFix(`
|
||||||
|
y: N.I;
|
||||||
|
`);
|
|
@ -6,8 +6,8 @@
|
||||||
//// z: number & { __iBrand: any };
|
//// z: number & { __iBrand: any };
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C implements I {[| |]
|
//// class C implements I {[|
|
||||||
//// constructor(public x: number) { }
|
//// |]constructor(public x: number) { }
|
||||||
//// y: number;
|
//// y: number;
|
||||||
//// }
|
//// }
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//// x: { y: T, z: T[] };
|
//// x: { y: T, z: T[] };
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C implements I<number> {[| |]}
|
//// class C implements I<number> {[| |]}
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
x: { y: number; z: number[]; };
|
x: { y: number; z: number[]; };
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//// x: T;
|
//// x: T;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C implements I<number> {[| |]}
|
//// class C implements I<number> {[| |]}
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
x: number;
|
x: number;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//// x: T;
|
//// x: T;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C<T> implements I<T> {[| |]}
|
//// class C<T> implements I<T> {[| |]}
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
x: T;
|
x: T;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//// x: T;
|
//// x: T;
|
||||||
//// }
|
//// }
|
||||||
////
|
////
|
||||||
//// class C<U> implements I<U> {[| |]}
|
//// class C<U> implements I<U> {[| |]}
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
x: U;
|
x: U;
|
||||||
|
|
|
@ -7,6 +7,6 @@
|
||||||
//// class C implements I {[| |]}
|
//// class C implements I {[| |]}
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`f<T extends number>(x: T){
|
verify.rangeAfterCodeFix(`f<T extends number>(x: T){
|
||||||
throw new Error('Method not implemented.');
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
`);
|
`);
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
verify.rangeAfterCodeFix(`
|
verify.rangeAfterCodeFix(`
|
||||||
class A {
|
class A {
|
||||||
[name: string]: number;
|
[x: string]: number;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.x = 10;
|
this.x = 10;
|
||||||
|
|
Loading…
Reference in a new issue