Provide brands for statements.

Introduce a ModuleElement type to provide more clear typesafety.
This commit is contained in:
Cyrus Najmabadi 2014-11-30 14:06:15 -08:00
parent 5f00c7cdbc
commit 54bd524c90
5 changed files with 50 additions and 30 deletions

View File

@ -7696,7 +7696,7 @@ module ts {
checkTypeAssignableTo(caseType, expressionType, clause.expression, /*headMessage*/ undefined);
}
}
checkBlock(clause);
forEach(clause.statements, checkSourceElement);
});
}
@ -8562,7 +8562,10 @@ module ts {
if (!(links.flags & NodeCheckFlags.TypeChecked)) {
emitExtends = false;
potentialThisCollisions.length = 0;
checkBody(node);
forEach(node.statements, checkSourceElement);
checkFunctionExpressionBodies(node);
if (isExternalModule(node)) {
var symbol = getExportAssignmentSymbol(node.symbol);
if (symbol && symbol.flags & SymbolFlags.Import) {
@ -8570,11 +8573,16 @@ module ts {
getSymbolLinks(symbol).referenced = true;
}
}
if (potentialThisCollisions.length) {
forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
potentialThisCollisions.length = 0;
}
if (emitExtends) links.flags |= NodeCheckFlags.EmitExtends;
if (emitExtends) {
links.flags |= NodeCheckFlags.EmitExtends;
}
links.flags |= NodeCheckFlags.TypeChecked;
}
}

View File

@ -701,7 +701,7 @@ module ts {
write(" {");
writeLine();
increaseIndent();
emitLines((<Block>node.body).statements);
emitLines((<ModuleBlock>node.body).statements);
decreaseIndent();
write("}");
writeLine();
@ -3264,7 +3264,7 @@ module ts {
emit(node.body);
decreaseIndent();
writeLine();
var moduleBlock = <Block>getInnerMostModuleDeclarationFromDottedModule(node).body;
var moduleBlock = <ModuleBlock>getInnerMostModuleDeclarationFromDottedModule(node).body;
emitToken(SyntaxKind.CloseBraceToken, moduleBlock.statements.end);
scopeEmitEnd();
}
@ -3410,7 +3410,7 @@ module ts {
}
}
function emitDirectivePrologues(statements: Statement[], startWithNewLine: boolean): number {
function emitDirectivePrologues(statements: Node[], startWithNewLine: boolean): number {
for (var i = 0; i < statements.length; ++i) {
if (isPrologueDirective(statements[i])) {
if (startWithNewLine || i > 0) {

View File

@ -405,7 +405,7 @@ module ts {
function traverse(node: Node): T {
switch (node.kind) {
case SyntaxKind.ReturnStatement:
return visitor(node);
return visitor(<ReturnStatement>node);
case SyntaxKind.Block:
case SyntaxKind.FunctionBlock:
case SyntaxKind.IfStatement:
@ -3591,8 +3591,8 @@ module ts {
return finishNode(node);
}
function parseFunctionDeclaration(fullStart: number, modifiers: ModifiersArray): FunctionLikeDeclaration {
var node = <FunctionLikeDeclaration>createNode(SyntaxKind.FunctionDeclaration, fullStart);
function parseFunctionDeclaration(fullStart: number, modifiers: ModifiersArray): FunctionDeclaration {
var node = <FunctionDeclaration>createNode(SyntaxKind.FunctionDeclaration, fullStart);
setModifiers(node, modifiers);
parseExpected(SyntaxKind.FunctionKeyword);
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
@ -3857,8 +3857,8 @@ module ts {
return finishNode(node);
}
function parseModuleBody(): Block {
var node = <Block>createNode(SyntaxKind.ModuleBlock, scanner.getStartPos());
function parseModuleBlock(): ModuleBlock {
var node = <ModuleBlock>createNode(SyntaxKind.ModuleBlock, scanner.getStartPos());
if (parseExpected(SyntaxKind.OpenBraceToken)) {
node.statements = parseList(ParsingContext.ModuleElements, /*checkForStrictMode*/ false, parseModuleElement);
parseExpected(SyntaxKind.CloseBraceToken);
@ -3875,7 +3875,7 @@ module ts {
node.name = parseIdentifier();
node.body = parseOptional(SyntaxKind.DotToken)
? parseInternalModuleTail(getNodePos(), NodeFlags.Export)
: parseModuleBody();
: parseModuleBlock();
return finishNode(node);
}
@ -3883,7 +3883,7 @@ module ts {
var node = <ModuleDeclaration>createNode(SyntaxKind.ModuleDeclaration, fullStart);
node.flags = flags;
node.name = parseStringLiteral();
node.body = parseModuleBody();
node.body = parseModuleBlock();
return finishNode(node);
}
@ -3950,7 +3950,7 @@ module ts {
}
}
function parseDeclaration(): Statement {
function parseDeclaration(): ModuleElement {
var fullStart = getNodePos();
var modifiers = parseModifiers();
if (token === SyntaxKind.ExportKeyword) {
@ -3961,7 +3961,7 @@ module ts {
}
var flags = modifiers ? modifiers.flags : 0;
var result: Declaration;
var result: ModuleElement;
switch (token) {
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
@ -4020,7 +4020,7 @@ module ts {
return parseSourceElementOrModuleElement();
}
function parseSourceElementOrModuleElement(): Statement {
function parseSourceElementOrModuleElement(): ModuleElement {
return isDeclarationStart()
? parseDeclaration()
: parseStatement();
@ -4380,7 +4380,7 @@ module ts {
}
function checkBreakOrContinueStatement(node: BreakOrContinueStatement): boolean {
var current = node;
var current: Node = node;
while (current) {
if (isAnyFunction(current)) {
return grammarErrorOnNode(node, Diagnostics.Jump_target_cannot_cross_function_boundary);
@ -4765,7 +4765,7 @@ module ts {
function checkModuleDeclarationStatements(node: ModuleDeclaration): boolean {
if (node.name.kind === SyntaxKind.Identifier && node.body.kind === SyntaxKind.ModuleBlock) {
var statements = (<Block>node.body).statements;
var statements = (<ModuleBlock>node.body).statements;
for (var i = 0, n = statements.length; i < n; i++) {
var statement = statements[i];

View File

@ -383,7 +383,7 @@ module ts {
body?: Block | Expression;
}
export interface FunctionDeclaration extends FunctionLikeDeclaration {
export interface FunctionDeclaration extends FunctionLikeDeclaration, Statement {
name: Identifier;
body?: Block;
}
@ -574,7 +574,9 @@ module ts {
expression: Expression;
}
export interface Statement extends Node { }
export interface Statement extends Node, ModuleElement {
_statementBrand: any;
}
export interface Block extends Statement {
statements: NodeArray<Statement>;
@ -662,7 +664,11 @@ module ts {
type?: TypeNode;
}
export interface ClassDeclaration extends Declaration {
export interface ModuleElement extends Node {
_moduleElementBrand: any;
}
export interface ClassDeclaration extends Declaration, ModuleElement {
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
baseType?: TypeReferenceNode;
@ -670,14 +676,14 @@ module ts {
members: NodeArray<Node>;
}
export interface InterfaceDeclaration extends Declaration {
export interface InterfaceDeclaration extends Declaration, ModuleElement {
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
baseTypes?: NodeArray<TypeReferenceNode>;
members: NodeArray<Node>;
}
export interface TypeAliasDeclaration extends Declaration {
export interface TypeAliasDeclaration extends Declaration, ModuleElement {
name: Identifier;
type: TypeNode;
}
@ -689,23 +695,27 @@ module ts {
initializer?: Expression;
}
export interface EnumDeclaration extends Declaration {
export interface EnumDeclaration extends Declaration, ModuleElement {
name: Identifier;
members: NodeArray<EnumMember>;
}
export interface ModuleDeclaration extends Declaration {
export interface ModuleDeclaration extends Declaration, ModuleElement {
name: Identifier | LiteralExpression;
body: Block | ModuleDeclaration;
body: ModuleBlock | ModuleDeclaration;
}
export interface ImportDeclaration extends Declaration {
export interface ModuleBlock extends Node, ModuleElement {
statements: NodeArray<ModuleElement>
}
export interface ImportDeclaration extends Declaration, ModuleElement {
name: Identifier;
entityName?: EntityName;
externalModuleName?: LiteralExpression;
}
export interface ExportAssignment extends Statement {
export interface ExportAssignment extends Statement, ModuleElement {
exportName: Identifier;
}
@ -717,7 +727,9 @@ module ts {
hasTrailingNewLine?: boolean;
}
export interface SourceFile extends Block {
export interface SourceFile extends Node {
statements: NodeArray<ModuleElement>;
filename: string;
text: string;
getLineAndCharacterFromPosition(position: number): LineAndCharacter;

View File

@ -3724,7 +3724,7 @@ module ts {
function aggregate(node: Node): void {
if (node.kind === SyntaxKind.BreakStatement || node.kind === SyntaxKind.ContinueStatement) {
statementAccumulator.push(node);
statementAccumulator.push(<BreakOrContinueStatement>node);
}
// Do not cross function boundaries.
else if (!isAnyFunction(node)) {