@@ -993,7 +993,18 @@ module ts {
993
993
}
994
994
995
995
function emitBindingPattern ( bindingPattern : BindingPattern ) {
996
- emitCommaList ( bindingPattern . elements , emitBindingElement ) ;
996
+ // Only select non-omitted expression from the bindingPattern's elements.
997
+ // We have to do this to avoid emitting trailing commas.
998
+ // For example:
999
+ // original: var [, c,,] = [ 2,3,4]
1000
+ // emitted: declare var c: number; // instead of declare var c:number, ;
1001
+ let elements : Node [ ] = [ ] ;
1002
+ for ( let element of bindingPattern . elements ) {
1003
+ if ( element . kind !== SyntaxKind . OmittedExpression ) {
1004
+ elements . push ( element ) ;
1005
+ }
1006
+ }
1007
+ emitCommaList ( elements , emitBindingElement ) ;
997
1008
}
998
1009
999
1010
function emitBindingElement ( bindingElement : BindingElement ) {
@@ -1291,7 +1302,10 @@ module ts {
1291
1302
write ( "..." ) ;
1292
1303
}
1293
1304
if ( isBindingPattern ( node . name ) ) {
1294
- write ( "_" + indexOf ( ( < FunctionLikeDeclaration > node . parent ) . parameters , node ) ) ;
1305
+ // For bindingPattern, we can't simply writeTextOfNode from the source file
1306
+ // because we want to omit the initializer and using writeTextOfNode will result in initializer get emitted.
1307
+ // Therefore, we will have to recursively emit each element in the bindingPattern.
1308
+ emitBindingPattern ( < BindingPattern > node . name ) ;
1295
1309
}
1296
1310
else {
1297
1311
writeTextOfNode ( currentSourceFile , node . name ) ;
@@ -1311,72 +1325,146 @@ module ts {
1311
1325
}
1312
1326
1313
1327
function getParameterDeclarationTypeVisibilityError ( symbolAccesibilityResult : SymbolAccessiblityResult ) : SymbolAccessibilityDiagnostic {
1314
- let diagnosticMessage : DiagnosticMessage ;
1328
+ let diagnosticMessage : DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage ( symbolAccesibilityResult ) ;
1329
+ return diagnosticMessage !== undefined ? {
1330
+ diagnosticMessage,
1331
+ errorNode : node ,
1332
+ typeName : node . name
1333
+ } : undefined ;
1334
+ }
1335
+
1336
+ function getParameterDeclarationTypeVisibilityDiagnosticMessage ( symbolAccesibilityResult : SymbolAccessiblityResult ) : DiagnosticMessage {
1315
1337
switch ( node . parent . kind ) {
1316
1338
case SyntaxKind . Constructor :
1317
- diagnosticMessage = symbolAccesibilityResult . errorModuleName ?
1339
+ return symbolAccesibilityResult . errorModuleName ?
1318
1340
symbolAccesibilityResult . accessibility === SymbolAccessibility . CannotBeNamed ?
1319
1341
Diagnostics . Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
1320
1342
Diagnostics . Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
1321
1343
Diagnostics . Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1 ;
1322
- break ;
1323
1344
1324
1345
case SyntaxKind . ConstructSignature :
1325
1346
// Interfaces cannot have parameter types that cannot be named
1326
- diagnosticMessage = symbolAccesibilityResult . errorModuleName ?
1347
+ return symbolAccesibilityResult . errorModuleName ?
1327
1348
Diagnostics . Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
1328
1349
Diagnostics . Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1 ;
1329
- break ;
1330
1350
1331
1351
case SyntaxKind . CallSignature :
1332
1352
// Interfaces cannot have parameter types that cannot be named
1333
- diagnosticMessage = symbolAccesibilityResult . errorModuleName ?
1353
+ return symbolAccesibilityResult . errorModuleName ?
1334
1354
Diagnostics . Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
1335
1355
Diagnostics . Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1 ;
1336
- break ;
1337
1356
1338
1357
case SyntaxKind . MethodDeclaration :
1339
1358
case SyntaxKind . MethodSignature :
1340
1359
if ( node . parent . flags & NodeFlags . Static ) {
1341
- diagnosticMessage = symbolAccesibilityResult . errorModuleName ?
1360
+ return symbolAccesibilityResult . errorModuleName ?
1342
1361
symbolAccesibilityResult . accessibility === SymbolAccessibility . CannotBeNamed ?
1343
1362
Diagnostics . Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
1344
1363
Diagnostics . Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
1345
1364
Diagnostics . Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1 ;
1346
1365
}
1347
1366
else if ( node . parent . parent . kind === SyntaxKind . ClassDeclaration ) {
1348
- diagnosticMessage = symbolAccesibilityResult . errorModuleName ?
1367
+ return symbolAccesibilityResult . errorModuleName ?
1349
1368
symbolAccesibilityResult . accessibility === SymbolAccessibility . CannotBeNamed ?
1350
1369
Diagnostics . Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
1351
1370
Diagnostics . Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
1352
1371
Diagnostics . Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1 ;
1353
1372
}
1354
1373
else {
1355
1374
// Interfaces cannot have parameter types that cannot be named
1356
- diagnosticMessage = symbolAccesibilityResult . errorModuleName ?
1375
+ return symbolAccesibilityResult . errorModuleName ?
1357
1376
Diagnostics . Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
1358
1377
Diagnostics . Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1 ;
1359
1378
}
1360
- break ;
1361
1379
1362
1380
case SyntaxKind . FunctionDeclaration :
1363
- diagnosticMessage = symbolAccesibilityResult . errorModuleName ?
1381
+ return symbolAccesibilityResult . errorModuleName ?
1364
1382
symbolAccesibilityResult . accessibility === SymbolAccessibility . CannotBeNamed ?
1365
1383
Diagnostics . Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
1366
1384
Diagnostics . Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 :
1367
1385
Diagnostics . Parameter_0_of_exported_function_has_or_is_using_private_name_1 ;
1368
- break ;
1369
1386
1370
1387
default :
1371
1388
Debug . fail ( "This is unknown parent for parameter: " + node . parent . kind ) ;
1372
1389
}
1390
+ }
1373
1391
1374
- return {
1375
- diagnosticMessage,
1376
- errorNode : node ,
1377
- typeName : node . name
1378
- } ;
1392
+ function emitBindingPattern ( bindingPattern : BindingPattern ) {
1393
+ // We have to explicitly emit square bracket and bracket because these tokens are not store inside the node.
1394
+ if ( bindingPattern . kind === SyntaxKind . ObjectBindingPattern ) {
1395
+ write ( "{" ) ;
1396
+ emitCommaList ( bindingPattern . elements , emitBindingElement ) ;
1397
+ write ( "}" ) ;
1398
+ }
1399
+ else if ( bindingPattern . kind === SyntaxKind . ArrayBindingPattern ) {
1400
+ write ( "[" ) ;
1401
+ let elements = bindingPattern . elements ;
1402
+ emitCommaList ( elements , emitBindingElement ) ;
1403
+ if ( elements && elements . hasTrailingComma ) {
1404
+ write ( ", " ) ;
1405
+ }
1406
+ write ( "]" ) ;
1407
+ }
1379
1408
}
1409
+
1410
+ function emitBindingElement ( bindingElement : BindingElement ) {
1411
+ function getBindingElementTypeVisibilityError ( symbolAccesibilityResult : SymbolAccessiblityResult ) : SymbolAccessibilityDiagnostic {
1412
+ let diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage ( symbolAccesibilityResult ) ;
1413
+ return diagnosticMessage !== undefined ? {
1414
+ diagnosticMessage,
1415
+ errorNode : bindingElement ,
1416
+ typeName : bindingElement . name
1417
+ } : undefined ;
1418
+ }
1419
+
1420
+ if ( bindingElement . kind === SyntaxKind . OmittedExpression ) {
1421
+ // If bindingElement is an omittedExpression (i.e. containing elision),
1422
+ // we will emit blank space (although this may differ from users' original code,
1423
+ // it allows emitSeparatedList to write separator appropriately)
1424
+ // Example:
1425
+ // original: function foo([, x, ,]) {}
1426
+ // emit : function foo([ , x, , ]) {}
1427
+ write ( " " ) ;
1428
+ }
1429
+ else if ( bindingElement . kind === SyntaxKind . BindingElement ) {
1430
+ if ( bindingElement . propertyName ) {
1431
+ // bindingElement has propertyName property in the following case:
1432
+ // { y: [a,b,c] ...} -> bindingPattern will have a property called propertyName for "y"
1433
+ // We have to explicitly emit the propertyName before descending into its binding elements.
1434
+ // Example:
1435
+ // original: function foo({y: [a,b,c]}) {}
1436
+ // emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void;
1437
+ writeTextOfNode ( currentSourceFile , bindingElement . propertyName ) ;
1438
+ write ( ": " ) ;
1439
+
1440
+ // If bindingElement has propertyName property, then its name must be another bindingPattern of SyntaxKind.ObjectBindingPattern
1441
+ emitBindingPattern ( < BindingPattern > bindingElement . name ) ;
1442
+ }
1443
+ else if ( bindingElement . name ) {
1444
+ if ( isBindingPattern ( bindingElement . name ) ) {
1445
+ // If it is a nested binding pattern, we will recursively descend into each element and emit each one separately.
1446
+ // In the case of rest element, we will omit rest element.
1447
+ // Example:
1448
+ // original: function foo([a, [[b]], c] = [1,[["string"]], 3]) {}
1449
+ // emit : declare function foo([a, [[b]], c]: [number, [[string]], number]): void;
1450
+ // original with rest: function foo([a, ...c]) {}
1451
+ // emit : declare function foo([a, ...c]): void;
1452
+ emitBindingPattern ( < BindingPattern > bindingElement . name ) ;
1453
+ }
1454
+ else {
1455
+ Debug . assert ( bindingElement . name . kind === SyntaxKind . Identifier ) ;
1456
+ // If the node is just an identifier, we will simply emit the text associated with the node's name
1457
+ // Example:
1458
+ // original: function foo({y = 10, x}) {}
1459
+ // emit : declare function foo({y, x}: {number, any}): void;
1460
+ if ( bindingElement . dotDotDotToken ) {
1461
+ write ( "..." ) ;
1462
+ }
1463
+ writeTextOfNode ( currentSourceFile , bindingElement . name ) ;
1464
+ }
1465
+ }
1466
+ }
1467
+ }
1380
1468
}
1381
1469
1382
1470
function emitNode ( node : Node ) {
0 commit comments