@@ -15,6 +15,10 @@ import {
15
15
isClassMethod ,
16
16
isSourceFileOfPseudoModuleType ,
17
17
isSourceFileOfTypeScriptLib ,
18
+ getSymbolModuleDeclaration ,
19
+ isGlobalThis ,
20
+ extractNamespace ,
21
+ extractSapUiNamespace ,
18
22
} from "./utils/utils.js" ;
19
23
import { taskStart } from "../../utils/perf.js" ;
20
24
import { getPositionsForNode } from "../../utils/nodePosition.js" ;
@@ -665,7 +669,7 @@ export default class SourceFileLinter {
665
669
}
666
670
const classType = this . checker . getTypeAtLocation ( node . expression ) ;
667
671
668
- const moduleDeclaration = this . getSymbolModuleDeclaration ( nodeType . symbol ) ;
672
+ const moduleDeclaration = getSymbolModuleDeclaration ( nodeType . symbol ) ;
669
673
if ( moduleDeclaration ?. name . text === "sap/ui/core/routing/Router" ) {
670
674
this . #analyzeNewCoreRouter( node ) ;
671
675
} else if ( moduleDeclaration ?. name . text === "sap/ui/model/odata/v4/ODataModel" ) {
@@ -727,47 +731,6 @@ export default class SourceFileLinter {
727
731
} ) ;
728
732
}
729
733
730
- extractNamespace ( node : ts . PropertyAccessExpression | ts . ElementAccessExpression | ts . CallExpression ) : string {
731
- const propAccessChain : string [ ] = [ ] ;
732
- propAccessChain . push ( node . expression . getText ( ) ) ;
733
-
734
- let scanNode : ts . Node = node ;
735
- while ( ts . isPropertyAccessExpression ( scanNode ) ) {
736
- if ( ! ts . isIdentifier ( scanNode . name ) ) {
737
- throw new Error (
738
- `Unexpected PropertyAccessExpression node: Expected name to be identifier but got ` +
739
- ts . SyntaxKind [ scanNode . name . kind ] ) ;
740
- }
741
- propAccessChain . push ( scanNode . name . text ) ;
742
- scanNode = scanNode . parent ;
743
- }
744
- return propAccessChain . join ( "." ) ;
745
- }
746
-
747
- /**
748
- * Extracts the sap.ui API namespace from a symbol name and a module declaration
749
- * (from @sapui5/types sap.ui.core.d.ts), e.g. sap.ui.view.
750
- */
751
- extractSapUiNamespace ( symbolName : string , moduleDeclaration : ts . ModuleDeclaration ) : string | undefined {
752
- const namespace : string [ ] = [ ] ;
753
- let currentModuleDeclaration : ts . Node | undefined = moduleDeclaration ;
754
- while (
755
- currentModuleDeclaration &&
756
- ts . isModuleDeclaration ( currentModuleDeclaration ) &&
757
- currentModuleDeclaration . flags & ts . NodeFlags . Namespace
758
- ) {
759
- namespace . unshift ( currentModuleDeclaration . name . text ) ;
760
- currentModuleDeclaration = currentModuleDeclaration . parent ?. parent ;
761
- }
762
-
763
- if ( ! namespace . length ) {
764
- return undefined ;
765
- } else {
766
- namespace . push ( symbolName ) ;
767
- return namespace . join ( "." ) ;
768
- }
769
- }
770
-
771
734
getDeprecationText ( deprecatedTag : ts . JSDocTagInfo ) : string {
772
735
// (Workaround) There's an issue in some UI5 TS definition versions and where the
773
736
// deprecation text gets merged with the description. Splitting on double
@@ -822,14 +785,14 @@ export default class SourceFileLinter {
822
785
throw new Error ( `Unhandled CallExpression expression syntax: ${ ts . SyntaxKind [ exprNode . kind ] } ` ) ;
823
786
}
824
787
825
- const moduleDeclaration = this . getSymbolModuleDeclaration ( exprType . symbol ) ;
788
+ const moduleDeclaration = getSymbolModuleDeclaration ( exprType . symbol ) ;
826
789
let globalApiName ;
827
790
828
791
if ( exprType . symbol && moduleDeclaration ) {
829
792
const symbolName = exprType . symbol . getName ( ) ;
830
793
const moduleName = moduleDeclaration . name . text ;
831
794
const nodeType = this . checker . getTypeAtLocation ( node ) ;
832
- globalApiName = this . extractSapUiNamespace ( symbolName , moduleDeclaration ) ;
795
+ globalApiName = extractSapUiNamespace ( symbolName , moduleDeclaration ) ;
833
796
834
797
if ( symbolName === "init" && moduleName === "sap/ui/core/Lib" ) {
835
798
// Check for sap/ui/core/Lib.init usages
@@ -919,7 +882,7 @@ export default class SourceFileLinter {
919
882
additionalMessage = `of module '${ this . checker . typeToString ( lhsExprType ) } '` ;
920
883
} else if ( ts . isPropertyAccessExpression ( exprNode ) ) {
921
884
// left-hand-side is a module or namespace, e.g. "module.deprecatedMethod()"
922
- additionalMessage = `(${ this . extractNamespace ( exprNode ) } )` ;
885
+ additionalMessage = `(${ extractNamespace ( exprNode ) } )` ;
923
886
}
924
887
} else if ( globalApiName ) {
925
888
additionalMessage = `(${ globalApiName } )` ;
@@ -952,14 +915,6 @@ export default class SourceFileLinter {
952
915
}
953
916
}
954
917
955
- getSymbolModuleDeclaration ( symbol : ts . Symbol ) {
956
- let parent = symbol . valueDeclaration ?. parent ;
957
- while ( parent && ! ts . isModuleDeclaration ( parent ) ) {
958
- parent = parent . parent ;
959
- }
960
- return parent ;
961
- }
962
-
963
918
#analyzeLibInitCall(
964
919
node : ts . CallExpression ,
965
920
exprNode : ts . CallExpression | ts . ElementAccessExpression | ts . PropertyAccessExpression | ts . Identifier ) {
@@ -1384,7 +1339,7 @@ export default class SourceFileLinter {
1384
1339
*/
1385
1340
#isPropertyBinding( node : ts . NewExpression | ts . CallExpression , propNames : string [ ] ) {
1386
1341
const controlAmbientModule =
1387
- this . getSymbolModuleDeclaration ( this . checker . getTypeAtLocation ( node ) . symbol ) ;
1342
+ getSymbolModuleDeclaration ( this . checker . getTypeAtLocation ( node ) . symbol ) ;
1388
1343
1389
1344
let classArg ;
1390
1345
if ( controlAmbientModule ?. body && ts . isModuleBlock ( controlAmbientModule . body ) ) {
@@ -1446,7 +1401,7 @@ export default class SourceFileLinter {
1446
1401
}
1447
1402
let namespace ;
1448
1403
if ( ts . isPropertyAccessExpression ( node ) ) {
1449
- namespace = this . extractNamespace ( node ) ;
1404
+ namespace = extractNamespace ( node ) ;
1450
1405
}
1451
1406
if ( this . isSymbolOfJquerySapType ( deprecationInfo . symbol ) ) {
1452
1407
const fixHints = this . getJquerySapFixHints ( node ) ;
@@ -1482,14 +1437,6 @@ export default class SourceFileLinter {
1482
1437
}
1483
1438
}
1484
1439
1485
- isGlobalThis ( nodeType : string ) {
1486
- return [
1487
- "Window & typeof globalThis" ,
1488
- "typeof globalThis" ,
1489
- // "Window", // top and parent will resolve to this string, however they are still treated as type 'any'
1490
- ] . includes ( nodeType ) ;
1491
- }
1492
-
1493
1440
analyzeExportedValuesByLib ( node : ts . PropertyAccessExpression | ts . ElementAccessExpression ) {
1494
1441
if ( ! ts . isElementAccessExpression ( node ) &&
1495
1442
node . name ?. kind !== ts . SyntaxKind . Identifier ) {
@@ -1592,7 +1539,7 @@ export default class SourceFileLinter {
1592
1539
1593
1540
// Get the NodeType in order to check whether this is indirect global access via Window
1594
1541
const nodeType = this . checker . getTypeAtLocation ( exprNode ) ;
1595
- if ( this . isGlobalThis ( this . checker . typeToString ( nodeType ) ) ) {
1542
+ if ( isGlobalThis ( this . checker . typeToString ( nodeType ) ) ) {
1596
1543
// In case of Indirect global access we need to check for
1597
1544
// a global UI5 variable on the right side of the expression instead of left
1598
1545
if ( ts . isPropertyAccessExpression ( node ) ) {
@@ -1613,7 +1560,7 @@ export default class SourceFileLinter {
1613
1560
if ( symbol && this . isSymbolOfUi5OrThirdPartyType ( symbol ) &&
1614
1561
! ( ( ts . isPropertyAccessExpression ( node ) || ts . isElementAccessExpression ( node ) ) &&
1615
1562
this . isAllowedPropertyAccess ( node ) ) ) {
1616
- const namespace = this . extractNamespace ( ( node as ts . PropertyAccessExpression ) ) ;
1563
+ const namespace = extractNamespace ( ( node as ts . PropertyAccessExpression ) ) ;
1617
1564
this . #reporter. addMessage ( MESSAGE . NO_GLOBALS , {
1618
1565
variableName : symbol . getName ( ) ,
1619
1566
namespace,
@@ -1632,7 +1579,7 @@ export default class SourceFileLinter {
1632
1579
return true ;
1633
1580
}
1634
1581
1635
- const propAccess = this . extractNamespace ( node ) ;
1582
+ const propAccess = extractNamespace ( node ) ;
1636
1583
return [
1637
1584
"sap.ui.define" ,
1638
1585
"sap.ui.require" ,
0 commit comments