@@ -191,6 +191,11 @@ namespace ts {
191
191
192
192
const typeReferenceExtensions = [ ".d.ts" ] ;
193
193
194
+ /**
195
+ * @param {string | undefined } containingFile - file that contains type reference directive, can be undefined if containing file is unknown.
196
+ * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups
197
+ * is assumed to be the same as root directory of the project.
198
+ */
194
199
export function resolveTypeReferenceDirective ( typeReferenceDirectiveName : string , containingFile : string , options : CompilerOptions , host : ModuleResolutionHost ) : ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
195
200
const traceEnabled = isTraceEnabled ( options , host ) ;
196
201
const moduleResolutionState : ModuleResolutionState = {
@@ -204,11 +209,21 @@ namespace ts {
204
209
const rootDir = options . typesRoot || ( options . configFilePath ? getDirectoryPath ( options . configFilePath ) : undefined ) ;
205
210
206
211
if ( traceEnabled ) {
207
- if ( rootDir !== undefined ) {
208
- trace ( host , Diagnostics . Resolving_type_reference_directive_0_from_1_root_dir_2 , typeReferenceDirectiveName , containingFile , rootDir ) ;
212
+ if ( containingFile === undefined ) {
213
+ if ( rootDir === undefined ) {
214
+ trace ( host , Diagnostics . Resolving_type_reference_directive_0_containing_file_not_set_root_directory_not_set , typeReferenceDirectiveName ) ;
215
+ }
216
+ else {
217
+ trace ( host , Diagnostics . Resolving_type_reference_directive_0_containing_file_not_set_root_directory_1 , typeReferenceDirectiveName , rootDir ) ;
218
+ }
209
219
}
210
220
else {
211
- trace ( host , Diagnostics . Resolving_type_reference_directive_0_from_1_root_dir_not_set , typeReferenceDirectiveName , containingFile ) ;
221
+ if ( rootDir === undefined ) {
222
+ trace ( host , Diagnostics . Resolving_type_reference_directive_0_containing_file_1_root_directory_not_set , typeReferenceDirectiveName , containingFile ) ;
223
+ }
224
+ else {
225
+ trace ( host , Diagnostics . Resolving_type_reference_directive_0_containing_file_1_root_directory_2 , typeReferenceDirectiveName , containingFile , rootDir ) ;
226
+ }
212
227
}
213
228
}
214
229
@@ -244,17 +259,33 @@ namespace ts {
244
259
}
245
260
}
246
261
247
- if ( traceEnabled ) {
248
- trace ( host , Diagnostics . Resolving_from_node_modules_folder ) ;
262
+ let resolvedFile : string ;
263
+ let initialLocationForSecondaryLookup : string ;
264
+ if ( containingFile ) {
265
+ initialLocationForSecondaryLookup = getDirectoryPath ( containingFile ) ;
249
266
}
250
- // check secondary locations
251
- const resolvedFile = loadModuleFromNodeModules ( typeReferenceDirectiveName , getDirectoryPath ( containingFile ) , failedLookupLocations , moduleResolutionState ) ;
252
- if ( traceEnabled ) {
253
- if ( resolvedFile ) {
254
- trace ( host , Diagnostics . Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2 , typeReferenceDirectiveName , resolvedFile , false ) ;
267
+ else {
268
+ initialLocationForSecondaryLookup = rootDir ;
269
+ }
270
+
271
+ if ( initialLocationForSecondaryLookup !== undefined ) {
272
+ // check secondary locations
273
+ if ( traceEnabled ) {
274
+ trace ( host , Diagnostics . Looking_up_in_node_modules_folder_initial_location_0 , initialLocationForSecondaryLookup ) ;
255
275
}
256
- else {
257
- trace ( host , Diagnostics . Type_reference_directive_0_was_not_resolved , typeReferenceDirectiveName ) ;
276
+ resolvedFile = loadModuleFromNodeModules ( typeReferenceDirectiveName , initialLocationForSecondaryLookup , failedLookupLocations , moduleResolutionState ) ;
277
+ if ( traceEnabled ) {
278
+ if ( resolvedFile ) {
279
+ trace ( host , Diagnostics . Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2 , typeReferenceDirectiveName , resolvedFile , false ) ;
280
+ }
281
+ else {
282
+ trace ( host , Diagnostics . Type_reference_directive_0_was_not_resolved , typeReferenceDirectiveName ) ;
283
+ }
284
+ }
285
+ }
286
+ else {
287
+ if ( traceEnabled ) {
288
+ trace ( host , Diagnostics . Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder ) ;
258
289
}
259
290
}
260
291
return {
@@ -927,24 +958,15 @@ namespace ts {
927
958
// used to track cases when two file names differ only in casing
928
959
const filesByNameIgnoreCase = host . useCaseSensitiveFileNames ( ) ? createFileMap < SourceFile > ( fileName => fileName . toLowerCase ( ) ) : undefined ;
929
960
930
- if ( oldProgram ) {
931
- // check properties that can affect structure of the program or module resolution strategy
932
- // if any of these properties has changed - structure cannot be reused
933
- const oldOptions = oldProgram . getCompilerOptions ( ) ;
934
- if ( ( oldOptions . module !== options . module ) ||
935
- ( oldOptions . noResolve !== options . noResolve ) ||
936
- ( oldOptions . target !== options . target ) ||
937
- ( oldOptions . noLib !== options . noLib ) ||
938
- ( oldOptions . jsx !== options . jsx ) ||
939
- ( oldOptions . allowJs !== options . allowJs ) ||
940
- ( oldOptions . rootDir !== options . rootDir ) ||
941
- ( oldOptions . typesSearchPaths !== options . typesSearchPaths ) ||
942
- ( oldOptions . configFilePath !== options . configFilePath ) ) {
943
- oldProgram = undefined ;
961
+ if ( ! tryReuseStructureFromOldProgram ( ) ) {
962
+ // load type declarations specified via 'types' argument
963
+ if ( options . types && options . types . length ) {
964
+ const resolutions = resolveTypeReferenceDirectiveNamesWorker ( options . types , /*containingFile*/ undefined ) ;
965
+ for ( let i = 0 ; i < options . types . length ; i ++ ) {
966
+ processTypeReferenceDirective ( options . types [ i ] , resolutions [ i ] ) ;
967
+ }
944
968
}
945
- }
946
969
947
- if ( ! tryReuseStructureFromOldProgram ( ) ) {
948
970
forEach ( rootNames , name => processRootFile ( name , /*isDefaultLib*/ false ) ) ;
949
971
// Do not process the default library if:
950
972
// - The '--noLib' flag is used.
@@ -1036,6 +1058,21 @@ namespace ts {
1036
1058
return false ;
1037
1059
}
1038
1060
1061
+ // check properties that can affect structure of the program or module resolution strategy
1062
+ // if any of these properties has changed - structure cannot be reused
1063
+ const oldOptions = oldProgram . getCompilerOptions ( ) ;
1064
+ if ( ( oldOptions . module !== options . module ) ||
1065
+ ( oldOptions . noResolve !== options . noResolve ) ||
1066
+ ( oldOptions . target !== options . target ) ||
1067
+ ( oldOptions . noLib !== options . noLib ) ||
1068
+ ( oldOptions . jsx !== options . jsx ) ||
1069
+ ( oldOptions . allowJs !== options . allowJs ) ||
1070
+ ( oldOptions . rootDir !== options . rootDir ) ||
1071
+ ( oldOptions . typesSearchPaths !== options . typesSearchPaths ) ||
1072
+ ( oldOptions . configFilePath !== options . configFilePath ) ) {
1073
+ return false ;
1074
+ }
1075
+
1039
1076
Debug . assert ( ! oldProgram . structureIsReused ) ;
1040
1077
1041
1078
// there is an old program, check if we can reuse its structure
@@ -1044,6 +1081,10 @@ namespace ts {
1044
1081
return false ;
1045
1082
}
1046
1083
1084
+ if ( ! arrayIsEqualTo ( options . types , oldOptions . types ) ) {
1085
+ return false ;
1086
+ }
1087
+
1047
1088
// check if program source files has changed in the way that can affect structure of the program
1048
1089
const newSourceFiles : SourceFile [ ] = [ ] ;
1049
1090
const filePaths : Path [ ] = [ ] ;
@@ -1733,45 +1774,61 @@ namespace ts {
1733
1774
const resolvedTypeReferenceDirective = resolutions [ i ] ;
1734
1775
// store resolved type directive on the file
1735
1776
setResolvedTypeReferenceDirective ( file , ref . fileName , resolvedTypeReferenceDirective ) ;
1736
- // If we already found this library as a primary reference - nothing to do
1737
- const previousResolution = resolvedTypeReferenceDirectives [ ref . fileName ] ;
1738
- if ( previousResolution && previousResolution . primary ) {
1739
- continue ;
1777
+ processTypeReferenceDirective ( ref . fileName , resolvedTypeReferenceDirective , file , ref . pos , ref . end ) ;
1778
+ }
1779
+ }
1780
+
1781
+ function processTypeReferenceDirective ( typeReferenceDirective : string , resolvedTypeReferenceDirective : ResolvedTypeReferenceDirective ,
1782
+ refFile ?: SourceFile , refPos ?: number , refEnd ?: number ) : void {
1783
+
1784
+ // If we already found this library as a primary reference - nothing to do
1785
+ const previousResolution = resolvedTypeReferenceDirectives [ typeReferenceDirective ] ;
1786
+ if ( previousResolution && previousResolution . primary ) {
1787
+ return ;
1788
+ }
1789
+ let saveResolution = true ;
1790
+ if ( resolvedTypeReferenceDirective ) {
1791
+ if ( resolvedTypeReferenceDirective . primary ) {
1792
+ // resolved from the primary path
1793
+ processSourceFile ( resolvedTypeReferenceDirective . resolvedFileName , /*isDefaultLib*/ false , /*isReference*/ true , refFile , refPos , refEnd ) ;
1740
1794
}
1741
- let saveResolution = true ;
1742
- if ( resolvedTypeReferenceDirective ) {
1743
- if ( resolvedTypeReferenceDirective . primary ) {
1744
- // resolved from the primary path
1745
- processSourceFile ( resolvedTypeReferenceDirective . resolvedFileName , /*isDefaultLib*/ false , /*isReference*/ true , file , ref . pos , ref . end ) ;
1795
+ else {
1796
+ // If we already resolved to this file, it must have been a secondary reference. Check file contents
1797
+ // for sameness and possibly issue an error
1798
+ if ( previousResolution ) {
1799
+ const otherFileText = host . readFile ( resolvedTypeReferenceDirective . resolvedFileName ) ;
1800
+ if ( otherFileText !== getSourceFile ( previousResolution . resolvedFileName ) . text ) {
1801
+ fileProcessingDiagnostics . add ( createDiagnostic ( refFile , refPos , refEnd ,
1802
+ Diagnostics . Conflicting_library_definitions_for_0_found_at_1_and_2_Copy_the_correct_file_to_the_typings_folder_to_resolve_this_conflict ,
1803
+ typeReferenceDirective ,
1804
+ resolvedTypeReferenceDirective . resolvedFileName ,
1805
+ previousResolution . resolvedFileName
1806
+ ) ) ;
1807
+ }
1808
+ // don't overwrite previous resolution result
1809
+ saveResolution = false ;
1746
1810
}
1747
1811
else {
1748
- // If we already resolved to this file, it must have been a secondary reference. Check file contents
1749
- // for sameness and possibly issue an error
1750
- if ( previousResolution ) {
1751
- const otherFileText = host . readFile ( resolvedTypeReferenceDirective . resolvedFileName ) ;
1752
- if ( otherFileText !== getSourceFile ( previousResolution . resolvedFileName ) . text ) {
1753
- fileProcessingDiagnostics . add ( createFileDiagnostic ( file , ref . pos , ref . end - ref . pos ,
1754
- Diagnostics . Conflicting_library_definitions_for_0_found_at_1_and_2_Copy_the_correct_file_to_the_typings_folder_to_resolve_this_conflict ,
1755
- ref . fileName ,
1756
- resolvedTypeReferenceDirective . resolvedFileName ,
1757
- previousResolution . resolvedFileName ) ) ;
1758
- }
1759
- // don't overwrite previous resolution result
1760
- saveResolution = false ;
1761
- }
1762
- else {
1763
- // First resolution of this library
1764
- processSourceFile ( resolvedTypeReferenceDirective . resolvedFileName , /*isDefaultLib*/ false , /*isReference*/ true , file , ref . pos , ref . end ) ;
1765
- }
1812
+ // First resolution of this library
1813
+ processSourceFile ( resolvedTypeReferenceDirective . resolvedFileName , /*isDefaultLib*/ false , /*isReference*/ true , refFile , refPos , refEnd ) ;
1766
1814
}
1767
1815
}
1768
- else {
1769
- fileProcessingDiagnostics . add ( createFileDiagnostic ( file , ref . pos , ref . end - ref . pos , Diagnostics . Cannot_find_name_0 , ref . fileName ) ) ;
1770
- }
1816
+ }
1817
+ else {
1818
+ fileProcessingDiagnostics . add ( createDiagnostic ( refFile , refPos , refEnd , Diagnostics . Cannot_find_name_0 , typeReferenceDirective ) ) ;
1819
+ }
1771
1820
1772
- if ( saveResolution ) {
1773
- resolvedTypeReferenceDirectives [ ref . fileName ] = resolvedTypeReferenceDirective ;
1774
- }
1821
+ if ( saveResolution ) {
1822
+ resolvedTypeReferenceDirectives [ typeReferenceDirective ] = resolvedTypeReferenceDirective ;
1823
+ }
1824
+ }
1825
+
1826
+ function createDiagnostic ( refFile : SourceFile , refPos : number , refEnd : number , message : DiagnosticMessage , ...args : any [ ] ) : Diagnostic {
1827
+ if ( refFile === undefined || refPos === undefined || refEnd === undefined ) {
1828
+ return createCompilerDiagnostic ( message , ...args ) ;
1829
+ }
1830
+ else {
1831
+ return createFileDiagnostic ( refFile , refPos , refEnd - refPos , message , ...args ) ;
1775
1832
}
1776
1833
}
1777
1834
0 commit comments