Support reference library directives

This commit is contained in:
Ryan Cavanaugh 2016-02-23 12:48:31 -08:00 committed by Vladimir Matveev
parent 68bdbe04e7
commit 05444eaabb
39 changed files with 750 additions and 35 deletions

View File

@ -2159,6 +2159,11 @@
"category": "Error",
"code": 4082
},
"Conflicting library definitions for '{0}' found at '{1}' and '{2}'. Copy the correct file to a local typings folder to resolve this conflict.": {
"category": "Message",
"code": 4090
},
"The current host does not support the '{0}' option.": {
"category": "Error",
"code": 5001

View File

@ -5505,6 +5505,7 @@ namespace ts {
function processReferenceComments(sourceFile: SourceFile): void {
const triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/false, LanguageVariant.Standard, sourceText);
const referencedFiles: FileReference[] = [];
const referencedLibraries: FileReference[] = [];
const amdDependencies: { path: string; name: string }[] = [];
let amdModuleName: string;
@ -5531,7 +5532,12 @@ namespace ts {
sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
const diagnosticMessage = referencePathMatchResult.diagnosticMessage;
if (fileReference) {
referencedFiles.push(fileReference);
if (referencePathMatchResult.isLibraryReference) {
referencedLibraries.push(fileReference);
}
else {
referencedFiles.push(fileReference);
}
}
if (diagnosticMessage) {
parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage));
@ -5563,6 +5569,7 @@ namespace ts {
}
sourceFile.referencedFiles = referencedFiles;
sourceFile.referencedLibraries = referencedLibraries;
sourceFile.amdDependencies = amdDependencies;
sourceFile.moduleName = amdModuleName;
}

View File

@ -12,6 +12,12 @@ namespace ts {
const emptyArray: any[] = [];
const defaultLibrarySearchPaths = <Path[]>[
"typings/",
"node_modules/",
"node_modules/@types/",
];
export const version = "1.9.0";
export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string {
@ -370,7 +376,7 @@ namespace ts {
const traceEnabled = isTraceEnabled(compilerOptions, host);
const failedLookupLocations: string[] = [];
const state = {compilerOptions, host, traceEnabled, skipTsx: false};
const state = { compilerOptions, host, traceEnabled, skipTsx: false };
let resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, nodeLoadModuleByRelativeName,
failedLookupLocations, supportedExtensions, state);
@ -406,7 +412,7 @@ namespace ts {
}
/* @internal */
export function directoryProbablyExists(directoryName: string, host: { directoryExists?: (directoryName: string) => boolean } ): boolean {
export function directoryProbablyExists(directoryName: string, host: { directoryExists?: (directoryName: string) => boolean }): boolean {
// if host does not support 'directoryExists' assume that directory will exist
return !host.directoryExists || host.directoryExists(directoryName);
}
@ -553,7 +559,7 @@ namespace ts {
return referencedSourceFile
? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations }
? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations }
: { resolvedModule: undefined, failedLookupLocations };
}
@ -653,9 +659,9 @@ namespace ts {
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[] {
let diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(
program.getSyntacticDiagnostics(sourceFile, cancellationToken),
program.getGlobalDiagnostics(cancellationToken),
program.getSemanticDiagnostics(sourceFile, cancellationToken));
program.getSyntacticDiagnostics(sourceFile, cancellationToken),
program.getGlobalDiagnostics(cancellationToken),
program.getSemanticDiagnostics(sourceFile, cancellationToken));
if (program.getCompilerOptions().declaration) {
diagnostics = diagnostics.concat(program.getDeclarationDiagnostics(sourceFile, cancellationToken));
@ -694,6 +700,14 @@ namespace ts {
let program: Program;
let files: SourceFile[] = [];
let fileProcessingDiagnostics = createDiagnosticCollection();
const currentDirectory = host.getCurrentDirectory();
const resolvedLibraries: Map<ResolvedLibrary> = {};
let libraryRoot =
(options.rootDir && ts.toPath(options.rootDir, currentDirectory, host.getCanonicalFileName)) ||
(options.configFilePath && getDirectoryPath(getNormalizedAbsolutePath(options.configFilePath, currentDirectory)));
if (libraryRoot === undefined) {
libraryRoot = computeCommonSourceDirectoryOfFilenames(rootNames);
}
const programDiagnostics = createDiagnosticCollection();
let commonSourceDirectory: string;
@ -710,7 +724,6 @@ namespace ts {
// Map storing if there is emit blocking diagnostics for given input
const hasEmitBlockingDiagnostics = createFileMap<boolean>(getCanonicalFileName);
const currentDirectory = host.getCurrentDirectory();
const resolveModuleNamesWorker = host.resolveModuleNames
? ((moduleNames: string[], containingFile: string) => host.resolveModuleNames(moduleNames, containingFile))
: ((moduleNames: string[], containingFile: string) => {
@ -897,8 +910,8 @@ namespace ts {
const oldResolution = getResolvedModule(oldSourceFile, moduleNames[i]);
const resolutionChanged = oldResolution
? !newResolution ||
oldResolution.resolvedFileName !== newResolution.resolvedFileName ||
!!oldResolution.isExternalLibraryImport !== !!newResolution.isExternalLibraryImport
oldResolution.resolvedFileName !== newResolution.resolvedFileName ||
!!oldResolution.isExternalLibraryImport !== !!newResolution.isExternalLibraryImport
: newResolution;
if (resolutionChanged) {
@ -1021,9 +1034,9 @@ namespace ts {
}
function getDiagnosticsHelper(
sourceFile: SourceFile,
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[],
cancellationToken: CancellationToken): Diagnostic[] {
sourceFile: SourceFile,
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[],
cancellationToken: CancellationToken): Diagnostic[] {
if (sourceFile) {
return getDiagnostics(sourceFile, cancellationToken);
}
@ -1498,6 +1511,7 @@ namespace ts {
const basePath = getDirectoryPath(fileName);
if (!options.noResolve) {
processReferencedFiles(file, basePath, /*isDefaultLib*/ isDefaultLib);
processReferencedLibraries(file, libraryRoot);
}
// always process imported modules to record module name resolutions
@ -1521,6 +1535,97 @@ namespace ts {
});
}
function findLibraryDefinition(searchPath: string) {
let typingFilename = "index.d.ts";
const packageJsonPath = combinePaths(searchPath, "package.json");
if (host.fileExists(packageJsonPath)) {
let package: { typings?: string } = {};
try {
package = JSON.parse(host.readFile(packageJsonPath));
}
catch (e) { }
if (package.typings) {
typingFilename = package.typings;
}
}
const combinedPath = normalizePath(combinePaths(searchPath, typingFilename));
return host.fileExists(combinedPath) ? combinedPath : undefined;
}
function processReferencedLibraries(file: SourceFile, compilationRoot: string) {
const primarySearchPaths = map(getEffectiveLibraryPrimarySearchPaths(), path => combinePaths(compilationRoot, path));
const failedSearchPaths: string[] = [];
const moduleResolutionState: ModuleResolutionState = {
compilerOptions: options,
host: host,
skipTsx: true,
traceEnabled: false
};
for (const ref of file.referencedLibraries) {
// If we already found this library as a primary reference, or failed to find it, nothing to do
const previousResolution = resolvedLibraries[ref.fileName];
if (previousResolution && (previousResolution.primary || (previousResolution.resolvedFileName === undefined))) {
continue;
}
let foundIt = false;
// Check primary library paths
for (const primaryPath of primarySearchPaths) {
const searchPath = combinePaths(primaryPath, ref.fileName);
const resolvedFile = findLibraryDefinition(searchPath);
if (resolvedFile) {
resolvedLibraries[ref.fileName] = { primary: true, resolvedFileName: resolvedFile };
processSourceFile(resolvedFile, /*isDefaultLib*/ false, /*isReference*/ true, file, ref.pos, ref.end);
foundIt = true;
break;
}
}
// Check secondary library paths
if (!foundIt) {
const secondaryResult = loadModuleFromNodeModules(ref.fileName, file.fileName, failedSearchPaths, moduleResolutionState);
if (secondaryResult) {
foundIt = true;
// If we already resolved to this file, it must have been a secondary reference. Check file contents
// for sameness and possibly issue an error
if (previousResolution) {
const otherFileText = host.readFile(secondaryResult);
if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) {
fileProcessingDiagnostics.add(createFileDiagnostic(file, ref.pos, ref.end - ref.pos,
Diagnostics.Conflicting_library_definitions_for_0_found_at_1_and_2_Copy_the_correct_file_to_a_local_typings_folder_to_resolve_this_conflict,
ref.fileName,
secondaryResult,
previousResolution.resolvedFileName));
}
}
else {
// First resolution of this library
resolvedLibraries[ref.fileName] = { primary: false, resolvedFileName: secondaryResult };
processSourceFile(secondaryResult, /*isDefaultLib*/ false, /*isReference*/ true, file, ref.pos, ref.end);
}
}
}
if (!foundIt) {
fileProcessingDiagnostics.add(createFileDiagnostic(file, ref.pos, ref.end - ref.pos, Diagnostics.Cannot_find_name_0, ref.fileName));
// Create an entry as a primary lookup result so we don't keep doing this
resolvedLibraries[ref.fileName] = { primary: true, resolvedFileName: undefined };
}
}
}
function getEffectiveLibraryPrimarySearchPaths(): Path[] {
return <Path[]>(options.librarySearchPaths ||
(options.configFilePath ?
[options.configFilePath].concat(defaultLibrarySearchPaths) :
defaultLibrarySearchPaths));
}
function getCanonicalFileName(fileName: string): string {
return host.getCanonicalFileName(fileName);
}
@ -1567,15 +1672,11 @@ namespace ts {
return;
}
function computeCommonSourceDirectory(sourceFiles: SourceFile[]): string {
function computeCommonSourceDirectoryOfFilenames(fileNames: string[]): string {
let commonPathComponents: string[];
const failed = forEach(files, sourceFile => {
const failed = forEach(fileNames, sourceFile => {
// Each file contributes into common source file path
if (isDeclarationFile(sourceFile)) {
return;
}
const sourcePathComponents = getNormalizedPathComponents(sourceFile.fileName, currentDirectory);
const sourcePathComponents = getNormalizedPathComponents(sourceFile, currentDirectory);
sourcePathComponents.pop(); // The base file name is not part of the common directory path
if (!commonPathComponents) {
@ -1615,6 +1716,16 @@ namespace ts {
return getNormalizedPathFromPathComponents(commonPathComponents);
}
function computeCommonSourceDirectory(sourceFiles: SourceFile[]): string {
const fileNames: string[] = [];
for (const file of sourceFiles) {
if (!file.isDeclarationFile) {
fileNames.push(file.fileName);
}
}
return computeCommonSourceDirectoryOfFilenames(fileNames);
}
function checkSourceFilesBelongToPath(sourceFiles: SourceFile[], rootDirectory: string): boolean {
let allFilesBelongToPath = true;
if (sourceFiles) {
@ -1760,7 +1871,7 @@ namespace ts {
// 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
if (options.outDir && dir === "" && forEach(files, file => getRootLength(file.fileName) > 1)) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
}
}

View File

@ -390,6 +390,7 @@ namespace ts {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* compilerHost */ undefined);
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
configParseResult.options.configFilePath = configFileName as Path;
return configParseResult;
}

View File

@ -1536,6 +1536,7 @@ namespace ts {
amdDependencies: AmdDependency[];
moduleName: string;
referencedFiles: FileReference[];
referencedLibraries: FileReference[];
languageVariant: LanguageVariant;
isDeclarationFile: boolean;
@ -2415,6 +2416,7 @@ namespace ts {
jsx?: JsxEmit;
reactNamespace?: string;
listFiles?: boolean;
librarySearchPaths?: string[];
locale?: string;
mapRoot?: string;
module?: ModuleKind;
@ -2466,8 +2468,11 @@ namespace ts {
// Do not perform validation of output file name in transpile scenarios
/* @internal */ suppressOutputPathCheck?: boolean;
list?: string[];
/* @internal */
// When options come from a config file, its path is recorded here
configFilePath?: string;
list?: string[];
[option: string]: CompilerOptionsValue;
}
@ -2743,6 +2748,13 @@ namespace ts {
isExternalLibraryImport?: boolean;
}
export interface ResolvedLibrary {
// True if the library was found in a primary lookup location
primary: boolean;
// The location of the .d.ts file we located, or undefined if resolution failed
resolvedFileName?: string;
}
export interface ResolvedModuleWithFailedLookupLocations {
resolvedModule: ResolvedModule;
failedLookupLocations: string[];

View File

@ -6,6 +6,7 @@ namespace ts {
fileReference?: FileReference;
diagnosticMessage?: DiagnosticMessage;
isNoDefaultLib?: boolean;
isLibraryReference?: boolean;
}
export interface SynthesizedNode extends Node {
@ -498,6 +499,7 @@ namespace ts {
}
export let fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)('|")(.+?)\2.*?\/>/;
export let fullTripleSlashReferenceLibraryRegEx = /^(\/\/\/\s*<reference\s+library\s*=\s*)('|")(.+?)\2.*?\/>/;
export let fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*<amd-dependency\s+path\s*=\s*)('|")(.+?)\2.*?\/>/;
export function isTypeNode(node: Node): boolean {
@ -1548,25 +1550,26 @@ namespace ts {
};
}
else {
const matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
if (matchResult) {
const refMatchResult = fullTripleSlashReferencePathRegEx.exec(comment);
const refLibResult = !refMatchResult && fullTripleSlashReferenceLibraryRegEx.exec(comment);
if (refMatchResult || refLibResult) {
const start = commentRange.pos;
const end = commentRange.end;
return {
fileReference: {
pos: start,
end: end,
fileName: matchResult[3]
fileName: (refMatchResult || refLibResult)[3]
},
isNoDefaultLib: false
};
}
else {
return {
diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax,
isNoDefaultLib: false
isNoDefaultLib: false,
isLibraryReference: !!refLibResult
};
}
return {
diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax,
isNoDefaultLib: false
};
}
}

View File

@ -102,6 +102,10 @@ class CompilerBaselineRunner extends RunnerBase {
});
}
if (tsConfigOptions && tsConfigOptions.configFilePath !== undefined) {
tsConfigOptions.configFilePath = ts.combinePaths(rootDir, tsConfigOptions.configFilePath);
}
const output = Harness.Compiler.compileFiles(
toBeCompiled, otherFiles, harnessSettings, /*options*/ tsConfigOptions, /*currentDirectory*/ undefined);

View File

@ -836,7 +836,7 @@ namespace Harness {
export let fourslashSourceFile: ts.SourceFile;
export function getCanonicalFileName(fileName: string): string {
return Harness.IO.useCaseSensitiveFileNames() ? fileName : fileName.toLowerCase();
return fileName;
}
export function createCompilerHost(
@ -851,6 +851,8 @@ namespace Harness {
// Local get canonical file name function, that depends on passed in parameter for useCaseSensitiveFileNames
const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames);
const harnessNormalizePath = (f: string) => <ts.Path>ts.normalizePath(getCanonicalFileName(f));
const fileMap: ts.FileMap<ts.SourceFile> = ts.createFileMap<ts.SourceFile>();
for (const file of inputFiles) {
if (file.content !== undefined) {
@ -858,6 +860,7 @@ namespace Harness {
const sourceFile = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget);
const path = ts.toPath(file.unitName, currentDirectory, getCanonicalFileName);
fileMap.set(path, sourceFile);
fileMap.set(harnessNormalizePath(path), sourceFile);
}
}
@ -884,6 +887,7 @@ namespace Harness {
newLineKind === ts.NewLineKind.LineFeed ? lineFeed :
Harness.IO.newLine();
return {
getCurrentDirectory: () => currentDirectory,
getSourceFile,
@ -892,8 +896,12 @@ namespace Harness {
getCanonicalFileName,
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
getNewLine: () => newLine,
fileExists: fileName => getSourceFile(fileName, ts.ScriptTarget.ES5) !== undefined,
readFile: (fileName: string): string => { return Harness.IO.readFile(fileName); }
fileExists: fileName => {
return fileMap.contains(harnessNormalizePath(fileName));
},
readFile: (fileName: string): string => {
return fileMap.get(harnessNormalizePath(fileName)).getText();
}
};
}
@ -1480,6 +1488,7 @@ namespace Harness {
baseDir = ts.getNormalizedAbsolutePath(baseDir, rootDir);
}
tsConfig = ts.parseJsonConfigFileContent(configJson.config, parseConfigHost, baseDir);
tsConfig.options.configFilePath = <ts.Path>data.name;
// delete entry from the list
testUnitData.splice(i, 1);

View File

@ -792,6 +792,7 @@ namespace ts {
public amdDependencies: { name: string; path: string }[];
public moduleName: string;
public referencedFiles: FileReference[];
public referencedLibraries: FileReference[];
public syntacticDiagnostics: Diagnostic[];
public referenceDiagnostics: Diagnostic[];

View File

@ -0,0 +1,17 @@
//// [tests/cases/conformance/references/library-reference-1.ts] ////
//// [index.d.ts]
// We can find typings in the ./typings folder
declare var $: { foo(): void };
//// [consumer.ts]
/// <reference library="jquery" />
$.foo();
//// [consumer.js]
/// <reference library="jquery" />
$.foo();

View File

@ -0,0 +1,16 @@
=== tests/cases/conformance/references/consumer.ts ===
/// <reference library="jquery" />
$.foo();
>$.foo : Symbol(foo, Decl(index.d.ts, 3, 16))
>$ : Symbol($, Decl(index.d.ts, 3, 11))
>foo : Symbol(foo, Decl(index.d.ts, 3, 16))
=== tests/cases/conformance/references/typings/jquery/index.d.ts ===
// We can find typings in the ./typings folder
declare var $: { foo(): void };
>$ : Symbol($, Decl(index.d.ts, 3, 11))
>foo : Symbol(foo, Decl(index.d.ts, 3, 16))

View File

@ -0,0 +1,17 @@
=== tests/cases/conformance/references/consumer.ts ===
/// <reference library="jquery" />
$.foo();
>$.foo() : void
>$.foo : () => void
>$ : { foo(): void; }
>foo : () => void
=== tests/cases/conformance/references/typings/jquery/index.d.ts ===
// We can find typings in the ./typings folder
declare var $: { foo(): void };
>$ : { foo(): void; }
>foo : () => void

View File

@ -0,0 +1,22 @@
//// [tests/cases/conformance/references/library-reference-2.ts] ////
//// [package.json]
// package.json in a primary reference can refer to another file
{
"typings": "jquery.d.ts"
}
//// [jquery.d.ts]
declare var $: { foo(): void };
//// [consumer.ts]
/// <reference library="jquery" />
$.foo();
//// [consumer.js]
/// <reference library="jquery" />
$.foo();

View File

@ -0,0 +1,13 @@
=== tests/cases/conformance/references/consumer.ts ===
/// <reference library="jquery" />
$.foo();
>$.foo : Symbol(foo, Decl(jquery.d.ts, 0, 16))
>$ : Symbol($, Decl(jquery.d.ts, 0, 11))
>foo : Symbol(foo, Decl(jquery.d.ts, 0, 16))
=== tests/cases/conformance/references/typings/jquery/jquery.d.ts ===
declare var $: { foo(): void };
>$ : Symbol($, Decl(jquery.d.ts, 0, 11))
>foo : Symbol(foo, Decl(jquery.d.ts, 0, 16))

View File

@ -0,0 +1,14 @@
=== tests/cases/conformance/references/consumer.ts ===
/// <reference library="jquery" />
$.foo();
>$.foo() : void
>$.foo : () => void
>$ : { foo(): void; }
>foo : () => void
=== tests/cases/conformance/references/typings/jquery/jquery.d.ts ===
declare var $: { foo(): void };
>$ : { foo(): void; }
>foo : () => void

View File

@ -0,0 +1,16 @@
//// [tests/cases/conformance/references/library-reference-3.ts] ////
//// [index.d.ts]
// Secondary references are possible
declare var $: { foo(): void };
//// [consumer.ts]
/// <reference library="jquery" />
$.foo();
//// [consumer.js]
/// <reference library="jquery" />
$.foo();

View File

@ -0,0 +1,15 @@
=== tests/cases/conformance/references/src/consumer.ts ===
/// <reference library="jquery" />
$.foo();
>$.foo : Symbol(foo, Decl(index.d.ts, 3, 16))
>$ : Symbol($, Decl(index.d.ts, 3, 11))
>foo : Symbol(foo, Decl(index.d.ts, 3, 16))
=== tests/cases/conformance/references/src/node_modules/jquery/index.d.ts ===
// Secondary references are possible
declare var $: { foo(): void };
>$ : Symbol($, Decl(index.d.ts, 3, 11))
>foo : Symbol(foo, Decl(index.d.ts, 3, 16))

View File

@ -0,0 +1,16 @@
=== tests/cases/conformance/references/src/consumer.ts ===
/// <reference library="jquery" />
$.foo();
>$.foo() : void
>$.foo : () => void
>$ : { foo(): void; }
>foo : () => void
=== tests/cases/conformance/references/src/node_modules/jquery/index.d.ts ===
// Secondary references are possible
declare var $: { foo(): void };
>$ : { foo(): void; }
>foo : () => void

View File

@ -0,0 +1,29 @@
tests/cases/conformance/references/src/root.ts(1,1): error TS2304: Cannot find name 'foo'.
tests/cases/conformance/references/src/root.ts(2,1): error TS2304: Cannot find name 'bar'.
==== tests/cases/conformance/references/src/root.ts (2 errors) ====
/// <reference library="foo" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2304: Cannot find name 'foo'.
/// <reference library="bar" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2304: Cannot find name 'bar'.
==== tests/cases/conformance/references/node_modules/foo/index.d.ts (0 errors) ====
// Secondary references may be duplicated if they agree in content
/// <reference library="alpha" />
declare var foo: any;
==== tests/cases/conformance/references/node_modules/foo/node_modules/alpha/index.d.ts (0 errors) ====
declare var alpha: any;
==== tests/cases/conformance/references/node_modules/bar/index.d.ts (0 errors) ====
/// <reference library="alpha" />
declare var bar: any;
==== tests/cases/conformance/references/node_modules/bar/node_modules/alpha/index.d.ts (0 errors) ====
declare var alpha: any;

View File

@ -0,0 +1,27 @@
//// [tests/cases/conformance/references/library-reference-4.ts] ////
//// [index.d.ts]
// Secondary references may be duplicated if they agree in content
/// <reference library="alpha" />
declare var foo: any;
//// [index.d.ts]
declare var alpha: any;
//// [index.d.ts]
/// <reference library="alpha" />
declare var bar: any;
//// [index.d.ts]
declare var alpha: any;
//// [root.ts]
/// <reference library="foo" />
/// <reference library="bar" />
//// [root.js]
/// <reference library="foo" />
/// <reference library="bar" />

View File

@ -0,0 +1,29 @@
tests/cases/conformance/references/src/root.ts(1,1): error TS2304: Cannot find name 'foo'.
tests/cases/conformance/references/src/root.ts(2,1): error TS2304: Cannot find name 'bar'.
==== tests/cases/conformance/references/src/root.ts (2 errors) ====
/// <reference library="foo" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2304: Cannot find name 'foo'.
/// <reference library="bar" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2304: Cannot find name 'bar'.
==== tests/cases/conformance/references/node_modules/foo/index.d.ts (0 errors) ====
// Secondary references may not be duplicated if they disagree in content
/// <reference library="alpha" />
declare var foo: any;
==== tests/cases/conformance/references/node_modules/foo/node_modules/alpha/index.d.ts (0 errors) ====
declare var alpha: any;
==== tests/cases/conformance/references/node_modules/bar/index.d.ts (0 errors) ====
/// <reference library="alpha" />
declare var bar: any;
==== tests/cases/conformance/references/node_modules/bar/node_modules/alpha/index.d.ts (0 errors) ====
declare var alpha: {};

View File

@ -0,0 +1,27 @@
//// [tests/cases/conformance/references/library-reference-5.ts] ////
//// [index.d.ts]
// Secondary references may not be duplicated if they disagree in content
/// <reference library="alpha" />
declare var foo: any;
//// [index.d.ts]
declare var alpha: any;
//// [index.d.ts]
/// <reference library="alpha" />
declare var bar: any;
//// [index.d.ts]
declare var alpha: {};
//// [root.ts]
/// <reference library="foo" />
/// <reference library="bar" />
//// [root.js]
/// <reference library="foo" />
/// <reference library="bar" />

View File

@ -0,0 +1,16 @@
//// [tests/cases/conformance/references/library-reference-6.ts] ////
//// [index.d.ts]
// The primary lookup folder is relative to tsconfig.json, if present
declare var alpha: { a: string };
//// [foo.ts]
/// <reference library="alpha" />
var x: string = alpha.a;
//// [foo.js]
/// <reference library="alpha" />
var x = alpha.a;

View File

@ -0,0 +1,16 @@
=== tests/cases/conformance/references/src/foo.ts ===
/// <reference library="alpha" />
var x: string = alpha.a;
>x : Symbol(x, Decl(foo.ts, 1, 3))
>alpha.a : Symbol(a, Decl(index.d.ts, 3, 20))
>alpha : Symbol(alpha, Decl(index.d.ts, 3, 11))
>a : Symbol(a, Decl(index.d.ts, 3, 20))
=== tests/cases/conformance/references/typings/alpha/index.d.ts ===
// The primary lookup folder is relative to tsconfig.json, if present
declare var alpha: { a: string };
>alpha : Symbol(alpha, Decl(index.d.ts, 3, 11))
>a : Symbol(a, Decl(index.d.ts, 3, 20))

View File

@ -0,0 +1,16 @@
=== tests/cases/conformance/references/src/foo.ts ===
/// <reference library="alpha" />
var x: string = alpha.a;
>x : string
>alpha.a : string
>alpha : { a: string; }
>a : string
=== tests/cases/conformance/references/typings/alpha/index.d.ts ===
// The primary lookup folder is relative to tsconfig.json, if present
declare var alpha: { a: string };
>alpha : { a: string; }
>a : string

View File

@ -0,0 +1,16 @@
//// [tests/cases/conformance/references/library-reference-7.ts] ////
//// [index.d.ts]
// The primary lookup folder is relative to tsconfig.json's 'root', if present
declare var alpha: { a: string };
//// [foo.ts]
/// <reference library="alpha" />
var x: string = alpha.a;
//// [foo.js]
/// <reference library="alpha" />
var x = alpha.a;

View File

@ -0,0 +1,16 @@
=== tests/cases/conformance/references/base/src/foo.ts ===
/// <reference library="alpha" />
var x: string = alpha.a;
>x : Symbol(x, Decl(foo.ts, 1, 3))
>alpha.a : Symbol(a, Decl(index.d.ts, 3, 20))
>alpha : Symbol(alpha, Decl(index.d.ts, 3, 11))
>a : Symbol(a, Decl(index.d.ts, 3, 20))
=== tests/cases/conformance/references/base/typings/alpha/index.d.ts ===
// The primary lookup folder is relative to tsconfig.json's 'root', if present
declare var alpha: { a: string };
>alpha : Symbol(alpha, Decl(index.d.ts, 3, 11))
>a : Symbol(a, Decl(index.d.ts, 3, 20))

View File

@ -0,0 +1,16 @@
=== tests/cases/conformance/references/base/src/foo.ts ===
/// <reference library="alpha" />
var x: string = alpha.a;
>x : string
>alpha.a : string
>alpha : { a: string; }
>a : string
=== tests/cases/conformance/references/base/typings/alpha/index.d.ts ===
// The primary lookup folder is relative to tsconfig.json's 'root', if present
declare var alpha: { a: string };
>alpha : { a: string; }
>a : string

View File

@ -0,0 +1,24 @@
//// [tests/cases/conformance/references/library-reference-8.ts] ////
//// [index.d.ts]
// Don't crash in circular library reference situations
/// <reference library="beta" />
declare var alpha: { a: string };
//// [index.d.ts]
/// <reference library="alpha" />
declare var beta: { b: string };
//// [foo.ts]
/// <reference library="alpha" />
/// <reference library="beta" />
var x: string = alpha.a + beta.b;
//// [foo.js]
/// <reference library="alpha" />
/// <reference library="beta" />
var x = alpha.a + beta.b;

View File

@ -0,0 +1,28 @@
=== tests/cases/conformance/references/foo.ts ===
/// <reference library="alpha" />
/// <reference library="beta" />
var x: string = alpha.a + beta.b;
>x : Symbol(x, Decl(foo.ts, 2, 3))
>alpha.a : Symbol(a, Decl(index.d.ts, 4, 20))
>alpha : Symbol(alpha, Decl(index.d.ts, 4, 11))
>a : Symbol(a, Decl(index.d.ts, 4, 20))
>beta.b : Symbol(b, Decl(index.d.ts, 1, 19))
>beta : Symbol(beta, Decl(index.d.ts, 1, 11))
>b : Symbol(b, Decl(index.d.ts, 1, 19))
=== tests/cases/conformance/references/typings/alpha/index.d.ts ===
// Don't crash in circular library reference situations
/// <reference library="beta" />
declare var alpha: { a: string };
>alpha : Symbol(alpha, Decl(index.d.ts, 4, 11))
>a : Symbol(a, Decl(index.d.ts, 4, 20))
=== tests/cases/conformance/references/typings/beta/index.d.ts ===
/// <reference library="alpha" />
declare var beta: { b: string };
>beta : Symbol(beta, Decl(index.d.ts, 1, 11))
>b : Symbol(b, Decl(index.d.ts, 1, 19))

View File

@ -0,0 +1,29 @@
=== tests/cases/conformance/references/foo.ts ===
/// <reference library="alpha" />
/// <reference library="beta" />
var x: string = alpha.a + beta.b;
>x : string
>alpha.a + beta.b : string
>alpha.a : string
>alpha : { a: string; }
>a : string
>beta.b : string
>beta : { b: string; }
>b : string
=== tests/cases/conformance/references/typings/alpha/index.d.ts ===
// Don't crash in circular library reference situations
/// <reference library="beta" />
declare var alpha: { a: string };
>alpha : { a: string; }
>a : string
=== tests/cases/conformance/references/typings/beta/index.d.ts ===
/// <reference library="alpha" />
declare var beta: { b: string };
>beta : { b: string; }
>b : string

View File

@ -0,0 +1,11 @@
// @noImplicitReferences: true
// We can find typings in the ./typings folder
// @filename: typings/jquery/index.d.ts
declare var $: { foo(): void };
// @filename: consumer.ts
/// <reference library="jquery" />
$.foo();

View File

@ -0,0 +1,16 @@
// @noImplicitReferences: true
// package.json in a primary reference can refer to another file
// @filename: typings/jquery/package.json
{
"typings": "jquery.d.ts"
}
// @filename: typings/jquery/jquery.d.ts
declare var $: { foo(): void };
// @filename: consumer.ts
/// <reference library="jquery" />
$.foo();

View File

@ -0,0 +1,10 @@
// @noImplicitReferences: true
// Secondary references are possible
// @filename: src/node_modules/jquery/index.d.ts
declare var $: { foo(): void };
// @filename: src/consumer.ts
/// <reference library="jquery" />
$.foo();

View File

@ -0,0 +1,21 @@
// @noImplicitReferences: true
// Secondary references may be duplicated if they agree in content
// @filename: node_modules/foo/index.d.ts
/// <reference library="alpha" />
declare var foo: any;
// @filename: node_modules/foo/node_modules/alpha/index.d.ts
declare var alpha: any;
// @filename: node_modules/bar/index.d.ts
/// <reference library="alpha" />
declare var bar: any;
// @filename: node_modules/bar/node_modules/alpha/index.d.ts
declare var alpha: any;
// @filename: src/root.ts
/// <reference library="foo" />
/// <reference library="bar" />

View File

@ -0,0 +1,21 @@
// @noImplicitReferences: true
// Secondary references may not be duplicated if they disagree in content
// @filename: node_modules/foo/index.d.ts
/// <reference library="alpha" />
declare var foo: any;
// @filename: node_modules/foo/node_modules/alpha/index.d.ts
declare var alpha: any;
// @filename: node_modules/bar/index.d.ts
/// <reference library="alpha" />
declare var bar: any;
// @filename: node_modules/bar/node_modules/alpha/index.d.ts
declare var alpha: {};
// @filename: src/root.ts
/// <reference library="foo" />
/// <reference library="bar" />

View File

@ -0,0 +1,14 @@
// @noImplicitReferences: true
// The primary lookup folder is relative to tsconfig.json, if present
// @filename: typings/alpha/index.d.ts
declare var alpha: { a: string };
// @filename: src/foo.ts
/// <reference library="alpha" />
var x: string = alpha.a;
// @filename: tsconfig.json
{
}

View File

@ -0,0 +1,17 @@
// @noImplicitReferences: true
// The primary lookup folder is relative to tsconfig.json's 'root', if present
// @filename: base/typings/alpha/index.d.ts
declare var alpha: { a: string };
// @filename: base/src/foo.ts
/// <reference library="alpha" />
var x: string = alpha.a;
// @filename: tsconfig.json
{
"compilerOptions": {
"rootDir": "base"
}
}

View File

@ -0,0 +1,17 @@
// @noImplicitReferences: true
// Don't crash in circular library reference situations
// @filename: typings/alpha/index.d.ts
/// <reference library="beta" />
declare var alpha: { a: string };
// @filename: typings/beta/index.d.ts
/// <reference library="alpha" />
declare var beta: { b: string };
// @filename: foo.ts
/// <reference library="alpha" />
/// <reference library="beta" />
var x: string = alpha.a + beta.b;