@@ -1033,6 +1033,90 @@ export function getOriginalOrResolvedTypeReferenceFileName(result: ResolvedTypeR
1033
1033
( result . resolvedTypeReferenceDirective . originalPath || result . resolvedTypeReferenceDirective . resolvedFileName ) ;
1034
1034
}
1035
1035
1036
+ /** @internal */
1037
+ export function createPerNonRelativeNameCache < T > (
1038
+ currentDirectory : string ,
1039
+ getCanonicalFileName : ( s : string ) => string ,
1040
+ getResolvedFileName : ( result : T ) => string | undefined ,
1041
+ ) : PerNonRelativeNameCache < T > {
1042
+ const directoryPathMap = new Map < Path , T > ( ) ;
1043
+
1044
+ return { get, set, getWithPath, setWithPath } ;
1045
+
1046
+ function get ( directory : string ) : T | undefined {
1047
+ return getWithPath ( toPath ( directory , currentDirectory , getCanonicalFileName ) ) ;
1048
+ }
1049
+
1050
+ function set ( directory : string , result : T ) : void {
1051
+ return setWithPath ( toPath ( directory , currentDirectory , getCanonicalFileName ) , result , noop ) ;
1052
+ }
1053
+
1054
+ function getWithPath ( directory : Path ) : T | undefined {
1055
+ return directoryPathMap . get ( directory ) ;
1056
+ }
1057
+
1058
+ /**
1059
+ * At first this function add entry directory -> module resolution result to the table.
1060
+ * Then it computes the set of parent folders for 'directory' that should have the same module resolution result
1061
+ * and for every parent folder in set it adds entry: parent -> module resolution. .
1062
+ * Lets say we first directory name: /a/b/c/d/e and resolution result is: /a/b/bar.ts.
1063
+ * Set of parent folders that should have the same result will be:
1064
+ * [
1065
+ * /a/b/c/d, /a/b/c, /a/b
1066
+ * ]
1067
+ * this means that request for module resolution from file in any of these folder will be immediately found in cache.
1068
+ */
1069
+ function setWithPath ( path : Path , result : T , ancestoryWorker : ( directory : Path ) => void ) : void {
1070
+ // if entry is already in cache do nothing
1071
+ if ( directoryPathMap . has ( path ) ) return ;
1072
+ directoryPathMap . set ( path , result ) ;
1073
+
1074
+ const resolvedFileName = getResolvedFileName ( result ) ;
1075
+ // find common prefix between directory and resolved file name
1076
+ // this common prefix should be the shortest path that has the same resolution
1077
+ // directory: /a/b/c/d/e
1078
+ // resolvedFileName: /a/b/foo.d.ts
1079
+ // commonPrefix: /a/b
1080
+ // for failed lookups cache the result for every directory up to root
1081
+ const commonPrefix = resolvedFileName && getCommonPrefix ( path , resolvedFileName ) ;
1082
+ let current = path ;
1083
+ while ( current !== commonPrefix ) {
1084
+ const parent = getDirectoryPath ( current ) ;
1085
+ if ( parent === current ) break ;
1086
+ if ( directoryPathMap . has ( parent ) ) {
1087
+ ancestoryWorker ( parent ) ;
1088
+ break ;
1089
+ }
1090
+ directoryPathMap . set ( parent , result ) ;
1091
+ ancestoryWorker ( parent ) ;
1092
+ current = parent ;
1093
+ }
1094
+ }
1095
+
1096
+ function getCommonPrefix ( directory : Path , resolution : string ) {
1097
+ const resolutionDirectory = toPath ( getDirectoryPath ( resolution ) , currentDirectory , getCanonicalFileName ) ;
1098
+
1099
+ // find first position where directory and resolution differs
1100
+ let i = 0 ;
1101
+ const limit = Math . min ( directory . length , resolutionDirectory . length ) ;
1102
+ while ( i < limit && directory . charCodeAt ( i ) === resolutionDirectory . charCodeAt ( i ) ) {
1103
+ i ++ ;
1104
+ }
1105
+ if ( i === directory . length && ( resolutionDirectory . length === i || resolutionDirectory [ i ] === directorySeparator ) ) {
1106
+ return directory ;
1107
+ }
1108
+ const rootLength = getRootLength ( directory ) ;
1109
+ if ( i < rootLength ) {
1110
+ return undefined ;
1111
+ }
1112
+ const sep = directory . lastIndexOf (
10000
directorySeparator , i - 1 ) ;
1113
+ if ( sep === - 1 ) {
1114
+ return undefined ;
1115
+ }
1116
+ return directory . substr ( 0 , Math . max ( sep , rootLength ) ) ;
1117
+ }
1118
+ }
1119
+
1036
1120
function createNonRelativeNameResolutionCache < T > (
1037
1121
currentDirectory : string ,
1038
1122
getCanonicalFileName : ( s : string ) => string ,
@@ -1079,82 +1163,7 @@ function createNonRelativeNameResolutionCache<T>(
1079
1163
}
1080
1164
1081
1165
function createPerModuleNameCache ( ) : PerNonRelativeNameCache < T > {
1082
- const directoryPathMap = new Map < Path , T > ( ) ;
1083
-
1084
- return { get, set, getWithPath, setWithPath } ;
1085
-
1086
- function get ( directory : string ) : T | undefined {
1087
- return getWithPath ( toPath ( directory , currentDirectory , getCanonicalFileName ) ) ;
1088
- }
1089
-
1090
- function set ( directory : string , result : T ) : void {
1091
- return setWithPath ( toPath ( directory , currentDirectory , getCanonicalFileName ) , result , noop ) ;
1092
- }
1093
-
1094
- function getWithPath ( directory : Path ) : T | undefined {
1095
- return directoryPathMap . get ( directory ) ;
1096
- }
1097
-
1098
- /**
1099
- * At first this function add entry directory -> module resolution result to the table.
1100
- * Then it computes the set of parent folders for 'directory' that should have the same module resolution result
1101
- * and for every parent folder in set it adds entry: parent -> module resolution. .
1102
- * Lets say we first directory name: /a/b/c/d/e and resolution result is: /a/b/bar.ts.
1103
- * Set of parent folders that should have the same result will be:
1104
- * [
1105
- * /a/b/c/d, /a/b/c, /a/b
1106
- * ]
1107
- * this means that request for module resolution from file in any of these folder will be immediately found in cache.
1108
- */
1109
- function setWithPath ( path : Path , result : T , ancestoryWorker : ( directory : Path ) => void ) : void {
1110
- // if entry is already in cache do nothing
1111
- if ( directoryPathMap . has ( path ) ) return ;
1112
- directoryPathMap . set ( path , result ) ;
1113
-
1114
- const resolvedFileName = getResolvedFileName ( result ) ;
1115
- // find common prefix between directory and resolved file name
1116
- // this common prefix should be the shortest path that has the same resolution
1117
- // directory: /a/b/c/d/e
1118
- // resolvedFileName: /a/b/foo.d.ts
1119
- // commonPrefix: /a/b
1120
- // for failed lookups cache the result for every directory up to root
1121
- const commonPrefix = resolvedFileName && getCommonPrefix ( path , resolvedFileName ) ;
1122
- let current = path ;
1123
- while ( current !== commonPrefix ) {
1124
- const parent = getDirectoryPath ( current ) ;
1125
- if ( parent === current ) break ;
1126
- if ( directoryPathMap . has ( parent ) ) {
1127
- ancestoryWorker ( parent ) ;
1128
- break ;
1129
- }
1130
- directoryPathMap . set ( parent , result ) ;
1131
- ancestoryWorker ( parent ) ;
1132
- current = parent ;
1133
- }
1134
- }
1135
-
1136
- function getCommonPrefix ( directory : Path , resolution : string ) {
1137
- const resolutionDirectory = toPath ( getDirectoryPath ( resolution ) , currentDirectory , getCanonicalFileName ) ;
1138
-
1139
- // find first position where directory and resolution differs
1140
- let i = 0 ;
1141
- const limit = Math . min ( directory . length , resolutionDirectory . length ) ;
1142
- while ( i < limit && directory . charCodeAt ( i ) === resolutionDirectory . charCodeAt ( i ) ) {
1143
- i ++ ;
1144
- }
1145
- if ( i === directory . length && ( resolutionDirectory . length === i || resolutionDirectory [ i ] === directorySeparator ) ) {
1146
- return directory ;
1147
- }
1148
- const rootLength = getRootLength ( directory ) ;
1149
- if ( i < rootLength ) {
1150
- return undefined ;
1151
- }
1152
- const sep = directory . lastIndexOf ( directorySeparator , i - 1 ) ;
1153
- if ( sep === - 1 ) {
1154
- return undefined ;
1155
- }
1156
- return directory . substr ( 0 , Math . max ( sep , rootLength ) ) ;
1157
- }
1166
+ return createPerNonRelativeNameCache ( currentDirectory , getCanonicalFileName , getResolvedFileName ) ;
1158
1167
}
1159
1168
}
1160
1169
0 commit comments