diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index cc17383c064ff..a6eac41b1e2e6 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -312,6 +312,16 @@ namespace ts { isFilePath: true } }, + { + name: "librarySearchPaths", + type: "list", + isTSConfigOnly: true, + element: { + name: "librarySearchPaths", + type: "string", + isFilePath: true + } + }, { name: "traceModuleResolution", type: "boolean", @@ -598,6 +608,7 @@ namespace ts { const compilerOptions: CompilerOptions = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName); const options = extend(existingOptions, compilerOptions); const typingOptions: TypingOptions = convertTypingOptionsFromJsonWorker(json["typingOptions"], basePath, errors, configFileName); + options.configFilePath = configFileName; const fileNames = getFileNames(errors); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index d7c2fac27102f..f9e87def2a952 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2155,6 +2155,11 @@ "category": "Error", "code": 4082 }, + "Conflicting library definitions for '{0}' found at '{1}' and '{2}'. Copy the correct file to the 'typings' folder to resolve this conflict.": { + "category": "Message", + "code": 4090 + }, + "The current host does not support the '{0}' option.": { "category": "Error", "code": 5001 diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b7c011631ee18..fae1c64ed518f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -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; } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index b528143384e2f..e55a69eacb833 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -12,6 +12,12 @@ namespace ts { const emptyArray: any[] = []; + const defaultLibrarySearchPaths = [ + "typings/", + "node_modules/", + "node_modules/@typings/", + ]; + export const version = "1.9.0"; export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string { @@ -371,7 +377,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); @@ -407,7 +413,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); } @@ -554,7 +560,7 @@ namespace ts { return referencedSourceFile - ? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations } + ? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations } : { resolvedModule: undefined, failedLookupLocations }; } @@ -649,9 +655,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)); @@ -690,6 +696,14 @@ namespace ts { let program: Program; let files: SourceFile[] = []; let fileProcessingDiagnostics = createDiagnosticCollection(); + const currentDirectory = host.getCurrentDirectory(); + const resolvedLibraries: Map = {}; + 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; @@ -706,7 +720,6 @@ namespace ts { // Map storing if there is emit blocking diagnostics for given input const hasEmitBlockingDiagnostics = createFileMap(getCanonicalFileName); - const currentDirectory = host.getCurrentDirectory(); const resolveModuleNamesWorker = host.resolveModuleNames ? ((moduleNames: string[], containingFile: string) => host.resolveModuleNames(moduleNames, containingFile)) : ((moduleNames: string[], containingFile: string) => { @@ -883,8 +896,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) { @@ -1007,9 +1020,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); } @@ -1484,6 +1497,7 @@ namespace ts { const basePath = getDirectoryPath(fileName); if (!options.noResolve) { processReferencedFiles(file, basePath); + processReferencedLibraries(file, libraryRoot); } // always process imported modules to record module name resolutions @@ -1507,6 +1521,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_the_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 (options.librarySearchPaths || + (options.configFilePath ? + [options.configFilePath].concat(defaultLibrarySearchPaths) : + defaultLibrarySearchPaths)); + } + function getCanonicalFileName(fileName: string): string { return host.getCanonicalFileName(fileName); } @@ -1553,15 +1658,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) { @@ -1601,6 +1702,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) { @@ -1742,7 +1853,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)); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 546d1631945cc..591c28e5ac781 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -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[]; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 2966af3cb76f3..27da2c6251ac2 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -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*/; + export let fullTripleSlashReferenceLibraryRegEx = /^(\/\/\/\s*/; export let fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; export function isTypeNode(node: Node): boolean { @@ -1538,25 +1540,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 + }; } } diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 3362cb1d375be..6dfc931342507 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -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); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index ddaca6420944f..9b822704056ff 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -817,7 +817,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( @@ -832,6 +832,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.normalizePath(getCanonicalFileName(f)); + const fileMap: ts.FileMap = ts.createFileMap(); for (const file of inputFiles) { if (file.content !== undefined) { @@ -839,6 +841,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); } } @@ -867,6 +870,7 @@ namespace Harness { newLineKind === ts.NewLineKind.LineFeed ? lineFeed : Harness.IO.newLine(); + return { getCurrentDirectory: () => currentDirectory, getSourceFile, @@ -875,8 +879,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(); + } }; } @@ -1462,6 +1470,7 @@ namespace Harness { baseDir = ts.getNormalizedAbsolutePath(baseDir, rootDir); } tsConfig = ts.parseJsonConfigFileContent(configJson.config, parseConfigHost, baseDir); + tsConfig.options.configFilePath = data.name; // delete entry from the list testUnitData.splice(i, 1); diff --git a/src/services/services.ts b/src/services/services.ts index 72255b554799d..7d0beb1c9e3ed 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -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[]; diff --git a/tests/baselines/reference/library-reference-1.js b/tests/baselines/reference/library-reference-1.js new file mode 100644 index 0000000000000..628790cc3eea5 --- /dev/null +++ b/tests/baselines/reference/library-reference-1.js @@ -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] +/// +$.foo(); + + +//// [consumer.js] +/// +$.foo(); diff --git a/tests/baselines/reference/library-reference-1.symbols b/tests/baselines/reference/library-reference-1.symbols new file mode 100644 index 0000000000000..416ec495d5641 --- /dev/null +++ b/tests/baselines/reference/library-reference-1.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/references/consumer.ts === +/// +$.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)) + + diff --git a/tests/baselines/reference/library-reference-1.types b/tests/baselines/reference/library-reference-1.types new file mode 100644 index 0000000000000..d2725524d48ec --- /dev/null +++ b/tests/baselines/reference/library-reference-1.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/references/consumer.ts === +/// +$.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 + + diff --git a/tests/baselines/reference/library-reference-2.js b/tests/baselines/reference/library-reference-2.js new file mode 100644 index 0000000000000..f908e94430935 --- /dev/null +++ b/tests/baselines/reference/library-reference-2.js @@ -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] +/// +$.foo(); + + +//// [consumer.js] +/// +$.foo(); diff --git a/tests/baselines/reference/library-reference-2.symbols b/tests/baselines/reference/library-reference-2.symbols new file mode 100644 index 0000000000000..4743737c4b6f4 --- /dev/null +++ b/tests/baselines/reference/library-reference-2.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/references/consumer.ts === +/// +$.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)) + + diff --git a/tests/baselines/reference/library-reference-2.types b/tests/baselines/reference/library-reference-2.types new file mode 100644 index 0000000000000..41167826ce0c7 --- /dev/null +++ b/tests/baselines/reference/library-reference-2.types @@ -0,0 +1,14 @@ +=== tests/cases/conformance/references/consumer.ts === +/// +$.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 + + diff --git a/tests/baselines/reference/library-reference-3.js b/tests/baselines/reference/library-reference-3.js new file mode 100644 index 0000000000000..26c5295b7ac3e --- /dev/null +++ b/tests/baselines/reference/library-reference-3.js @@ -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] +/// +$.foo(); + + +//// [consumer.js] +/// +$.foo(); diff --git a/tests/baselines/reference/library-reference-3.symbols b/tests/baselines/reference/library-reference-3.symbols new file mode 100644 index 0000000000000..1e0bc89bbe79e --- /dev/null +++ b/tests/baselines/reference/library-reference-3.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/references/src/consumer.ts === +/// +$.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)) + diff --git a/tests/baselines/reference/library-reference-3.types b/tests/baselines/reference/library-reference-3.types new file mode 100644 index 0000000000000..231dc451c22f4 --- /dev/null +++ b/tests/baselines/reference/library-reference-3.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/references/src/consumer.ts === +/// +$.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 + diff --git a/tests/baselines/reference/library-reference-4.errors.txt b/tests/baselines/reference/library-reference-4.errors.txt new file mode 100644 index 0000000000000..0090b64afc237 --- /dev/null +++ b/tests/baselines/reference/library-reference-4.errors.txt @@ -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) ==== + /// + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2304: Cannot find name 'foo'. + /// + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! 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 + + /// + 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) ==== + /// + declare var bar: any; + +==== tests/cases/conformance/references/node_modules/bar/node_modules/alpha/index.d.ts (0 errors) ==== + declare var alpha: any; + \ No newline at end of file diff --git a/tests/baselines/reference/library-reference-4.js b/tests/baselines/reference/library-reference-4.js new file mode 100644 index 0000000000000..514b3430e8b66 --- /dev/null +++ b/tests/baselines/reference/library-reference-4.js @@ -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 + +/// +declare var foo: any; + +//// [index.d.ts] +declare var alpha: any; + +//// [index.d.ts] +/// +declare var bar: any; + +//// [index.d.ts] +declare var alpha: any; + +//// [root.ts] +/// +/// + + +//// [root.js] +/// +/// diff --git a/tests/baselines/reference/library-reference-5.errors.txt b/tests/baselines/reference/library-reference-5.errors.txt new file mode 100644 index 0000000000000..3d1483af9f268 --- /dev/null +++ b/tests/baselines/reference/library-reference-5.errors.txt @@ -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) ==== + /// + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2304: Cannot find name 'foo'. + /// + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! 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 + + /// + 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) ==== + /// + declare var bar: any; + +==== tests/cases/conformance/references/node_modules/bar/node_modules/alpha/index.d.ts (0 errors) ==== + declare var alpha: {}; + \ No newline at end of file diff --git a/tests/baselines/reference/library-reference-5.js b/tests/baselines/reference/library-reference-5.js new file mode 100644 index 0000000000000..00872041253b8 --- /dev/null +++ b/tests/baselines/reference/library-reference-5.js @@ -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 + +/// +declare var foo: any; + +//// [index.d.ts] +declare var alpha: any; + +//// [index.d.ts] +/// +declare var bar: any; + +//// [index.d.ts] +declare var alpha: {}; + +//// [root.ts] +/// +/// + + +//// [root.js] +/// +/// diff --git a/tests/baselines/reference/library-reference-6.js b/tests/baselines/reference/library-reference-6.js new file mode 100644 index 0000000000000..5bcd3b8554198 --- /dev/null +++ b/tests/baselines/reference/library-reference-6.js @@ -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] +/// +var x: string = alpha.a; + + +//// [foo.js] +/// +var x = alpha.a; diff --git a/tests/baselines/reference/library-reference-6.symbols b/tests/baselines/reference/library-reference-6.symbols new file mode 100644 index 0000000000000..06128adb89c56 --- /dev/null +++ b/tests/baselines/reference/library-reference-6.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/references/src/foo.ts === +/// +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)) + diff --git a/tests/baselines/reference/library-reference-6.types b/tests/baselines/reference/library-reference-6.types new file mode 100644 index 0000000000000..843bf6990a067 --- /dev/null +++ b/tests/baselines/reference/library-reference-6.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/references/src/foo.ts === +/// +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 + diff --git a/tests/baselines/reference/library-reference-7.js b/tests/baselines/reference/library-reference-7.js new file mode 100644 index 0000000000000..ff7febbbd4cfd --- /dev/null +++ b/tests/baselines/reference/library-reference-7.js @@ -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] +/// +var x: string = alpha.a; + + +//// [foo.js] +/// +var x = alpha.a; diff --git a/tests/baselines/reference/library-reference-7.symbols b/tests/baselines/reference/library-reference-7.symbols new file mode 100644 index 0000000000000..ce0df1fa2fcfa --- /dev/null +++ b/tests/baselines/reference/library-reference-7.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/references/base/src/foo.ts === +/// +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)) + diff --git a/tests/baselines/reference/library-reference-7.types b/tests/baselines/reference/library-reference-7.types new file mode 100644 index 0000000000000..5f8b5bc23eed4 --- /dev/null +++ b/tests/baselines/reference/library-reference-7.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/references/base/src/foo.ts === +/// +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 + diff --git a/tests/baselines/reference/library-reference-8.js b/tests/baselines/reference/library-reference-8.js new file mode 100644 index 0000000000000..7357ad2214344 --- /dev/null +++ b/tests/baselines/reference/library-reference-8.js @@ -0,0 +1,24 @@ +//// [tests/cases/conformance/references/library-reference-8.ts] //// + +//// [index.d.ts] + +// Don't crash in circular library reference situations + +/// +declare var alpha: { a: string }; + +//// [index.d.ts] +/// +declare var beta: { b: string }; + +//// [foo.ts] +/// +/// +var x: string = alpha.a + beta.b; + + + +//// [foo.js] +/// +/// +var x = alpha.a + beta.b; diff --git a/tests/baselines/reference/library-reference-8.symbols b/tests/baselines/reference/library-reference-8.symbols new file mode 100644 index 0000000000000..7a7bc9e5097fe --- /dev/null +++ b/tests/baselines/reference/library-reference-8.symbols @@ -0,0 +1,28 @@ +=== tests/cases/conformance/references/foo.ts === +/// +/// +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 + +/// +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 === +/// +declare var beta: { b: string }; +>beta : Symbol(beta, Decl(index.d.ts, 1, 11)) +>b : Symbol(b, Decl(index.d.ts, 1, 19)) + diff --git a/tests/baselines/reference/library-reference-8.types b/tests/baselines/reference/library-reference-8.types new file mode 100644 index 0000000000000..2057559b498da --- /dev/null +++ b/tests/baselines/reference/library-reference-8.types @@ -0,0 +1,29 @@ +=== tests/cases/conformance/references/foo.ts === +/// +/// +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 + +/// +declare var alpha: { a: string }; +>alpha : { a: string; } +>a : string + +=== tests/cases/conformance/references/typings/beta/index.d.ts === +/// +declare var beta: { b: string }; +>beta : { b: string; } +>b : string + diff --git a/tests/cases/conformance/references/library-reference-1.ts b/tests/cases/conformance/references/library-reference-1.ts new file mode 100644 index 0000000000000..76e33ee72cf5d --- /dev/null +++ b/tests/cases/conformance/references/library-reference-1.ts @@ -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 +/// +$.foo(); diff --git a/tests/cases/conformance/references/library-reference-2.ts b/tests/cases/conformance/references/library-reference-2.ts new file mode 100644 index 0000000000000..aa128290ad421 --- /dev/null +++ b/tests/cases/conformance/references/library-reference-2.ts @@ -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 +/// +$.foo(); diff --git a/tests/cases/conformance/references/library-reference-3.ts b/tests/cases/conformance/references/library-reference-3.ts new file mode 100644 index 0000000000000..6e1fa61abb374 --- /dev/null +++ b/tests/cases/conformance/references/library-reference-3.ts @@ -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 +/// +$.foo(); diff --git a/tests/cases/conformance/references/library-reference-4.ts b/tests/cases/conformance/references/library-reference-4.ts new file mode 100644 index 0000000000000..2aaac5da78ed6 --- /dev/null +++ b/tests/cases/conformance/references/library-reference-4.ts @@ -0,0 +1,21 @@ +// @noImplicitReferences: true + +// Secondary references may be duplicated if they agree in content + +// @filename: node_modules/foo/index.d.ts +/// +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 +/// +declare var bar: any; + +// @filename: node_modules/bar/node_modules/alpha/index.d.ts +declare var alpha: any; + +// @filename: src/root.ts +/// +/// diff --git a/tests/cases/conformance/references/library-reference-5.ts b/tests/cases/conformance/references/library-reference-5.ts new file mode 100644 index 0000000000000..e6f4049b27ce3 --- /dev/null +++ b/tests/cases/conformance/references/library-reference-5.ts @@ -0,0 +1,21 @@ +// @noImplicitReferences: true + +// Secondary references may not be duplicated if they disagree in content + +// @filename: node_modules/foo/index.d.ts +/// +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 +/// +declare var bar: any; + +// @filename: node_modules/bar/node_modules/alpha/index.d.ts +declare var alpha: {}; + +// @filename: src/root.ts +/// +/// diff --git a/tests/cases/conformance/references/library-reference-6.ts b/tests/cases/conformance/references/library-reference-6.ts new file mode 100644 index 0000000000000..7c8ffc812b1d3 --- /dev/null +++ b/tests/cases/conformance/references/library-reference-6.ts @@ -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 +/// +var x: string = alpha.a; + +// @filename: tsconfig.json +{ +} diff --git a/tests/cases/conformance/references/library-reference-7.ts b/tests/cases/conformance/references/library-reference-7.ts new file mode 100644 index 0000000000000..10b6c365c8cae --- /dev/null +++ b/tests/cases/conformance/references/library-reference-7.ts @@ -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 +/// +var x: string = alpha.a; + +// @filename: tsconfig.json +{ + "compilerOptions": { + "rootDir": "base" + } +} diff --git a/tests/cases/conformance/references/library-reference-8.ts b/tests/cases/conformance/references/library-reference-8.ts new file mode 100644 index 0000000000000..36f9f129caa7d --- /dev/null +++ b/tests/cases/conformance/references/library-reference-8.ts @@ -0,0 +1,17 @@ +// @noImplicitReferences: true + +// Don't crash in circular library reference situations + +// @filename: typings/alpha/index.d.ts +/// +declare var alpha: { a: string }; + +// @filename: typings/beta/index.d.ts +/// +declare var beta: { b: string }; + +// @filename: foo.ts +/// +/// +var x: string = alpha.a + beta.b; +