@@ -140,15 +140,18 @@ export class TSHelper {
140140 ( type . flags & ts . TypeFlags . StringLiteral ) !== 0 ;
141141 }
142142
143- public static isArrayTypeNode ( typeNode : ts . TypeNode ) : boolean {
144- return typeNode . kind === ts . SyntaxKind . ArrayType || typeNode . kind === ts . SyntaxKind . TupleType ||
145- ( ( typeNode . kind === ts . SyntaxKind . UnionType || typeNode . kind === ts . SyntaxKind . IntersectionType ) &&
146- ( typeNode as ts . UnionOrIntersectionTypeNode ) . types . some ( TSHelper . isArrayTypeNode ) ) ;
147- }
143+ public static isExplicitArrayType ( type : ts . Type , checker : ts . TypeChecker , program : ts . Program ) : boolean {
144+ if ( type . isUnionOrIntersection ( ) ) {
145+ return type . types . some ( t => TSHelper . isExplicitArrayType ( t , checker , program ) ) ;
146+ }
148147
149- public static isExplicitArrayType ( type : ts . Type , checker : ts . TypeChecker ) : boolean {
150- const typeNode = checker . typeToTypeNode ( type , undefined , ts . NodeBuilderFlags . InTypeAlias ) ;
151- return typeNode && TSHelper . isArrayTypeNode ( typeNode ) ;
148+ if ( TSHelper . isStandardLibraryType ( type , "ReadonlyArray" , program ) ) {
149+ return true ;
150+ }
151+
152+ const flags = ts . NodeBuilderFlags . InTypeAlias | ts . NodeBuilderFlags . AllowEmptyTuple ;
153+ const typeNode = checker . typeToTypeNode ( type , undefined , flags ) ;
154+ return typeNode && ( ts . isArrayTypeNode ( typeNode ) || ts . isTupleTypeNode ( typeNode ) ) ;
152155 }
153156
154157 public static isFunctionType ( type : ts . Type , checker : ts . TypeChecker ) : boolean {
@@ -161,8 +164,8 @@ export class TSHelper {
161164 return TSHelper . isFunctionType ( type , checker ) ;
162165 }
163166
164- public static isArrayType ( type : ts . Type , checker : ts . TypeChecker ) : boolean {
165- return TSHelper . forTypeOrAnySupertype ( type , checker , t => TSHelper . isExplicitArrayType ( t , checker ) ) ;
167+ public static isArrayType ( type : ts . Type , checker : ts . TypeChecker , program : ts . Program ) : boolean {
168+ return TSHelper . forTypeOrAnySupertype ( type , checker , t => TSHelper . isExplicitArrayType ( t , checker , program ) ) ;
166169 }
167170
168171 public static isLuaIteratorType ( node : ts . Node , checker : ts . TypeChecker ) : boolean {
@@ -180,12 +183,12 @@ export class TSHelper {
180183 }
181184 }
182185
183- public static isInTupleReturnFunction ( node : ts . Node , checker : ts . TypeChecker ) : boolean {
186+ public static isInTupleReturnFunction ( node : ts . Node , checker : ts . TypeChecker , program : ts . Program ) : boolean {
184187 const declaration = TSHelper . findFirstNodeAbove ( node , ts . isFunctionLike ) ;
185188 if ( declaration ) {
186189 let functionType : ts . Type ;
187190 if ( ts . isFunctionExpression ( declaration ) || ts . isArrowFunction ( declaration ) ) {
188- functionType = TSHelper . inferAssignedType ( declaration , checker ) ;
191+ functionType = TSHelper . inferAssignedType ( declaration , checker , program ) ;
189192 } else {
190193 functionType = checker . getTypeAtLocation ( declaration ) ;
191194 }
@@ -330,13 +333,17 @@ export class TSHelper {
330333
331334 // If expression is property/element access with possible effects from being evaluated, returns true along with the
332335 // separated object and index expressions.
333- public static isAccessExpressionWithEvaluationEffects ( node : ts . Expression , checker : ts . TypeChecker ) :
334- [ boolean , ts . Expression , ts . Expression ] {
336+ public static isAccessExpressionWithEvaluationEffects (
337+ node : ts . Expression ,
338+ checker : ts . TypeChecker ,
339+ program : ts . Program
340+ ) : [ boolean , ts . Expression , ts . Expression ]
341+ {
335342 if ( ts . isElementAccessExpression ( node ) &&
336343 ( TSHelper . isExpressionWithEvaluationEffect ( node . expression )
337344 || TSHelper . isExpressionWithEvaluationEffect ( node . argumentExpression ) ) ) {
338345 const type = checker . getTypeAtLocation ( node . expression ) ;
339- if ( TSHelper . isArrayType ( type , checker ) ) {
346+ if ( TSHelper . isArrayType ( type , checker , program ) ) {
340347 // Offset arrays by one
341348 const oneLit = ts . createNumericLiteral ( "1" ) ;
342349 const exp = ts . createParen ( node . argumentExpression ) ;
@@ -446,10 +453,10 @@ export class TSHelper {
446453 ) !== undefined ;
447454 }
448455
449- public static inferAssignedType ( expression : ts . Expression , checker : ts . TypeChecker ) : ts . Type {
456+ public static inferAssignedType ( expression : ts . Expression , checker : ts . TypeChecker , program : ts . Program ) : ts . Type {
450457 if ( ts . isParenthesizedExpression ( expression . parent ) ) {
451458 // Ignore expressions wrapped in parenthesis
452- return this . inferAssignedType ( expression . parent , checker ) ;
459+ return this . inferAssignedType ( expression . parent , checker , program ) ;
453460
454461 } else if ( ts . isCallOrNewExpression ( expression . parent ) ) {
455462 // Expression being passed as argument to a function
@@ -462,7 +469,7 @@ export class TSHelper {
462469 parentSignature . parameters [ signatureIndex ] ,
463470 expression
464471 ) ;
465- if ( TSHelper . isArrayType ( parameterType , checker ) ) {
472+ if ( TSHelper . isArrayType ( parameterType , checker , program ) ) {
466473 // Check for elipses argument
467474 const parentSignatureDeclaration = parentSignature . getDeclaration ( ) ;
468475 if ( parentSignatureDeclaration ) {
@@ -496,7 +503,7 @@ export class TSHelper {
496503
497504 } else if ( ts . isPropertyAssignment ( expression . parent ) ) {
498505 // Expression being assigned to an object literal property
499- const objType = this . inferAssignedType ( expression . parent . parent , checker ) ;
506+ const objType = this . inferAssignedType ( expression . parent . parent , checker , program ) ;
500507 const property = objType . getProperty ( expression . parent . name . getText ( ) ) ;
501508 if ( ! property ) {
502509 const stringPropertyType = objType . getStringIndexType ( ) ;
@@ -509,7 +516,7 @@ export class TSHelper {
509516
510517 } else if ( ts . isArrayLiteralExpression ( expression . parent ) ) {
511518 // Expression in an array literal
512- const arrayType = this . inferAssignedType ( expression . parent , checker ) ;
519+ const arrayType = this . inferAssignedType ( expression . parent , checker , program ) ;
513520 if ( ts . isTupleTypeNode ( checker . typeToTypeNode ( arrayType ) ) ) {
514521 // Tuples
515522 const i = expression . parent . elements . indexOf ( expression ) ;
@@ -530,7 +537,7 @@ export class TSHelper {
530537 return checker . getTypeAtLocation ( expression . parent . left ) ;
531538 } else {
532539 // Other binary expressions
533- return TSHelper . inferAssignedType ( expression . parent , checker ) ;
540+ return TSHelper . inferAssignedType ( expression . parent , checker , program ) ;
534541 }
535542
536543 } else if ( ts . isAssertionExpression ( expression . parent ) ) {
@@ -550,7 +557,8 @@ export class TSHelper {
550557
551558 public static getSignatureDeclarations (
552559 signatures : ReadonlyArray < ts . Signature > ,
553- checker : ts . TypeChecker
560+ checker : ts . TypeChecker ,
561+ program : ts . Program
554562 ) : ts . SignatureDeclaration [ ]
555563 {
556564 const signatureDeclarations : ts . SignatureDeclaration [ ] = [ ] ;
@@ -560,7 +568,7 @@ export class TSHelper {
560568 && ! TSHelper . getExplicitThisParameter ( signatureDeclaration ) )
561569 {
562570 // Infer type of function expressions/arrow functions
563- const inferredType = TSHelper . inferAssignedType ( signatureDeclaration , checker ) ;
571+ const inferredType = TSHelper . inferAssignedType ( signatureDeclaration , checker , program ) ;
564572 if ( inferredType ) {
565573 const inferredSignatures = TSHelper . getAllCallSignatures ( inferredType ) ;
566574 if ( inferredSignatures . length > 0 ) {
@@ -650,20 +658,22 @@ export class TSHelper {
650658 return contexts . reduce ( reducer , ContextType . None ) ;
651659 }
652660
653- public static getFunctionContextType ( type : ts . Type , checker : ts . TypeChecker ) : ContextType {
661+ public static getFunctionContextType ( type : ts . Type , checker : ts . TypeChecker , program : ts . Program ) : ContextType {
654662 if ( type . isTypeParameter ( ) ) {
655663 type = type . getConstraint ( ) || type ;
656664 }
657665
658666 if ( type . isUnion ( ) ) {
659- return TSHelper . reduceContextTypes ( type . types . map ( t => TSHelper . getFunctionContextType ( t , checker ) ) ) ;
667+ return TSHelper . reduceContextTypes (
668+ type . types . map ( t => TSHelper . getFunctionContextType ( t , checker , program ) )
669+ ) ;
660670 }
661671
662672 const signatures = checker . getSignaturesOfType ( type , ts . SignatureKind . Call ) ;
663673 if ( signatures . length === 0 ) {
664674 return ContextType . None ;
665675 }
666- const signatureDeclarations = TSHelper . getSignatureDeclarations ( signatures , checker ) ;
676+ const signatureDeclarations = TSHelper . getSignatureDeclarations ( signatures , checker , program ) ;
667677 return TSHelper . reduceContextTypes (
668678 signatureDeclarations . map ( s => TSHelper . getDeclarationContextType ( s , checker ) ) ) ;
669679 }
0 commit comments