Skip to content

use 'allowGeneratedIdentifiers' to explicitly tell when identifier can b... #2374

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 16, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 4 additions & 19 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11085,26 +11085,11 @@ module ts {
function getBlockScopedVariableId(n: Identifier): number {
Debug.assert(!nodeIsSynthesized(n));

// ignore name parts of property access expressions
if (n.parent.kind === SyntaxKind.PropertyAccessExpression &&
(<PropertyAccessExpression>n.parent).name === n) {
return undefined;
}

// ignore property names in object binding patterns
if (n.parent.kind === SyntaxKind.BindingElement &&
(<BindingElement>n.parent).propertyName === n) {
return undefined;
}

// for names in variable declarations and binding elements try to short circuit and fetch symbol from the node
let declarationSymbol: Symbol =
(n.parent.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>n.parent).name === n) ||
n.parent.kind === SyntaxKind.BindingElement
? getSymbolOfNode(n.parent)
: undefined;
let isVariableDeclarationOrBindingElement =
n.parent.kind === SyntaxKind.BindingElement || (n.parent.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>n.parent).name === n);

let symbol = declarationSymbol ||
let symbol =
(isVariableDeclarationOrBindingElement ? getSymbolOfNode(n.parent) : undefined) ||
getNodeLinks(n).resolvedSymbol ||
resolveName(n, n.text, SymbolFlags.Value | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined);

Expand Down
72 changes: 46 additions & 26 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2074,19 +2074,19 @@ module ts {
sourceMapDir = getDirectoryPath(normalizePath(jsFilePath));
}

