@@ -12,6 +12,12 @@ namespace ts {
12
12
13
13
const emptyArray : any [ ] = [ ] ;
14
14
15
+ const defaultLibrarySearchPaths = < Path [ ] > [
16
+ "typings/" ,
17
+ "node_modules/" ,
18
+ "node_modules/@types/" ,
19
+ ] ;
20
+
15
21
export const version = "1.9.0" ;
16
22
17
23
export function findConfigFile ( searchPath : string , fileExists : ( fileName : string ) => boolean ) : string {
@@ -371,7 +377,7 @@ namespace ts {
371
377
const traceEnabled = isTraceEnabled ( compilerOptions , host ) ;
372
378
373
379
const failedLookupLocations : string [ ] = [ ] ;
374
- const state = { compilerOptions, host, traceEnabled, skipTsx : false } ;
380
+ const state = { compilerOptions, host, traceEnabled, skipTsx : false } ;
375
381
let resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings ( moduleName , containingDirectory , nodeLoadModuleByRelativeName ,
376
382
failedLookupLocations , supportedExtensions , state ) ;
377
383
@@ -407,7 +413,7 @@ namespace ts {
407
413
}
408
414
409
415
/* @internal */
410
- export function directoryProbablyExists ( directoryName : string , host : { directoryExists ?: ( directoryName : string ) => boolean } ) : boolean {
416
+ export function directoryProbablyExists ( directoryName : string , host : { directoryExists ?: ( directoryName : string ) => boolean } ) : boolean {
411
417
// if host does not support 'directoryExists' assume that directory will exist
412
418
return ! host . directoryExists || host . directoryExists ( directoryName ) ;
413
419
}
@@ -554,7 +560,7 @@ namespace ts {
554
560
555
561
556
562
return referencedSourceFile
557
- ? { resolvedModule : { resolvedFileName : referencedSourceFile } , failedLookupLocations }
563
+ ? { resolvedModule : { resolvedFileName : referencedSourceFile } , failedLookupLocations }
558
564
: { resolvedModule : undefined , failedLookupLocations } ;
559
565
}
560
566
@@ -649,9 +655,9 @@ namespace ts {
649
655
650
656
export function getPreEmitDiagnostics ( program : Program , sourceFile ?: SourceFile , cancellationToken ?: CancellationToken ) : Diagnostic [ ] {
651
657
let diagnostics = program . getOptionsDiagnostics ( cancellationToken ) . concat (
652
- program . getSyntacticDiagnostics ( sourceFile , cancellationToken ) ,
653
- program . getGlobalDiagnostics ( cancellationToken ) ,
654
- program . getSemanticDiagnostics ( sourceFile , cancellationToken ) ) ;
658
+ program . getSyntacticDiagnostics ( sourceFile , cancellationToken ) ,
659
+ program . getGlobalDiagnostics ( cancellationToken ) ,
660
+ program . getSemanticDiagnostics ( sourceFile , cancellationToken ) ) ;
655
661
656
662
if ( program . getCompilerOptions ( ) . declaration ) {
657
663
diagnostics = diagnostics . concat ( program . getDeclarationDiagnostics ( sourceFile , cancellationToken ) ) ;
@@ -690,6 +696,14 @@ namespace ts {
690
696
let program : Program ;
691
697
let files : SourceFile [ ] = [ ] ;
692
698
let fileProcessingDiagnostics = createDiagnosticCollection ( ) ;
699
+ const currentDirectory = host . getCurrentDirectory ( ) ;
700
+ const resolvedLibraries : Map < ResolvedLibrary > = { } ;
701
+ let libraryRoot =
702
+ ( options . rootDir && ts . toPath ( options . rootDir , currentDirectory , host . getCanonicalFileName ) ) ||
703
+ ( options . configFilePath && getDirectoryPath ( getNormalizedAbsolutePath ( options . configFilePath , currentDirectory ) ) ) ;
704
+ if ( libraryRoot === undefined ) {
705
+ libraryRoot = computeCommonSourceDirectoryOfFilenames ( rootNames ) ;
706
+ }
693
707
const programDiagnostics = createDiagnosticCollection ( ) ;
694
708
695
709
let commonSourceDirectory : string ;
@@ -706,7 +720,6 @@ namespace ts {
706
720
// Map storing if there is emit blocking diagnostics for given input
707
721
const hasEmitBlockingDiagnostics = createFileMap < boolean > ( getCanonicalFileName ) ;
708
722
709
- const currentDirectory = host . getCurrentDirectory ( ) ;
710
723
const resolveModuleNamesWorker = host . resolveModuleNames
711
724
? ( ( moduleNames : string [ ] , containingFile : string ) => host . resolveModuleNames ( moduleNames , containingFile ) )
712
725
: ( ( moduleNames : string [ ] , containingFile : string ) => {
@@ -883,8 +896,8 @@ namespace ts {
883
896
const oldResolution = getResolvedModule ( oldSourceFile , moduleNames [ i ] ) ;
884
897
const resolutionChanged = oldResolution
885
898
? ! newResolution ||
886
- oldResolution . resolvedFileName !== newResolution . resolvedFileName ||
887
- ! ! oldResolution . isExternalLibraryImport !== ! ! newResolution . isExternalLibraryImport
899
+ oldResolution . resolvedFileName !== newResolution . resolvedFileName ||
900
+ ! ! oldResolution . isExternalLibraryImport !== ! ! newResolution . isExternalLibraryImport
888
901
: newResolution ;
889
902
890
903
if ( resolutionChanged ) {
@@ -1007,9 +1020,9 @@ namespace ts {
1007
1020
}
1008
1021
1009
1022
function getDiagnosticsHelper (
1010
- sourceFile : SourceFile ,
1011
- getDiagnostics : ( sourceFile : SourceFile , cancellationToken : CancellationToken ) => Diagnostic [ ] ,
1012
- cancellationToken : CancellationToken ) : Diagnostic [ ] {
1023
+ sourceFile : SourceFile ,
1024
+ getDiagnostics : ( sourceFile : SourceFile , cancellationToken : CancellationToken ) => Diagnostic [ ] ,
1025
+ cancellationToken : CancellationToken ) : Diagnostic [ ] {
1013
1026
if ( sourceFile ) {
1014
1027
return getDiagnostics ( sourceFile , cancellationToken ) ;
1015
1028
}
@@ -1484,6 +1497,7 @@ namespace ts {
1484
1497
const basePath = getDirectoryPath ( fileName ) ;
1485
1498
if ( ! options . noResolve ) {
1486
1499
processReferencedFiles ( file , basePath ) ;
1500
+ processReferencedLibraries ( file , libraryRoot ) ;
1487
1501
}
1488
1502
1489
1503
// always process imported modules to record module name resolutions
@@ -1507,6 +1521,97 @@ namespace ts {
1507
1521
} ) ;
1508
1522
}
1509
1523
1524
+ function findLibraryDefinition ( searchPath : string ) {
1525
+ let typingFilename = "index.d.ts" ;
1526
+ const packageJsonPath = combinePaths ( searchPath , "package.json" ) ;
1527
+ if ( host . fileExists ( packageJsonPath ) ) {
1528
+ let package : { typings ?: string } = { } ;
1529
+ try {
1530
+ package = JSON . parse ( host . readFile ( packageJsonPath ) ) ;
1531
+ }
1532
+ catch ( e ) { }
1533
+
1534
+ if ( package . typings ) {
1535
+ typingFilename = package . typings ;
1536
+ }
1537
+ }
1538
+
1539
+ const combinedPath = normalizePath ( combinePaths ( searchPath , typingFilename ) ) ;
1540
+ return host . fileExists ( combinedPath ) ? combinedPath : undefined ;
1541
+ }
1542
+
1543
+ function processReferencedLibraries ( file : SourceFile , compilationRoot : string ) {
1544
+ const primarySearchPaths = map ( getEffectiveLibraryPrimarySearchPaths ( ) , path => combinePaths ( compilationRoot , path ) ) ;
1545
+
1546
+ const failedSearchPaths : string [ ] = [ ] ;
1547
+ const moduleResolutionState : ModuleResolutionState = {
1548
+ compilerOptions : options ,
1549
+ host : host ,
1550
+ skipTsx : true ,
1551
+ traceEnabled : false
1552
+ } ;
1553
+
1554
+ for ( const ref of file . referencedLibraries ) {
1555
+ // If we already found this library as a primary reference, or failed to find it, nothing to do
1556
+ const previousResolution = resolvedLibraries [ ref . fileName ] ;
1557
+ if ( previousResolution && ( previousResolution . primary || ( previousResolution . resolvedFileName === undefined ) ) ) {
1558
+ continue ;
1559
+ }
1560
+
1561
+ let foundIt = false ;
1562
+
1563
+ // Check primary library paths
1564
+ for ( const primaryPath of primarySearchPaths ) {
1565
+ const searchPath = combinePaths ( primaryPath , ref . fileName ) ;
1566
+ const resolvedFile = findLibraryDefinition ( searchPath ) ;
1567
+ if ( resolvedFile ) {
1568
+ resolvedLibraries [ ref . fileName ] = { primary : true , resolvedFileName : resolvedFile } ;
1569
+ processSourceFile ( resolvedFile , /*isDefaultLib*/ false , /*isReference*/ true , file , ref . pos , ref . end ) ;
1570
+ foundIt = true ;
1571
+ break ;
1572
+ }
1573
+ }
1574
+
1575
+ // Check secondary library paths
1576
+ if ( ! foundIt ) {
1577
+ const secondaryResult = loadModuleFromNodeModules ( ref . fileName , file . fileName , failedSearchPaths , moduleResolutionState ) ;
1578
+ if ( secondaryResult ) {
1579
+ foundIt = true ;
1580
+ // If we already resolved to this file, it must have been a secondary reference. Check file contents
1581
+ // for sameness and possibly issue an error
1582
+ if ( previousResolution ) {
1583
+ const otherFileText = host . readFile ( secondaryResult ) ;
1584
+ if ( otherFileText !== getSourceFile ( previousResolution . resolvedFileName ) . text ) {
1585
+ fileProcessingDiagnostics . add ( createFileDiagnostic ( file , ref . pos , ref . end - ref . pos ,
1586
+ Diagnostics . Conflicting_library_definitions_for_0_found_at_1_and_2_Copy_the_correct_file_to_a_local_typings_folder_to_resolve_this_conflict ,
1587
+ ref . fileName ,
1588
+ secondaryResult ,
1589
+ previousResolution . resolvedFileName ) ) ;
1590
+ }
1591
+ }
1592
+ else {
1593
+ // First resolution of this library
1594
+ resolvedLibraries [ ref . fileName ] = { primary : false , resolvedFileName : secondaryResult } ;
1595
+ processSourceFile ( secondaryResult , /*isDefaultLib*/ false , /*isReference*/ true , file , ref . pos , ref . end ) ;
1596
+ }
1597
+ }
1598
+ }
1599
+
1600
+ if ( ! foundIt ) {
1601
+ fileProcessingDiagnostics . add ( createFileDiagnostic ( file , ref . pos , ref . end - ref . pos , Diagnostics . Cannot_find_name_0 , ref . fileName ) ) ;
1602
+ // Create an entry as a primary lookup result so we don't keep doing this
1603
+ resolvedLibraries [ ref . fileName ] = { primary : true , resolvedFileName : undefined } ;
1604
+ }
1605
+ }
1606
+ }
1607
+
1608
+ function getEffectiveLibraryPrimarySearchPaths ( ) : Path [ ] {
1609
+ return < Path [ ] > ( options . librarySearchPaths ||
1610
+ ( options . configFilePath ?
1611
+ [ options . configFilePath ] . concat ( defaultLibrarySearchPaths ) :
1612
+ defaultLibrarySearchPaths ) ) ;
1613
+ }
1614
+
1510
1615
function getCanonicalFileName ( fileName : string ) : string {
1511
1616
return host . getCanonicalFileName ( fileName ) ;
1512
1617
}
@@ -1553,15 +1658,11 @@ namespace ts {
1553
1658
return ;
1554
1659
}
1555
1660
1556
- function computeCommonSourceDirectory ( sourceFiles : SourceFile [ ] ) : string {
1661
+ function computeCommonSourceDirectoryOfFilenames ( fileNames : string [ ] ) : string {
1557
1662
let commonPathComponents : string [ ] ;
1558
- const failed = forEach ( files , sourceFile => {
1663
+ const failed = forEach ( fileNames , sourceFile => {
1559
1664
// Each file contributes into common source file path
1560
- if ( isDeclarationFile ( sourceFile ) ) {
1561
- return ;
1562
- }
1563
-
1564
- const sourcePathComponents = getNormalizedPathComponents ( sourceFile . fileName , currentDirectory ) ;
1665
+ const sourcePathComponents = getNormalizedPathComponents ( sourceFile , currentDirectory ) ;
1565
1666
sourcePathComponents . pop ( ) ; // The base file name is not part of the common directory path
1566
1667
1567
1668
if ( ! commonPathComponents ) {
@@ -1601,6 +1702,16 @@ namespace ts {
1601
1702
return getNormalizedPathFromPathComponents ( commonPathComponents ) ;
1602
1703
}
1603
1704
1705
+ function computeCommonSourceDirectory ( sourceFiles : SourceFile [ ] ) : string {
1706
+ const fileNames : string [ ] = [ ] ;
1707
+ for ( const file of sourceFiles ) {
1708
+ if ( ! file . isDeclarationFile ) {
1709
+ fileNames . push ( file . fileName ) ;
1710
+ }
1711
+ }
1712
+ return computeCommonSourceDirectoryOfFilenames ( fileNames ) ;
1713
+ }
1714
+
1604
1715
function checkSourceFilesBelongToPath ( sourceFiles : SourceFile [ ] , rootDirectory : string ) : boolean {
1605
1716
let allFilesBelongToPath = true ;
1606
1717
if ( sourceFiles ) {
@@ -1742,7 +1853,7 @@ namespace ts {
1742
1853
1743
1854
// If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure
1744
1855
if ( options . outDir && dir === "" && forEach ( files , file => getRootLength ( file . fileName ) > 1 ) ) {
1745
- programDiagnostics . add ( createCompilerDiagnostic ( Diagnostics . Cannot_find_the_common_subdirectory_path_for_the_input_files ) ) ;
1856
+ programDiagnostics . add ( createCompilerDiagnostic ( Diagnostics . Cannot_find_the_common_subdirectory_path_for_the_input_files ) ) ;
1746
1857
}
1747
1858
}
1748
1859
0 commit comments