Skip to content
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

Let and const support #904

Merged
merged 30 commits into from
Oct 24, 2014
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
873c1df
Add es6 target
mhegazy Oct 11, 2014
778f101
Add basic parsing support for let and const
mhegazy Oct 13, 2014
979d45e
Disallow let and const declarations outside blocks
mhegazy Oct 13, 2014
6f6f4af
Fix line endings
mhegazy Oct 13, 2014
cf89f5c
Add binder support for block scoped variable declarations
mhegazy Oct 14, 2014
1dde985
Do not allow use of block-scoped variable before its definition
mhegazy Oct 14, 2014
318575c
Ensure duplicate let/const declarations accross files are reported
mhegazy Oct 14, 2014
cffc62a
Report duplicate identifier errors on all locations for merged declar…
mhegazy Oct 14, 2014
f5c2740
Flag assignments to a const
mhegazy Oct 14, 2014
82f5fb4
Flag const declarations shodowed by var redeclarations
mhegazy Oct 15, 2014
3e45601
Allow const in for statements
mhegazy Oct 15, 2014
03a100d
Do not allow let and const declarations to be exported from a module
mhegazy Oct 15, 2014
6154923
Fix emitting for const in for loops
mhegazy Oct 15, 2014
e15f4e6
Merge branch 'master' into letAndConst
mhegazy Oct 16, 2014
60bb37b
Add language service support for const
mhegazy Oct 16, 2014
fd469d6
Fix search for shadowed const declarations by a var declarations to s…
mhegazy Oct 17, 2014
4ef68b9
Respond to code review comments
mhegazy Oct 17, 2014
a5a6c6f
Allow const and let declarations to be exported in modules. Also ensu…
mhegazy Oct 17, 2014
0a59cdd
Treat blockScoped variable declarations as a separate category when i…
mhegazy Oct 17, 2014
0e7d8b6
Merge branch 'master' into letAndConst
mhegazy Oct 20, 2014
dd5c89d
Update error messages
mhegazy Oct 20, 2014
91f4098
Simplify the binder logic for managing blockScopeContainer
mhegazy Oct 20, 2014
d5fe43b
allow let and const declarations in module bodies under labels
mhegazy Oct 20, 2014
dd7ca69
Create a new flag for diagnostics 'isEarly' and disable emit if this …
mhegazy Oct 21, 2014
373dc76
respond to code review comments
mhegazy Oct 21, 2014
9353c11
Merge branch 'master' into letAndConst
mhegazy Oct 23, 2014
d1858d0
Merge branch 'master' into letAndConst
mhegazy Oct 23, 2014
e4a2084
Ensure let and const declarations in labels are parsed correctelly
mhegazy Oct 24, 2014
67c78a2
Only check for collisions with variabels and not properties
mhegazy Oct 24, 2014
51e101c
Merge branch 'master' into letAndConst
mhegazy Oct 24, 2014
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
112 changes: 80 additions & 32 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@ module ts {

var parent: Node;
var container: Declaration;
var blockScopeContainer: Node;
var lastContainer: Declaration;
var symbolCount = 0;
var Symbol = objectAllocator.getSymbolConstructor();

if (!file.locals) {
file.locals = {};
container = file;
container = blockScopeContainer = file;
bind(file);
file.symbolCount = symbolCount;
}
Expand Down Expand Up @@ -167,12 +168,13 @@ module ts {

// All container nodes are kept on a linked list in declaration order. This list is used by the getLocalNameOfContainer function
// in the type checker to validate that the local name used for a container is unique.
function bindChildren(node: Declaration, symbolKind: SymbolFlags) {
function bindChildren(node: Declaration, symbolKind: SymbolFlags, isBlockScopeContainer: boolean) {
if (symbolKind & SymbolFlags.HasLocals) {
node.locals = {};
}
var saveParent = parent;
var saveContainer = container;
var savedBlockScopeContainer = blockScopeContainer;
parent = node;
if (symbolKind & SymbolFlags.IsContainer) {
container = node;
Expand All @@ -184,12 +186,16 @@ module ts {
lastContainer = container;
}
}
if (isBlockScopeContainer) {
blockScopeContainer = node;
}
forEachChild(node, bind);
container = saveContainer;
parent = saveParent;
blockScopeContainer = savedBlockScopeContainer;
}

function bindDeclaration(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags) {
function bindDeclaration(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags, isBlockScopeContainer: boolean) {
switch (container.kind) {
case SyntaxKind.ModuleDeclaration:
declareModuleMember(node, symbolKind, symbolExcludes);
Expand Down Expand Up @@ -225,126 +231,168 @@ module ts {
declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
break;
}
bindChildren(node, symbolKind);
bindChildren(node, symbolKind, isBlockScopeContainer);
}

function bindConstructorDeclaration(node: ConstructorDeclaration) {
bindDeclaration(node, SymbolFlags.Constructor, 0);
bindDeclaration(node, SymbolFlags.Constructor, 0, /*isBlockScopeContainer*/ true);
forEach(node.parameters, p => {
if (p.flags & (NodeFlags.Public | NodeFlags.Private | NodeFlags.Protected)) {
bindDeclaration(p, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
bindDeclaration(p, SymbolFlags.Property, SymbolFlags.PropertyExcludes, /*isBlockScopeContainer*/ false);
}
});
}

function bindModuleDeclaration(node: ModuleDeclaration) {
if (node.name.kind === SyntaxKind.StringLiteral) {
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
}
else if (isInstantiated(node)) {
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
}
else {
bindDeclaration(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes);
bindDeclaration(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes, /*isBlockScopeContainer*/ true);
}
}

function bindAnonymousDeclaration(node: Node, symbolKind: SymbolFlags, name: string) {
function bindAnonymousDeclaration(node: Node, symbolKind: SymbolFlags, name: string, isBlockScopeContainer: boolean) {
var symbol = createSymbol(symbolKind, name);
addDeclarationToSymbol(symbol, node, symbolKind);
bindChildren(node, symbolKind);
bindChildren(node, symbolKind, isBlockScopeContainer);
}

function bindCatchVariableDeclaration(node: CatchBlock) {
var symbol = createSymbol(SymbolFlags.Variable, node.variable.text || "__missing");
addDeclarationToSymbol(symbol, node, SymbolFlags.Variable);
var saveParent = parent;
parent = node;
var savedBlockScopeContainer = blockScopeContainer;
parent = blockScopeContainer = node;
forEachChild(node, bind);
parent = saveParent;
blockScopeContainer = savedBlockScopeContainer;
}

function bindBlockScopedVariableDeclaration(node: Declaration) {
var symbolKind = SymbolFlags.Variable | SymbolFlags.BlockScoped;
switch (blockScopeContainer.kind) {
case SyntaxKind.ModuleDeclaration:
declareModuleMember(node, symbolKind, SymbolFlags.BlockScopedExcludes);
break;
case SyntaxKind.SourceFile:
if (isExternalModule(<SourceFile>container)) {
declareModuleMember(node, symbolKind, SymbolFlags.BlockScopedExcludes);
break;
}
default:
if (!blockScopeContainer.locals) {
blockScopeContainer.locals = {};
}
declareSymbol(blockScopeContainer.locals, undefined, node, symbolKind, SymbolFlags.BlockScopedExcludes);
}

bindChildren(node, symbolKind, /*isBlockScopeContainer*/ false);
}

function bind(node: Node) {
var isBlockScopeContainer: boolean;
node.parent = parent;
switch (node.kind) {
case SyntaxKind.TypeParameter:
bindDeclaration(<Declaration>node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.Parameter:
bindDeclaration(<Declaration>node, SymbolFlags.Variable, SymbolFlags.ParameterExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.Variable, SymbolFlags.ParameterExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.VariableDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.Variable, SymbolFlags.VariableExcludes);
if (node.flags & NodeFlags.BlockScoped) {
bindBlockScopedVariableDeclaration(<Declaration>node);
}
else {
bindDeclaration(<Declaration>node, SymbolFlags.Variable, SymbolFlags.VariableExcludes, /*isBlockScopeContainer*/ false);
}
break;
case SyntaxKind.Property:
case SyntaxKind.PropertyAssignment:
bindDeclaration(<Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.EnumMember:
bindDeclaration(<Declaration>node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.CallSignature:
bindDeclaration(<Declaration>node, SymbolFlags.CallSignature, 0);
bindDeclaration(<Declaration>node, SymbolFlags.CallSignature, 0, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.Method:
bindDeclaration(<Declaration>node, SymbolFlags.Method, SymbolFlags.MethodExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.Method, SymbolFlags.MethodExcludes, /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.ConstructSignature:
bindDeclaration(<Declaration>node, SymbolFlags.ConstructSignature, 0);
bindDeclaration(<Declaration>node, SymbolFlags.ConstructSignature, 0, /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.IndexSignature:
bindDeclaration(<Declaration>node, SymbolFlags.IndexSignature, 0);
bindDeclaration(<Declaration>node, SymbolFlags.IndexSignature, 0, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.FunctionDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.Function, SymbolFlags.FunctionExcludes, /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.Constructor:
bindConstructorDeclaration(<ConstructorDeclaration>node);
break;
case SyntaxKind.GetAccessor:
bindDeclaration(<Declaration>node, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes, /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.SetAccessor:
bindDeclaration(<Declaration>node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes, /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.TypeLiteral:
bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type");
bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type", /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.ObjectLiteral:
bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object");
bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object", /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
bindAnonymousDeclaration(node, SymbolFlags.Function, "__function");
bindAnonymousDeclaration(node, SymbolFlags.Function, "__function", /*isBlockScopeContainer*/ true);
break;
case SyntaxKind.CatchBlock:
bindCatchVariableDeclaration(<CatchBlock>node);
break;
case SyntaxKind.ClassDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.Class, SymbolFlags.ClassExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.Class, SymbolFlags.ClassExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.InterfaceDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.EnumDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.Enum, SymbolFlags.EnumExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.Enum, SymbolFlags.EnumExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.ModuleDeclaration:
bindModuleDeclaration(<ModuleDeclaration>node);
break;
case SyntaxKind.ImportDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes);
bindDeclaration(<Declaration>node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.SourceFile:
if (isExternalModule(<SourceFile>node)) {
bindAnonymousDeclaration(node, SymbolFlags.ValueModule, '"' + removeFileExtension((<SourceFile>node).filename) + '"');
bindAnonymousDeclaration(node, SymbolFlags.ValueModule, '"' + removeFileExtension((<SourceFile>node).filename) + '"', /*isBlockScopeContainer*/ true);
break;
}

case SyntaxKind.Block:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.FinallyBlock:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.SwitchStatement:
isBlockScopeContainer = true;

default:
var saveParent = parent;
var savedBlockScopeContainer = blockScopeContainer;
parent = node;
if (isBlockScopeContainer) blockScopeContainer = node;
forEachChild(node, bind);
parent = saveParent;
blockScopeContainer = savedBlockScopeContainer;
}
}
}
Expand Down
Loading