Skip to content

Commit 74a961b

Browse files
committed
Support reference library directives in tsc
1 parent 7d372bf commit 74a961b

File tree

6 files changed

+71
-23
lines changed

6 files changed

+71
-23
lines changed

src/compiler/parser.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5491,6 +5491,7 @@ namespace ts {
54915491
function processReferenceComments(sourceFile: SourceFile): void {
54925492
const triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/false, LanguageVariant.Standard, sourceText);
54935493
const referencedFiles: FileReference[] = [];
5494+
const referencedLibraries: FileReference[] = [];
54945495
const amdDependencies: { path: string; name: string }[] = [];
54955496
let amdModuleName: string;
54965497

@@ -5517,7 +5518,12 @@ namespace ts {
55175518
sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
55185519
const diagnosticMessage = referencePathMatchResult.diagnosticMessage;
55195520
if (fileReference) {
5520-
referencedFiles.push(fileReference);
5521+
if (referencePathMatchResult.isLibraryReference) {
5522+
referencedLibraries.push(fileReference);
5523+
}
5524+
else {
5525+
referencedFiles.push(fileReference);
5526+
}
55215527
}
55225528
if (diagnosticMessage) {
55235529
parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage));
@@ -5549,6 +5555,7 @@ namespace ts {
55495555
}
55505556

55515557
sourceFile.referencedFiles = referencedFiles;
5558+
sourceFile.referencedLibraries = referencedLibraries;
55525559
sourceFile.amdDependencies = amdDependencies;
55535560
sourceFile.moduleName = amdModuleName;
55545561
}

src/compiler/program.ts

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ namespace ts {
1212

1313
const emptyArray: any[] = [];
1414

15+
const defaultLibrarySearchPaths = [
16+
'./',
17+
'./typings/',
18+
'./node_modules/',
19+
'./node_modules/@types/',
20+
];
21+
1522
export const version = "1.9.0";
1623

1724
export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string {
@@ -371,7 +378,7 @@ namespace ts {
371378
const traceEnabled = isTraceEnabled(compilerOptions, host);
372379

373380
const failedLookupLocations: string[] = [];
374-
const state = {compilerOptions, host, traceEnabled, skipTsx: false};
381+
const state = { compilerOptions, host, traceEnabled, skipTsx: false };
375382
let resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, nodeLoadModuleByRelativeName,
376383
failedLookupLocations, supportedExtensions, state);
377384

@@ -407,7 +414,7 @@ namespace ts {
407414
}
408415

409416
/* @internal */
410-
export function directoryProbablyExists(directoryName: string, host: { directoryExists?: (directoryName: string) => boolean } ): boolean {
417+
export function directoryProbablyExists(directoryName: string, host: { directoryExists?: (directoryName: string) => boolean }): boolean {
411418
// if host does not support 'directoryExists' assume that directory will exist
412419
return !host.directoryExists || host.directoryExists(directoryName);
413420
}
@@ -554,7 +561,7 @@ namespace ts {
554561

555562

556563
return referencedSourceFile
557-
? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations }
564+
? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations }
558565
: { resolvedModule: undefined, failedLookupLocations };
559566
}
560567

@@ -649,9 +656,9 @@ namespace ts {
649656

650657
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[] {
651658
let diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(
652-
program.getSyntacticDiagnostics(sourceFile, cancellationToken),
653-
program.getGlobalDiagnostics(cancellationToken),
654-
program.getSemanticDiagnostics(sourceFile, cancellationToken));
659+
program.getSyntacticDiagnostics(sourceFile, cancellationToken),
660+
program.getGlobalDiagnostics(cancellationToken),
661+
program.getSemanticDiagnostics(sourceFile, cancellationToken));
655662

656663
if (program.getCompilerOptions().declaration) {
657664
diagnostics = diagnostics.concat(program.getDeclarationDiagnostics(sourceFile, cancellationToken));
@@ -883,8 +890,8 @@ namespace ts {
883890
const oldResolution = getResolvedModule(oldSourceFile, moduleNames[i]);
884891
const resolutionChanged = oldResolution
885892
? !newResolution ||
886-
oldResolution.resolvedFileName !== newResolution.resolvedFileName ||
887-
!!oldResolution.isExternalLibraryImport !== !!newResolution.isExternalLibraryImport
893+
oldResolution.resolvedFileName !== newResolution.resolvedFileName ||
894+
!!oldResolution.isExternalLibraryImport !== !!newResolution.isExternalLibraryImport
888895
: newResolution;
889896

890897
if (resolutionChanged) {
@@ -1007,9 +1014,9 @@ namespace ts {
10071014
}
10081015

10091016
function getDiagnosticsHelper(
1010-
sourceFile: SourceFile,
1011-
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[],
1012-
cancellationToken: CancellationToken): Diagnostic[] {
1017+
sourceFile: SourceFile,
1018+
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[],
1019+
cancellationToken: CancellationToken): Diagnostic[] {
10131020
if (sourceFile) {
10141021
return getDiagnostics(sourceFile, cancellationToken);
10151022
}
@@ -1486,6 +1493,10 @@ namespace ts {
14861493
processReferencedFiles(file, basePath);
14871494
}
14881495

1496+
const libraryRoot = computeCommonSourceDirectory(files);
1497+
1498+
processReferencedLibraries(file, libraryRoot);
1499+
14891500
// always process imported modules to record module name resolutions
14901501
processImportedModules(file, basePath);
14911502

@@ -1507,6 +1518,25 @@ namespace ts {
15071518
});
15081519
}
15091520

1521+
function processReferencedLibraries(file: SourceFile, compilationRoot: string) {
1522+
const searchPaths = getEffectiveLibrarySearchPaths();
1523+
for (const ref of file.referencedLibraries) {
1524+
for (const path of searchPaths) {
1525+
const combinedPath = combinePaths(path, ref.fileName);
1526+
if (host.fileExists(combinedPath)) {
1527+
processSourceFile(combinedPath, false, file, ref.pos, ref.end);
1528+
}
1529+
}
1530+
}
1531+
}
1532+
1533+
function getEffectiveLibrarySearchPaths() {
1534+
return options.librarySearchPaths ||
1535+
(options.configFilePath ?
1536+
[options.configFilePath].concat(defaultLibrarySearchPaths) :
1537+
defaultLibrarySearchPaths);
1538+
}
1539+
15101540
function getCanonicalFileName(fileName: string): string {
15111541
return host.getCanonicalFileName(fileName);
15121542
}
@@ -1742,7 +1772,7 @@ namespace ts {
17421772

17431773
// 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
17441774
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));
1775+
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
17461776
}
17471777
}
17481778

src/compiler/tsc.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ namespace ts {
390390
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* compilerHost */ undefined);
391391
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
392392
}
393+
configParseResult.options.configFilePath = configFileName;
393394
return configParseResult;
394395
}
395396

