@@ -697,6 +697,8 @@ namespace ts {
697
697
let program : Program ;
698
698
let files : SourceFile [ ] = [ ] ;
699
699
let fileProcessingDiagnostics = createDiagnosticCollection ( ) ;
700
+ const resolvedLibraries : Map < ResolvedLibrary > = { } ;
701
+ const libraryRoot = options . rootDir || options . configFilePath || computeCommonSourceDirectoryOfFilenames ( rootNames ) ;
700
702
const programDiagnostics = createDiagnosticCollection ( ) ;
701
703
702
704
let commonSourceDirectory : string ;
@@ -1489,11 +1491,9 @@ namespace ts {
1489
1491
skipDefaultLib = skipDefaultLib || file . hasNoDefaultLib ;
1490
1492
1491
1493
const basePath = getDirectoryPath ( fileName ) ;
1492
- const libraryBasePath = options . rootDir || options . configFilePath || getDirectoryPath ( file . fileName ) ;
1493
1494
if ( ! options . noResolve ) {
1494
1495
processReferencedFiles ( file , basePath ) ;
1495
-
1496
- processReferencedLibraries ( file , libraryBasePath ) ;
1496
+ processReferencedLibraries ( file , libraryRoot ) ;
1497
1497
}
1498
1498
1499
1499
// always process imported modules to record module name resolutions
@@ -1517,41 +1517,90 @@ namespace ts {
1517
1517
} ) ;
1518
1518
}
1519
1519
1520
+ function findLibraryDefinition ( searchPath : string ) {
1521
+ let typingFilename = "index.d.ts" ;
1522
+ const packageJsonPath = combinePaths ( searchPath , "package.json" ) ;
1523
+ if ( host . fileExists ( packageJsonPath ) ) {
1524
+ let package : { typings ?: string } = { } ;
1525
+ try {
1526
+ package = JSON . parse ( host . readFile ( packageJsonPath ) ) ;
1527
+ } catch ( e ) { }
1528
+
1529
+ if ( package . typings ) {
1530
+ typingFilename = package . typings ;
1531
+ }
1532
+ }
1533
+
1534
+ const combinedPath = normalizePath ( combinePaths ( searchPath , typingFilename ) ) ;
1535
+ return host . fileExists ( combinedPath ) ? combinedPath : undefined ;
1536
+ }
1537
+
1520
1538
function processReferencedLibraries ( file : SourceFile , compilationRoot : string ) {
1521
- const searchPaths = getEffectiveLibrarySearchPaths ( ) ;
1539
+ const primarySearchPaths = map ( getEffectiveLibraryPrimarySearchPaths ( ) , path => combinePaths ( compilationRoot , path ) ) ;
1540
+
1541
+ const failedSearchPaths : string [ ] = [ ] ;
1542
+ const moduleResolutionState : ModuleResolutionState = {
1543
+ compilerOptions : options ,
1544
+ host : host ,
1545
+ skipTsx : true ,
1546
+ traceEnabled : false
1547
+ } ;
1548
+
1522
1549
for ( const ref of file . referencedLibraries ) {
1550
+ // If we already found this library as a primary reference, or failed to find it, nothing to do
1551
+ const previousResolution = resolvedLibraries [ ref . fileName ] ;
1552
+ if ( previousResolution && ( previousResolution . primary || ( previousResolution . resolvedFileName === undefined ) ) ) {
1553
+ continue ;
1554
+ }
1555
+
1523
1556
let foundIt = false ;
1524
1557
1525
- for ( const path of searchPaths ) {
1526
- let typingFilename = "index.d.ts" ;
1527
- const searchPath = combinePaths ( combinePaths ( compilationRoot , path ) , ref . fileName ) ;
1528
- const packageJsonPath = combinePaths ( searchPath , "package.json" ) ;
1529
- console . log ( 'Check for ' + packageJsonPath ) ;
1530
- if ( host . fileExists ( packageJsonPath ) ) {
1531
- let package : { typings ?: string } = { } ;
1532
- try {
1533
- package = JSON . parse ( host . readFile ( packageJsonPath ) ) ;
1534
- } catch ( e ) { }
1535
-
1536
- if ( package . typings ) {
1537
- typingFilename = package . typings ;
1538
- }
1558
+ // Check primary library paths
1559
+ for ( const primaryPath of primarySearchPaths ) {
1560
+ const searchPath = combinePaths ( primaryPath , ref . fileName ) ;
1561
+ const resolvedFile = findLibraryDefinition ( searchPath ) ;
1562
+ if ( resolvedFile ) {
1563
+ processSourceFile ( resolvedFile , /*isDefaultLib*/ false , /*isReference*/ true , file , ref . pos , ref . end ) ;
1564
+ resolvedLibraries [ ref . fileName ] = { primary : true , resolvedFileName : resolvedFile } ;
1565
+ foundIt = true ;
1566
+ break ;
1539
1567
}
1568
+ }
1540
1569
1541
- const combinedPath = normalizePath ( combinePaths ( compilationRoot , combinePaths ( combinePaths ( path , ref . fileName ) , typingFilename ) ) ) ;
1542
- if ( host . fileExists ( combinedPath ) ) {
1543
- processSourceFile ( combinedPath , /*isDefaultLib*/ false , /*isReference*/ true , file , ref . pos , ref . end ) ;
1570
+ // Check secondary library paths
1571
+ if ( ! foundIt ) {
1572
+ const secondaryResult = loadModuleFromNodeModules ( ref . fileName , file . fileName , failedSearchPaths , moduleResolutionState ) ;
1573
+ if ( secondaryResult ) {
1544
1574
foundIt = true ;
1545
- break ;
1575
+ // If we already resolved to this file, it must have been a secondary reference. Check file contents
1576
+ // for sameness and possibly issue an error
1577
+ if ( previousResolution ) {
1578
+ const otherFileText = host . readFile ( secondaryResult ) ;
1579
+ if ( otherFileText !== getSourceFile ( previousResolution . resolvedFileName ) . text ) {
1580
+ fileProcessingDiagnostics . add ( createFileDiagnostic ( file , ref . pos , ref . end - ref . pos ,
1581
+ Diagnostics . Conflicting_library_definitions_for_0_found_at_1_and_2_Copy_the_correct_file_to_a_local_typings_folder_to_resolve_this_conflict ,
1582
+ ref . fileName ,
1583
+ secondaryResult ,
1584
+ previousResolution . resolvedFileName ) ) ;
1585
+ }
1586
+ }
1587
+ else {
1588
+ // First resolution of this library
1589
+ processSourceFile ( secondaryResult , /*isDefaultLib*/ false , /*isReference*/ true , file , ref . pos , ref . end ) ;
1590
+ resolvedLibraries [ ref . fileName ] = { primary : false , resolvedFileName : secondaryResult } ;
1591
+ }
1546
1592
}
1547
1593
}
1594
+
1548
1595
if ( ! foundIt ) {
1549
1596
fileProcessingDiagnostics . add ( createFileDiagnostic ( file , ref . pos , ref . end - ref . pos , Diagnostics . Cannot_find_name_0 , ref . fileName ) ) ;
1597
+ // Create an entry as a primary lookup result so we don't keep doing this
1598
+ resolvedLibraries [ ref . fileName ] = { primary : true , resolvedFileName : undefined } ;
1550
1599
}
1551
1600
}
1552
1601
}
1553
1602
1554
- function getEffectiveLibrarySearchPaths ( ) {
1603
+ function getEffectiveLibraryPrimarySearchPaths ( ) {
1555
1604
return options . librarySearchPaths ||
1556
1605
( options . configFilePath ?
1557
1606
[ options . configFilePath ] . concat ( defaultLibrarySearchPaths ) :
@@ -1604,15 +1653,11 @@ namespace ts {
1604
1653
return ;
1605
1654
}
1606
1655
1607
- function computeCommonSourceDirectory ( sourceFiles : SourceFile [ ] ) : string {
1656
+ function computeCommonSourceDirectoryOfFilenames ( fileNames : string [ ] ) : string {
1608
1657
let commonPathComponents : string [ ] ;
1609
- const failed = forEach ( files , sourceFile => {
1658
+ const failed = forEach ( fileNames , sourceFile => {
1610
1659
// Each file contributes into common source file path
1611
- if ( isDeclarationFile ( sourceFile ) ) {
1612
- return ;
1613
- }
1614
-
1615
- const sourcePathComponents = getNormalizedPathComponents ( sourceFile . fileName , currentDirectory ) ;
1660
+ const sourcePathComponents = getNormalizedPathComponents ( sourceFile , currentDirectory ) ;
1616
1661
sourcePathComponents . pop ( ) ; // The base file name is not part of the common directory path
1617
1662
1618
1663
if ( ! commonPathComponents ) {
@@ -1652,6 +1697,16 @@ namespace ts {
1652
1697
return getNormalizedPathFromPathComponents ( commonPathComponents ) ;
1653
1698
}
1654
1699
1700
+ function computeCommonSourceDirectory ( sourceFiles : SourceFile [ ] ) : string {
1701
+ const fileNames : string [ ] = [ ] ;
1702
+ for ( const file of sourceFiles ) {
1703
+ if ( ! file . isDeclarationFile ) {
1704
+ fileNames . push ( file . fileName ) ;
1705
+ }
1706
+ }
1707
+ return computeCommonSourceDirectoryOfFilenames ( fileNames ) ;
1708
+ }
1709
+
1655
1710
function checkSourceFilesBelongToPath ( sourceFiles : SourceFile [ ] , rootDirectory : string ) : boolean {
1656
1711
let allFilesBelongToPath = true ;
1657
1712
if ( sourceFiles ) {
0 commit comments