@@ -571,24 +571,24 @@ function handleImportDeclarations(node: tsEs.Program) {
571
571
* Type checking is not carried out as this function is only responsible for hoisting declarations.
572
572
*/
573
573
function addTypeDeclarationsToEnvironment ( node : tsEs . Program | tsEs . BlockStatement ) {
574
- node . body . forEach ( node => {
575
- switch ( node . type ) {
574
+ node . body . forEach ( bodyNode => {
575
+ switch ( bodyNode . type ) {
576
576
case 'FunctionDeclaration' :
577
- if ( node . id === null ) {
577
+ if ( bodyNode . id === null ) {
578
578
throw new Error (
579
579
'Encountered a FunctionDeclaration node without an identifier. This should have been caught when parsing.'
580
580
)
581
581
}
582
582
// Only identifiers/rest elements are used as function params in Source
583
- const params = node . params . filter (
583
+ const params = bodyNode . params . filter (
584
584
( param ) : param is tsEs . Identifier | tsEs . RestElement =>
585
585
param . type === 'Identifier' || param . type === 'RestElement'
586
586
)
587
- if ( params . length !== node . params . length ) {
588
- throw new TypecheckError ( node , 'Unknown function parameter type' )
587
+ if ( params . length !== bodyNode . params . length ) {
588
+ throw new TypecheckError ( bodyNode , 'Unknown function parameter type' )
589
589
}
590
- const fnName = node . id . name
591
- const returnType = getTypeAnnotationType ( node . returnType )
590
+ const fnName = bodyNode . id . name
591
+ const returnType = getTypeAnnotationType ( bodyNode . returnType )
592
592
593
593
// If the function has variable number of arguments, set function type as any
594
594
// TODO: Add support for variable number of function arguments
@@ -607,46 +607,52 @@ function addTypeDeclarationsToEnvironment(node: tsEs.Program | tsEs.BlockStateme
607
607
setType ( fnName , fnType , env )
608
608
break
609
609
case 'VariableDeclaration' :
610
- if ( node . kind === 'var' ) {
611
- throw new TypecheckError ( node , 'Variable declaration using "var" is not allowed' )
610
+ if ( bodyNode . kind === 'var' ) {
611
+ throw new TypecheckError ( bodyNode , 'Variable declaration using "var" is not allowed' )
612
612
}
613
- if ( node . declarations . length !== 1 ) {
613
+ if ( bodyNode . declarations . length !== 1 ) {
614
614
throw new TypecheckError (
615
- node ,
615
+ bodyNode ,
616
616
'Variable declaration should have one and only one declaration'
617
617
)
618
618
}
619
- if ( node . declarations [ 0 ] . id . type !== 'Identifier' ) {
620
- throw new TypecheckError ( node , 'Variable declaration ID should be an identifier' )
619
+ if ( bodyNode . declarations [ 0 ] . id . type !== 'Identifier' ) {
620
+ throw new TypecheckError ( bodyNode , 'Variable declaration ID should be an identifier' )
621
621
}
622
- const id = node . declarations [ 0 ] . id as tsEs . Identifier
622
+ const id = bodyNode . declarations [ 0 ] . id as tsEs . Identifier
623
623
const expectedType = getTypeAnnotationType ( id . typeAnnotation )
624
624
625
625
// Save variable type and decl kind in type env
626
626
setType ( id . name , expectedType , env )
627
- setDeclKind ( id . name , node . kind , env )
627
+ setDeclKind ( id . name , bodyNode . kind , env )
628
628
break
629
629
case 'TSTypeAliasDeclaration' :
630
- const alias = node . id . name
630
+ if ( node . type === 'BlockStatement' ) {
631
+ throw new TypecheckError (
632
+ bodyNode ,
633
+ 'Type alias declarations may only appear at the top level'
634
+ )
635
+ }
636
+ const alias = bodyNode . id . name
631
637
if ( Object . values ( typeAnnotationKeywordToBasicTypeMap ) . includes ( alias as TSBasicType ) ) {
632
- context . errors . push ( new TypeAliasNameNotAllowedError ( node , alias ) )
638
+ context . errors . push ( new TypeAliasNameNotAllowedError ( bodyNode , alias ) )
633
639
break
634
640
}
635
641
if ( lookupTypeAlias ( alias , env ) !== undefined ) {
636
642
// Only happens when attempting to declare type aliases that share names with predeclared types (e.g. Pair, List)
637
643
// Declaration of two type aliases with the same name will be caught as syntax error by parser
638
- context . errors . push ( new DuplicateTypeAliasError ( node , alias ) )
644
+ context . errors . push ( new DuplicateTypeAliasError ( bodyNode , alias ) )
639
645
break
640
646
}
641
647
642
648
let type : BindableType = tAny
643
- if ( node . typeParameters && node . typeParameters . params . length > 0 ) {
649
+ if ( bodyNode . typeParameters && bodyNode . typeParameters . params . length > 0 ) {
644
650
const typeParams : Variable [ ] = [ ]
645
651
// Check validity of type parameters
646
652
pushEnv ( env )
647
- node . typeParameters . params . forEach ( param => {
653
+ bodyNode . typeParameters . params . forEach ( param => {
648
654
if ( param . type !== 'TSTypeParameter' ) {
649
- throw new TypecheckError ( node , 'Invalid type parameter type' )
655
+ throw new TypecheckError ( bodyNode , 'Invalid type parameter type' )
650
656
}
651
657
const name = param . name
652
658
if ( Object . values ( typeAnnotationKeywordToBasicTypeMap ) . includes ( name as TSBasicType ) ) {
@@ -655,10 +661,10 @@ function addTypeDeclarationsToEnvironment(node: tsEs.Program | tsEs.BlockStateme
655
661
}
656
662
typeParams . push ( tVar ( name ) )
657
663
} )
658
- type = tForAll ( getTypeAnnotationType ( node ) , typeParams )
664
+ type = tForAll ( getTypeAnnotationType ( bodyNode ) , typeParams )
659
665
env . pop ( )
660
666
} else {
661
- type = getTypeAnnotationType ( node )
667
+ type = getTypeAnnotationType ( bodyNode )
662
668
}
663
669
setTypeAlias ( alias , type , env )
664
670
break
0 commit comments