@@ -2203,25 +2203,23 @@ namespace ts {
2203
2203
return createTypeParameterDeclaration(name, constraint, defaultParameter);
2204
2204
}
2205
2205
2206
- // TODO: enclosing declaration appears to be unused in getTypeOfSymbolAtLocation
2207
2206
function createParameterDeclarationFromSymbol(parameterSymbol: Symbol, enclosingDeclaration: Node): ParameterDeclaration {
2208
2207
const parameterDeclaration = parameterSymbol.declarations[0] as ParameterDeclaration;
2209
2208
const parameterType = getTypeOfSymbol(parameterSymbol);
2210
2209
const parameterTypeNode = createTypeNode(parameterType, enclosingDeclaration);
2211
- // TODO: clone binding names correctly.
2212
- // TODO: copy initialzer in a way that checks whether all symbols used in expression are accessible here, and qualify them appropriately .
2210
+ // TODO: how should we clone members/modifiers?
2211
+ // TODO: check initializer accessibility correctly .
2213
2212
const parameterNode = createParameter(
2214
2213
parameterDeclaration.decorators && parameterDeclaration.decorators.map(getSynthesizedDeepClone)
2215
2214
, parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedDeepClone)
2216
2215
, parameterDeclaration.dotDotDotToken && createToken(SyntaxKind.DotDotDotToken)
2217
2216
, getSynthesizedDeepClone(parameterDeclaration.name)
2218
2217
, parameterDeclaration.questionToken && createToken(SyntaxKind.QuestionToken)
2219
2218
, parameterTypeNode
2220
- , /* initializer*/ undefined );
2219
+ , parameterDeclaration. initializer && getSynthesizedDeepClone(parameterDeclaration.initializer) );
2221
2220
return parameterNode;
2222
2221
}
2223
2222
2224
- // TODO: expose this, remove copy from helper, possibly don't expose createParameter/TypeParameter?
2225
2223
function createSignatureParts(signature: Signature, enclosingDeclaration: Node): SignatureParts {
2226
2224
return {
2227
2225
typeParameters: signature.typeParameters && signature.typeParameters.map(parameter => createTypeParameterDeclarationFromType(parameter,enclosingDeclaration)),
@@ -2242,23 +2240,16 @@ namespace ts {
2242
2240
let checkAlias = true;
2243
2241
let symbolStack: Symbol[] = undefined;
2244
2242
2245
- let result = createTypeNodeWorker(type);
2246
- if (result) {
2247
- (<any>result).__type_source = type;
2248
- (<any>result).__type_source_str = typeToString(type);
2249
- }
2250
- return result;
2243
+ const result = createTypeNodeWorker(type);
2244
+ return encounteredError ? undefined: result;
2251
2245
2252
2246
function createTypeNodeWorker(type: Type): TypeNode {
2253
2247
if (!type) {
2254
2248
if (undefinedArgumentIsError) { encounteredError = true; }
2255
2249
return undefined;
2256
2250
}
2257
2251
2258
- const typeString = typeToString(type, enclosingDeclaration); typeString; // TODO: remove.
2259
-
2260
2252
if (type.flags & TypeFlags.Any) {
2261
- // TODO: add other case where type ends up being `any`.
2262
2253
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
2263
2254
}
2264
2255
if (type.flags & TypeFlags.String) {
@@ -2318,19 +2309,16 @@ namespace ts {
2318
2309
}
2319
2310
if (objectFlags & ObjectFlags.ClassOrInterface) {
2320
2311
Debug.assert(!!(type.flags & TypeFlags.Object));
2321
- // TODO: Detect whether class is named and fail if not.
2322
2312
const name = createNameFromSymbol(type.symbol);
2323
2313
// TODO: handle type arguments.
2324
- return createTypeReferenceNode(name, /*typeParameters*/ undefined);
2314
+ return createTypeReferenceNode(name, /*typeArguments*/ undefined);
2325
2315
}
2326
2316
if (type.flags & TypeFlags.TypeParameter) {
2327
- // TODO: get qualified name when necessary instead of string.
2328
2317
const name = createNameFromSymbol(type.symbol);
2329
2318
// Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter.
2330
2319
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
2331
2320
}
2332
2321
2333
- // TODO: move back up later on?
2334
2322
if (checkAlias && type.aliasSymbol) {
2335
2323
const name = createNameFromSymbol(type.aliasSymbol);
2336
2324
const typeArgumentNodes = mapToTypeNodeArray(type.aliasTypeArguments);
@@ -2352,18 +2340,14 @@ namespace ts {
2352
2340
return createAnonymousTypeNode(<ObjectType>type);
2353
2341
}
2354
2342
2355
- // TODO: implement when this is testable.
2356
- // else if (type.flags & TypeFlags.StringOrNumberLiteral) {
2357
- // writer.writeStringLiteral(literalTypeToString(<LiteralType>type));
2343
+ // TODO (aozgaa): implement string and number literals here once there is a testable case.
2358
2344
2359
2345
if (type.flags & TypeFlags.Index) {
2360
- // TODO: test.
2361
- const indexType = getIndexType(getApparentType((<IndexType>type).type));
2362
- const indexTypeNode = createTypeNodeWorker(indexType);
2346
+ const indexedType = (<IndexType>type).type;
2347
+ const indexTypeNode = createTypeNodeWorker(indexedType);
2363
2348
return createTypeOperatorNode(indexTypeNode);
2364
2349
}
2365
2350
if (type.flags & TypeFlags.IndexedAccess) {
2366
- // TODO: test.
2367
2351
const objectTypeNode = createTypeNodeWorker((<IndexedAccessType>type).objectType);
2368
2352
const indexTypeNode = createTypeNodeWorker((<IndexedAccessType>type).indexType);
2369
2353
return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode);
@@ -2375,27 +2359,15 @@ namespace ts {
2375
2359
return types && asNodeArray(types.map(createTypeNodeWorker) as TypeNode[]);
2376
2360
}
2377
2361
2378
- function createNameFromSymbol(symbol: Symbol): Identifier;
2379
- function createNameFromSymbol(symbol: Symbol): EntityName;
2380
- function createNameFromSymbol(symbol: Symbol): EntityName {
2381
- symbol; enclosingDeclaration;
2382
- // TODO: actually implement this
2383
- return createIdentifier(symbolToString(symbol, enclosingDeclaration));
2384
- }
2385
-
2386
2362
function createMappedTypeNodeFromType(type: MappedType) {
2387
2363
Debug.assert(!!(type.flags & TypeFlags.Object));
2388
-
2389
- // TODO: does typeParameter have the same constraint or do we need to overwrite it somehow?
2390
2364
const typeParameter = getTypeParameterFromMappedType(<MappedType>type);
2391
- // const constraintType = getConstraintTypeFromMappedType(<MappedType>type);
2392
2365
const typeParameterNode = createTypeParameterDeclarationFromType(typeParameter, enclosingDeclaration);
2393
2366
2394
2367
const templateTypeNode = createTypeNode(getTemplateTypeFromMappedType(<MappedType>type), enclosingDeclaration);
2395
2368
const readonlyToken = (<MappedType>type).declaration && (<MappedType>type).declaration.readonlyToken ? createToken(SyntaxKind.ReadonlyKeyword) : undefined;
2396
2369
const questionToken = (<MappedType>type).declaration && (<MappedType>type).declaration.questionToken ? createToken(SyntaxKind.QuestionToken) : undefined;
2397
2370
2398
- // TODO: test.
2399
2371
return createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode);
2400
2372
}
2401
2373
@@ -2501,7 +2473,6 @@ namespace ts {
2501
2473
return createTupleTypeNode(typeArguments.length > 0 ? mapToTypeNodeArray(typeArguments.slice(0, getTypeReferenceArity(type))) : undefined);
2502
2474
}
2503
2475
else {
2504
- // TODO: handle type parameters in qualified names...
2505
2476
const outerTypeParameters = type.target.outerTypeParameters;
2506
2477
let i = 0;
2507
2478
let qualifiedName: QualifiedName | undefined = undefined;
@@ -2516,10 +2487,9 @@ namespace ts {
2516
2487
} while (i < length && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent);
2517
2488
// When type parameters are their own type arguments for the whole group (i.e. we have
2518
2489
// the default outer type arguments), we don't show the group.
2519
- // TODO: figure out how to handle type arguments
2520
2490
if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) {
2521
2491
const name = createNameFromSymbol(parent);
2522
- const qualifiedNamePart = name; // createTypeReferenceNode(name, mapToTypeNodeArray(typeArguments.slice(start, i - start)));
2492
+ const qualifiedNamePart = name;
2523
2493
if (!qualifiedName) {
2524
2494
qualifiedName = createQualifiedName(qualifiedNamePart, /*right*/undefined);
2525
2495
}
@@ -2534,7 +2504,6 @@ namespace ts {
2534
2504
let entityName: EntityName = undefined;
2535
2505
const nameIdentifier = createNameFromSymbol(type.symbol);
2536
2506
if (qualifiedName) {
2537
- // TODO: handle checking of type arguments for qualified names?
2538
2507
Debug.assert(!qualifiedName.right);
2539
2508
qualifiedName.right = nameIdentifier;
2540
2509
entityName = qualifiedName;
@@ -2597,6 +2566,68 @@ namespace ts {
2597
2566
}
2598
2567
return typeElements.length ? typeElements : undefined;
2599
2568
}
2569
+
2570
+ function createNameFromSymbol(symbol: Symbol): Identifier;
2571
+ function createNameFromSymbol(symbol: Symbol): EntityName;
2572
+ function createNameFromSymbol(symbol: Symbol): EntityName {
2573
+ let parentSymbol: Symbol;
2574
+ symbol; enclosingDeclaration;
2575
+ let meaning: SymbolFlags;
2576
+
2577
+ // Get qualified name if the symbol is not a type parameter
2578
+ // and there is an enclosing declaration.
2579
+ let chain: Symbol[];
2580
+ const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter;
2581
+ if (!isTypeParameter && enclosingDeclaration) {
2582
+ chain = getSymbolChain(symbol, meaning, /*endOfChain*/ true);
2583
+ Debug.assert(chain && chain.length > 0);
2584
+ }
2585
+ else {
2586
+ chain = [symbol];
2587
+ }
2588
+
2589
+ const result = createEntityNameFromSymbolChain(chain, chain.length - 1);
2590
+ return result;
2591
+
2592
+ function createEntityNameFromSymbolChain(chain: Symbol[], index: number): EntityName {
2593
+ Debug.assert(chain && 0 <= index && index < chain.length);
2594
+ const identifier = createIdentifier(getNameOfSymbol(chain[index]));
2595
+ return index > 0 ? createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier;
2596
+ }
2597
+
2598
+ /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */
2599
+ function getSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined {
2600
+ let accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, /*useOnlyExternalAliasing*/false);
2601
+
2602
+ if (!accessibleSymbolChain ||
2603
+ needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
2604
+
2605
+ // Go up and add our parent.
2606
+ const parent = getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol);
2607
+ if (parent) {
2608
+ const parentChain = getSymbolChain(parent, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false);
2609
+ if (parentChain) {
2610
+ accessibleSymbolChain = parentChain.concat(accessibleSymbolChain || [symbol]);
2611
+ }
2612
+ }
2613
+ }
2614
+
2615
+ if (accessibleSymbolChain) {
2616
+ return accessibleSymbolChain;
2617
+ }
2618
+
2619
+ else if (
2620
+ // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols.
2621
+ endOfChain ||
2622
+ // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.)
2623
+ !(!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) &&
2624
+ // If a parent symbol is an anonymous type, don't write it.
2625
+ !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral))) {
2626
+
2627
+ return [symbol];
2628
+ }
2629
+ }
2630
+ }
2600
2631
}
2601
2632
}
2602
2633
0 commit comments