Check if imported file is a proper external module

This commit is contained in:
Vladimir Matveev
2015-09-10 11:36:31 -07:00
parent f2b8e4b7b6
commit 98f31635f8
28 changed files with 347 additions and 144 deletions

View File

@@ -0,0 +1,17 @@
//// [tests/cases/compiler/nodeResolution4.ts] ////
//// [ref.ts]
var x = 1;
//// [a.ts]
/// <reference path="ref.ts"/>
export var y;
//// [b.ts]
import y = require("./a");
//// [ref.js]
var x = 1;
//// [a.js]
//// [b.js]

View File

@@ -0,0 +1,14 @@
=== tests/cases/compiler/b.ts ===
import y = require("./a");
>y : Symbol(y, Decl(b.ts, 0, 0))
=== tests/cases/compiler/ref.ts ===
var x = 1;
>x : Symbol(x, Decl(ref.ts, 1, 3))
=== tests/cases/compiler/a.ts ===
/// <reference path="ref.ts"/>
export var y;
>y : Symbol(y, Decl(a.ts, 1, 10))

View File

@@ -0,0 +1,15 @@
=== tests/cases/compiler/b.ts ===
import y = require("./a");
>y : typeof y
=== tests/cases/compiler/ref.ts ===
var x = 1;
>x : number
>1 : number
=== tests/cases/compiler/a.ts ===
/// <reference path="ref.ts"/>
export var y;
>y : any

View File

@@ -0,0 +1,14 @@
tests/cases/compiler/b.ts(1,20): error TS2306: File 'tests/cases/compiler/node_modules/a.d.ts' is not a module.
==== tests/cases/compiler/b.ts (1 errors) ====
import y = require("a");
~~~
!!! error TS2306: File 'a.d.ts' is not a module.
==== tests/cases/compiler/node_modules/a.d.ts (0 errors) ====
declare module "a" {
var x: number;
}

View File

@@ -0,0 +1,13 @@
//// [tests/cases/compiler/nodeResolution5.ts] ////
//// [a.d.ts]
declare module "a" {
var x: number;
}
//// [b.ts]
import y = require("a");
//// [b.js]

View File

@@ -0,0 +1,17 @@
tests/cases/compiler/node_modules/a.d.ts(1,1): error TS2654: Proper external module that carries external typings cannot contain tripleslash references.
==== tests/cases/compiler/b.ts (0 errors) ====
import y = require("a");
==== tests/cases/compiler/node_modules/ref.ts (0 errors) ====
var x = 1;
==== tests/cases/compiler/node_modules/a.d.ts (1 errors) ====
/// <reference path="ref.ts"/>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2654: Proper external module that carries external typings cannot contain tripleslash references.
export declare var y;

View File

@@ -0,0 +1,18 @@
//// [tests/cases/compiler/nodeResolution6.ts] ////
//// [ref.ts]
var x = 1;
//// [a.d.ts]
/// <reference path="ref.ts"/>
export declare var y;
//// [b.ts]
import y = require("a");
//// [ref.js]
var x = 1;
//// [b.js]

View File

@@ -0,0 +1,14 @@
tests/cases/compiler/b.ts(1,20): error TS2306: File 'tests/cases/compiler/node_modules/a/index.d.ts' is not a module.
==== tests/cases/compiler/b.ts (1 errors) ====
import y = require("a");
~~~
!!! error TS2306: File 'index.d.ts' is not a module.
==== tests/cases/compiler/node_modules/a/index.d.ts (0 errors) ====
declare module "a" {
var x: number;
}

View File

@@ -0,0 +1,13 @@
//// [tests/cases/compiler/nodeResolution7.ts] ////
//// [index.d.ts]
declare module "a" {
var x: number;
}
//// [b.ts]
import y = require("a");
//// [b.js]

View File

@@ -0,0 +1,16 @@
tests/cases/compiler/node_modules/a/index.d.ts(1,1): error TS2654: Proper external module that carries external typings cannot contain tripleslash references.
==== tests/cases/compiler/b.ts (0 errors) ====
import y = require("a");
==== tests/cases/compiler/node_modules/a/ref.ts (0 errors) ====
var x = 1;
==== tests/cases/compiler/node_modules/a/index.d.ts (1 errors) ====
/// <reference path="ref.ts"/>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2654: Proper external module that carries external typings cannot contain tripleslash references.
export declare var y;

View File

@@ -0,0 +1,17 @@
//// [tests/cases/compiler/nodeResolution8.ts] ////
//// [ref.ts]
var x = 1;
//// [index.d.ts]
/// <reference path="ref.ts"/>
export declare var y;
//// [b.ts]
import y = require("a");
//// [ref.js]
var x = 1;
//// [b.js]

View File

@@ -0,0 +1,12 @@
// @module: commonjs
// @moduleResolution: node
// @filename: ref.ts
var x = 1;
// @filename: a.ts
/// <reference path="ref.ts"/>
export var y;
// @filename: b.ts
import y = require("./a");

View File

@@ -0,0 +1,10 @@
// @module: commonjs
// @moduleResolution: node
// @filename: node_modules/a.d.ts
declare module "a" {
var x: number;
}
// @filename: b.ts
import y = require("a");