function emitNodeWithSourceMap(node: Node) {
function emitNodeWithSourceMap(node: Node, allowGeneratedIdentifiers?: boolean) {
if (node) {
if (nodeIsSynthesized(node)) {
return emitNodeWithoutSourceMap(node);
return emitNodeWithoutSourceMap(node, /*allowGeneratedIdentifiers*/ false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment

}
if (node.kind != SyntaxKind.SourceFile) {
recordEmitNodeStartSpan(node);
emitNodeWithoutSourceMap(node);
emitNodeWithoutSourceMap(node, allowGeneratedIdentifiers);
recordEmitNodeEndSpan(node);
}
else {
recordNewSourceFileStart(<SourceFile>node);
emitNodeWithoutSourceMap(node);
emitNodeWithoutSourceMap(node, /*allowGeneratedIdentifiers*/ false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add small comment

}
}
}
Expand Down Expand Up @@ -2623,17 +2623,24 @@ module ts {
}
}

function getBlockScopedVariableId(node: Identifier): number {
// return undefined for synthesized nodes
return !nodeIsSynthesized(node) && resolver.getBlockScopedVariableId(node);
function getGeneratedNameForIdentifier(node: Identifier): string {
if (nodeIsSynthesized(node) || !generatedBlockScopeNames) {
return undefined;
}

var variableId = resolver.getBlockScopedVariableId(node)
if (variableId === undefined) {
return undefined;
}

return generatedBlockScopeNames[variableId];
}

function emitIdentifier(node: Identifier) {
let variableId = getBlockScopedVariableId(node);
if (variableId !== undefined && generatedBlockScopeNames) {
let text = generatedBlockScopeNames[variableId];
if (text) {
write(text);
function emitIdentifier(node: Identifier, allowGeneratedIdentifiers: boolean) {
if (allowGeneratedIdentifiers) {
let generatedName = getGeneratedNameForIdentifier(node);
if (generatedName) {
write(generatedName);
return;
}
}
Expand Down Expand Up @@ -2686,7 +2693,7 @@ module ts {

function emitBindingElement(node: BindingElement) {
if (node.propertyName) {
emit(node.propertyName);
emit(node.propertyName, /*allowGeneratedIdentifiers*/ false);
write(": ");
}
if (node.dotDotDotToken) {
Expand Down Expand Up @@ -3030,21 +3037,21 @@ module ts {
}

function emitMethod(node: MethodDeclaration) {
emit(node.name);
emit(node.name, /*allowGeneratedIdentifiers*/ false);
if (languageVersion < ScriptTarget.ES6) {
write(": function ");
}
emitSignatureAndBody(node);
}

function emitPropertyAssignment(node: PropertyDeclaration) {
emit(node.name);
emit(node.name, /*allowGeneratedIdentifiers*/ false);
write(": ");
emit(node.initializer);
}

function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) {
emit(node.name);
emit(node.name, /*allowGeneratedIdentifiers*/ false);
// If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment. For example:
// module m {
// export let y;
Expand All @@ -3053,7 +3060,20 @@ module ts {
// export let obj = { y };
// }
// The short-hand property in obj need to emit as such ... = { y : m.y } regardless of the TargetScript version
if (languageVersion < ScriptTarget.ES6 || resolver.getExpressionNameSubstitution(node.name)) {
if (languageVersion < ScriptTarget.ES6) {
// Emit identifier as an identifier
write(": ");
var generatedName = getGeneratedNameForIdentifier(node.name);
if (generatedName) {
write(generatedName);
}
else {
// Even though this is stored as identifier treat it as an expression
// Short-hand, { x }, is equivalent of normal form { x: x }
emitExpressionIdentifier(node.name);
}
}
else if (resolver.getExpressionNameSubstitution(node.name)) {
// Emit identifier as an identifier
write(": ");
// Even though this is stored as identifier treat it as an expression
Expand Down Expand Up @@ -3106,7 +3126,7 @@ module ts {
let indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken);
write(".");
let indentedAfterDot = indentIfOnDifferentLines(node, node.dotToken, node.name);
emit(node.name);
emit(node.name, /*allowGeneratedIdentifiers*/ false);
decreaseIndentIf(indentedBeforeDot, indentedAfterDot);
}

Expand Down Expand Up @@ -4294,7 +4314,7 @@ module ts {

function emitAccessor(node: AccessorDeclaration) {
write(node.kind === SyntaxKind.GetAccessor ? "get " : "set ");
emit(node.name);
emit(node.name, /*allowGeneratedIdentifiers*/ false);
emitSignatureAndBody(node);
}

Expand Down Expand Up @@ -5340,7 +5360,7 @@ module ts {
emitLeadingComments(node.endOfFileToken);
}

function emitNodeWithoutSourceMapWithComments(node: Node): void {
function emitNodeWithoutSourceMapWithComments(node: Node, allowGeneratedIdentifiers?: boolean): void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use default value

if (!node) {
return;
}
Expand All @@ -5354,14 +5374,14 @@ module ts {
emitLeadingComments(node);
}

emitJavaScriptWorker(node);
emitJavaScriptWorker(node, allowGeneratedIdentifiers);

if (emitComments) {
emitTrailingComments(node);
}
}

function emitNodeWithoutSourceMapWithoutComments(node: Node): void {
function emitNodeWithoutSourceMapWithoutComments(node: Node, allowGeneratedIdentifiers?: boolean): void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add default value

if (!node) {
return;
}
Expand All @@ -5370,7 +5390,7 @@ module ts {
return emitPinnedOrTripleSlashComments(node);
}

emitJavaScriptWorker(node);
emitJavaScriptWorker(node, allowGeneratedIdentifiers);
}

function shouldEmitLeadingAndTrailingComments(node: Node) {
Expand Down Expand Up @@ -5400,11 +5420,11 @@ module ts {
return true;
}

function emitJavaScriptWorker(node: Node) {
function emitJavaScriptWorker(node: Node, allowGeneratedIdentifiers: boolean = true) {
// Check if the node can be emitted regardless of the ScriptTarget
switch (node.kind) {
case SyntaxKind.Identifier:
return emitIdentifier(<Identifier>node);
return emitIdentifier(<Identifier>node, allowGeneratedIdentifiers);
case SyntaxKind.Parameter:
return emitParameter(<ParameterDeclaration>node);
case SyntaxKind.MethodDeclaration:
Expand Down
46 changes: 46 additions & 0 deletions tests/baselines/reference/initializePropertiesWithRenamedLet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//// [initializePropertiesWithRenamedLet.ts]

var x0;
if (true) {
let x0;
var obj1 = { x0: x0 };
var obj2 = { x0 };
}

var x, y, z;
if (true) {
let { x: x } = { x: 0 };
let { y } = { y: 0 };
let z;
({ z: z } = { z: 0 });
({ z } = { z: 0 });
}

//// [initializePropertiesWithRenamedLet.js]
var x0;
if (true) {
var _x0;
var obj1 = {
x0: _x0
};
var obj2 = {
x0: _x0
};
}
var x, y, z;
if (true) {
var _x = ({
x: 0
}).x;
var _y = ({
y: 0
}).y;
var _z;
(_a = {
z: 0
}, _z = _a.z, _a);
(_b = {
z: 0
}, _z = _b.z, _b);
}
var _a, _b;
58 changes: 58 additions & 0 deletions tests/baselines/reference/initializePropertiesWithRenamedLet.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
=== tests/cases/compiler/initializePropertiesWithRenamedLet.ts ===

var x0;
>x0 : any

if (true) {
let x0;
>x0 : any

var obj1 = { x0: x0 };
>obj1 : { x0: any; }
>{ x0: x0 } : { x0: any; }
>x0 : any
>x0 : any

var obj2 = { x0 };
>obj2 : { x0: any; }
>{ x0 } : { x0: any; }
>x0 : any
}

var x, y, z;
>x : any
>y : any
>z : any

if (true) {
let { x: x } = { x: 0 };
>x : unknown
>x : number
>{ x: 0 } : { x: number; }
>x : number

let { y } = { y: 0 };
>y : number
>{ y: 0 } : { y: number; }
>y : number

let z;
>z : any

({ z: z } = { z: 0 });
>({ z: z } = { z: 0 }) : { z: number; }
>{ z: z } = { z: 0 } : { z: number; }
>{ z: z } : { z: any; }
>z : any
>z : any
>{ z: 0 } : { z: number; }
>z : number

({ z } = { z: 0 });
>({ z } = { z: 0 }) : { z: number; }
>{ z } = { z: 0 } : { z: number; }
>{ z } : { z: any; }
>z : any
>{ z: 0 } : { z: number; }
>z : number
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ if (true) {
if (true) {
var x = 0; // Error
var _a = ({
_x: 0
x: 0
}).x, x = _a === void 0 ? 0 : _a; // Error
var _b = ({
_x: 0
x: 0
}).x, x = _b === void 0 ? 0 : _b; // Error
var x = ({
_x: 0
x: 0
}).x; // Error
var x = ({
_x: 0
x: 0
}).x; // Error
}
}
17 changes: 17 additions & 0 deletions tests/cases/compiler/initializePropertiesWithRenamedLet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// @target: es5

var x0;
if (true) {
let x0;
var obj1 = { x0: x0 };
var obj2 = { x0 };
}

var x, y, z;
if (true) {
let { x: x } = { x: 0 };
let { y } = { y: 0 };
let z;
({ z: z } = { z: 0 });
({ z } = { z: 0 });
}