src/compiler/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,7 @@ namespace ts {
15221522
amdDependencies: AmdDependency[];
15231523
moduleName: string;
15241524
referencedFiles: FileReference[];
1525+
referencedLibraries: FileReference[];
15251526
languageVariant: LanguageVariant;
15261527
isDeclarationFile: boolean;
15271528

@@ -2395,6 +2396,7 @@ namespace ts {
23952396
jsx?: JsxEmit;
23962397
reactNamespace?: string;
23972398
listFiles?: boolean;
2399+
librarySearchPaths?: string[];
23982400
locale?: string;
23992401
mapRoot?: string;
24002402
module?: ModuleKind;
@@ -2444,6 +2446,10 @@ namespace ts {
24442446
// Do not perform validation of output file name in transpile scenarios
24452447
/* @internal */ suppressOutputPathCheck?: boolean;
24462448

2449+
/* @internal */
2450+
// When options come from a config file, its path is recorded here
2451+
configFilePath?: string;
2452+
24472453
[option: string]: string | number | boolean | TsConfigOnlyOptions;
24482454
}
24492455

src/compiler/utilities.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace ts {
66
fileReference?: FileReference;
77
diagnosticMessage?: DiagnosticMessage;
88
isNoDefaultLib?: boolean;
9+
isLibraryReference?: boolean;
910
}
1011

1112
export interface SynthesizedNode extends Node {
@@ -498,6 +499,7 @@ namespace ts {
498499
}
499500

500501
export let fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)('|")(.+?)\2.*?\/>/;
502+
export let fullTripleSlashReferenceLibraryRegEx = /^(\/\/\/\s*<reference\s+library\s*=\s*)('|")(.+?)\2.*?\/>/;
501503
export let fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*<amd-dependency\s+path\s*=\s*)('|")(.+?)\2.*?\/>/;
502504

503505
export function isTypeNode(node: Node): boolean {
@@ -1536,25 +1538,26 @@ namespace ts {
15361538
};
15371539
}
15381540
else {
1539-
const matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
1540-
if (matchResult) {
1541+
const refMatchResult = fullTripleSlashReferencePathRegEx.exec(comment);
1542+
const refLibResult = !refMatchResult && fullTripleSlashReferenceLibraryRegEx.exec(comment);
1543+
if (refMatchResult || refLibResult) {
15411544
const start = commentRange.pos;
15421545
const end = commentRange.end;
15431546
return {
15441547
fileReference: {
15451548
pos: start,
15461549
end: end,
1547-
fileName: matchResult[3]
1550+
fileName: (refMatchResult || refLibResult)[3]
15481551
},
1549-
isNoDefaultLib: false
1550-
};
1551-
}
1552-
else {
1553-
return {
1554-
diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax,
1555-
isNoDefaultLib: false
1552+
isNoDefaultLib: false,
1553+
isLibraryReference: !!refLibResult
15561554
};
15571555
}
1556+
1557+
return {
1558+
diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax,
1559+
isNoDefaultLib: false
1560+
};
15581561
}
15591562
}
15601563

src/services/services.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,7 @@ namespace ts {
792792
public amdDependencies: { name: string; path: string }[];
793793
public moduleName: string;
794794
public referencedFiles: FileReference[];
795+
public referencedLibraries: FileReference[];
795796

796797
public syntacticDiagnostics: Diagnostic[];
797798
public referenceDiagnostics: Diagnostic[];

0 commit comments

Comments
 (0)