View File

@@ -0,0 +1,13 @@
// @module: commonjs
// @moduleResolution: node
// @filename: node_modules/ref.ts
var x = 1;
// @filename: node_modules/a.d.ts
/// <reference path="ref.ts"/>
export declare var y;
// @filename: b.ts
import y = require("a");

View File

@@ -0,0 +1,10 @@
// @module: commonjs
// @moduleResolution: node
// @filename: node_modules/a/index.d.ts
declare module "a" {
var x: number;
}
// @filename: b.ts
import y = require("a");

View File

@@ -0,0 +1,13 @@
// @module: commonjs
// @moduleResolution: node
// @filename: node_modules/a/ref.ts
var x = 1;
// @filename: node_modules/a/index.d.ts
/// <reference path="ref.ts"/>
export declare var y;
// @filename: b.ts
import y = require("a");

View File

@@ -40,8 +40,9 @@ module ts {
let containingFile = { name: containingFileName }
let moduleFile = { name: moduleFileNameNoExt + ext }
let resolution = nodeModuleNameResolver(moduleName, containingFile.name, createModuleResolutionHost(containingFile, moduleFile));
assert.equal(resolution.resolvedFileName, moduleFile.name);
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
assert.equal(!!resolution.resolvedModule.shouldBeProperExternalModule, false);
let failedLookupLocations: string[] = [];
let dir = getDirectoryPath(containingFileName);
for (let e of supportedExtensions) {
@@ -78,7 +79,8 @@ module ts {
let packageJson = { name: packageJsonFileName, content: JSON.stringify({ "typings": fieldRef }) };
let moduleFile = { name: moduleFileName };
let resolution = nodeModuleNameResolver(moduleName, containingFile.name, createModuleResolutionHost(containingFile, packageJson, moduleFile));
assert.equal(resolution.resolvedFileName, moduleFile.name);
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
assert.equal(!!resolution.resolvedModule.shouldBeProperExternalModule, false);
// expect three failed lookup location - attempt to load module as file with all supported extensions
assert.equal(resolution.failedLookupLocations.length, 3);
}
@@ -95,7 +97,8 @@ module ts {
let packageJson = {name: "/a/b/foo/package.json", content: JSON.stringify({main: "/c/d"})};
let indexFile = { name: "/a/b/foo/index.d.ts" };
let resolution = nodeModuleNameResolver("./foo", containingFile.name, createModuleResolutionHost(containingFile, packageJson, indexFile));
assert.equal(resolution.resolvedFileName, indexFile.name);
assert.equal(resolution.resolvedModule.resolvedFileName, indexFile.name);
assert.equal(!!resolution.resolvedModule.shouldBeProperExternalModule, false);
assert.deepEqual(resolution.failedLookupLocations, [
"/a/b/foo.ts",
"/a/b/foo.tsx",
@@ -111,7 +114,7 @@ module ts {
let containingFile = { name: "/a/b/c/d/e.ts" };
let moduleFile = { name: "/a/b/node_modules/foo.ts" };
let resolution = nodeModuleNameResolver("foo", containingFile.name, createModuleResolutionHost(containingFile, moduleFile));
assert.equal(resolution.resolvedFileName, undefined);
assert.equal(resolution.resolvedModule, undefined);
assert.deepEqual(resolution.failedLookupLocations, [
"/a/b/c/d/node_modules/foo.d.ts",
"/a/b/c/d/node_modules/foo/package.json",
@@ -135,14 +138,16 @@ module ts {
let containingFile = { name: "/a/b/c/d/e.ts" };
let moduleFile = { name: "/a/b/node_modules/foo.d.ts" };
let resolution = nodeModuleNameResolver("foo", containingFile.name, createModuleResolutionHost(containingFile, moduleFile));
assert.equal(resolution.resolvedFileName, moduleFile.name);
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
assert.equal(resolution.resolvedModule.shouldBeProperExternalModule, true);
});
it("load module as directory", () => {
let containingFile = { name: "/a/node_modules/b/c/node_modules/d/e.ts" };
let moduleFile = { name: "/a/node_modules/foo/index.d.ts" };
let resolution = nodeModuleNameResolver("foo", containingFile.name, createModuleResolutionHost(containingFile, moduleFile));
assert.equal(resolution.resolvedFileName, moduleFile.name);
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
assert.equal(resolution.resolvedModule.shouldBeProperExternalModule, true);
assert.deepEqual(resolution.failedLookupLocations, [
"/a/node_modules/b/c/node_modules/d/node_modules/foo.d.ts",
"/a/node_modules/b/c/node_modules/d/node_modules/foo/package.json",
@@ -158,64 +163,4 @@ module ts {
]);
});
});
describe("BaseUrl mode", () => {
it ("load module as relative url", () => {
function test(containingFileName: string, moduleFileName: string, moduleName: string): void {
let containingFile = {name: containingFileName };
let moduleFile = { name: moduleFileName };
let resolution = baseUrlModuleNameResolver(moduleName, containingFile.name, "<some-value>", createModuleResolutionHost(containingFile, moduleFile));
assert.equal(resolution.resolvedFileName, moduleFile.name);
let expectedFailedLookupLocations: string[] = [];
let moduleNameHasExt = forEach(supportedExtensions, e => fileExtensionIs(moduleName, e));
if (!moduleNameHasExt) {
let dir = getDirectoryPath(containingFileName);
// add candidates with extensions that precede extension of the actual module name file in the list of supportd extensions
for (let ext of supportedExtensions) {
let hasExtension = ext !== ".ts"
? fileExtensionIs(moduleFileName, ext)
: fileExtensionIs(moduleFileName, ".ts") && !fileExtensionIs(moduleFileName, ".d.ts");
if (hasExtension) {
break;
}
else {
expectedFailedLookupLocations.push(normalizePath(combinePaths(dir, moduleName + ext)));
}
}
}
assert.deepEqual(resolution.failedLookupLocations, expectedFailedLookupLocations)
}
test("/a/b/c/d.ts", "/foo.ts", "/foo");
test("/a/b/c/d.ts", "/foo.d.ts", "/foo");
test("/a/b/c/d.ts", "/foo.tsx", "/foo");
test("/a/b/c/d.ts", "/a/b/c/foo.ts", "./foo");
test("/a/b/c/d.ts", "/a/b/c/foo.d.ts", "./foo");
test("/a/b/c/d.ts", "/a/b/c/foo.tsx", "./foo");
test("/a/b/c/d.ts", "/a/b/foo.ts", "../foo");
test("/a/b/c/d.ts", "/a/b/foo.d.ts", "../foo");
test("/a/b/c/d.ts", "/a/b/foo.tsx", "../foo");
});
it ("load module using base url", () => {
function test(containingFileName: string, moduleFileName: string, moduleName: string, baseUrl: string): void {
let containingFile = { name: containingFileName };
let moduleFile = { name: moduleFileName };
let resolution = baseUrlModuleNameResolver(moduleName, containingFileName, baseUrl, createModuleResolutionHost(containingFile, moduleFile));
assert.equal(resolution.resolvedFileName, moduleFile.name);
}
test("/a/base/c/d.ts", "/a/base/c/d/e.ts", "c/d/e", "/a/base");
test("/a/base/c/d.ts", "/a/base/c/d/e.d.ts", "c/d/e", "/a/base");
test("/a/base/c/d.ts", "/a/base/c/d/e.tsx", "c/d/e", "/a/base");
});
});
}

View File

@@ -160,7 +160,7 @@ module ts {
return size;
}
function checkResolvedModulesCache(program: Program, fileName: string, expectedContent: Map<string>): void {
function checkResolvedModulesCache(program: Program, fileName: string, expectedContent: Map<ResolvedModule>): void {
let file = program.getSourceFile(fileName);
assert.isTrue(file !== undefined, `cannot find file ${fileName}`);
if (expectedContent === undefined) {
@@ -175,7 +175,16 @@ module ts {
for (let id in expectedContent) {
if (hasProperty(expectedContent, id)) {
assert.isTrue(hasProperty(file.resolvedModules, id), `expected ${id} to be found in resolved modules`);
assert.isTrue(expectedContent[id] === file.resolvedModules[id], `expected '${expectedContent[id]}' to be equal to '${file.resolvedModules[id]}'`);
if (expectedContent[id]) {
const expected = expectedContent[id];
const actual = file.resolvedModules[id];
assert.isTrue(actual !== undefined);
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
assert.isTrue(expected.shouldBeProperExternalModule === actual.shouldBeProperExternalModule, `'shouldBeProperExternalModule': expected '${expected.shouldBeProperExternalModule}' to be equal to '${actual.shouldBeProperExternalModule}'`);
}
else {
assert.isTrue(file.resolvedModules[id] === undefined);
}
}
}
}
@@ -237,7 +246,7 @@ module ts {
var options: CompilerOptions = { target };
var program_1 = newProgram(files, ["a.ts"], options);
checkResolvedModulesCache(program_1, "a.ts", { "b": "b.ts" });
checkResolvedModulesCache(program_1, "a.ts", { "b": { resolvedFileName: "b.ts" } });
checkResolvedModulesCache(program_1, "b.ts", undefined);
var program_2 = updateProgram(program_1, ["a.ts"], options, files => {
@@ -246,7 +255,7 @@ module ts {
assert.isTrue(program_1.structureIsReused);
// content of resolution cache should not change
checkResolvedModulesCache(program_1, "a.ts", { "b": "b.ts" });
checkResolvedModulesCache(program_1, "a.ts", { "b": { resolvedFileName: "b.ts" } });
checkResolvedModulesCache(program_1, "b.ts", undefined);
// imports has changed - program is not reused
@@ -263,7 +272,7 @@ module ts {
files[0].text = files[0].text.updateImportsAndExports(newImports);
});
assert.isTrue(!program_3.structureIsReused);
checkResolvedModulesCache(program_4, "a.ts", { "b": "b.ts", "c": undefined });
checkResolvedModulesCache(program_4, "a.ts", { "b": { resolvedFileName: "b.ts" }, "c": undefined });
});
})
}