@@ -191,6 +191,11 @@ namespace ts {
191191
192192 const typeReferenceExtensions = [ ".d.ts" ] ;
193193
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+ */
194199 export function resolveTypeReferenceDirective ( typeReferenceDirectiveName : string , containingFile : string , options : CompilerOptions , host : ModuleResolutionHost ) : ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
195200 const traceEnabled = isTraceEnabled ( options , host ) ;
196201 const moduleResolutionState : ModuleResolutionState = {
@@ -204,11 +209,21 @@ namespace ts {
204209 const rootDir = options . typesRoot || ( options . configFilePath ? getDirectoryPath ( options . configFilePath ) : undefined ) ;
205210
206211 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+ }
209219 }
210220 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+ }
212227 }
213228 }
214229
@@ -244,17 +259,33 @@ namespace ts {
244259 }
245260 }
246261
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 ) ;
249266 }
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 ) ;
255275 }
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 ) ;
258289 }
259290 }
260291 return {
@@ -927,24 +958,15 @@ namespace ts {
927958 // used to track cases when two file names differ only in casing
928959 const filesByNameIgnoreCase = host . useCaseSensitiveFileNames ( ) ? createFileMap < SourceFile > ( fileName => fileName . toLowerCase ( ) ) : undefined ;
929960
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+ }
944968 }
945- }
946969
947- if ( ! tryReuseStructureFromOldProgram ( ) ) {
948970 forEach ( rootNames , name => processRootFile ( name , /*isDefaultLib*/ false ) ) ;
949971 // Do not process the default library if:
950972 // - The '--noLib' flag is used.
@@ -1036,6 +1058,21 @@ namespace ts {
10361058 return false ;
10371059 }
10381060
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+
10391076 Debug . assert ( ! oldProgram . structureIsReused ) ;
10401077
10411078 // there is an old program, check if we can reuse its structure
@@ -1044,6 +1081,10 @@ namespace ts {
10441081 return false ;
10451082 }
10461083
1084+ if ( ! arrayIsEqualTo ( options . types , oldOptions . types ) ) {
1085+ return false ;
1086+ }
1087+
10471088 // check if program source files has changed in the way that can affect structure of the program
10481089 const newSourceFiles : SourceFile [ ] = [ ] ;
10491090 const filePaths : Path [ ] = [ ] ;
@@ -1733,45 +1774,61 @@ namespace ts {
17331774 const resolvedTypeReferenceDirective = resolutions [ i ] ;
17341775 // store resolved type directive on the file
17351776 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 ) ;
17401794 }
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 ;
17461810 }
17471811 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 ) ;
17661814 }
17671815 }
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+ }
17711820
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 ) ;
17751832 }
17761833 }
17771834
0 commit comments