Merge pull request #9607 from Microsoft/issue9542

Fix #9542 (allow files under node_modules to be included in the compilation).
This commit is contained in:
Bill Ticehurst 2016-07-11 13:47:39 -07:00 committed by GitHub
commit 2f768f622e
21 changed files with 116 additions and 32 deletions

1
.gitignore vendored
View file

@ -51,3 +51,4 @@ internal/
!**/.vscode/tasks.json
!tests/cases/projects/projectOption/**/node_modules
!tests/cases/projects/NodeModulesSearch/**/*
!tests/baselines/reference/project/nodeModules*/**/*

View file

@ -1095,13 +1095,13 @@ namespace ts {
// As all these operations happen - and are nested - within the createProgram call, they close over the below variables.
// The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses.
const maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 2;
let currentNodeModulesJsDepth = 0;
let currentNodeModulesDepth = 0;
// If a module has some of its imports skipped due to being at the depth limit under node_modules, then track
// this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed.
const modulesWithElidedImports: Map<boolean> = {};
// Track source files that are JavaScript files found by searching under node_modules, as these shouldn't be compiled.
// Track source files that are source files found by searching under node_modules, as these shouldn't be compiled.
const sourceFilesFoundSearchingNodeModules: Map<boolean> = {};
const start = new Date().getTime();
@ -1918,9 +1918,21 @@ namespace ts {
reportFileNamesDifferOnlyInCasingError(fileName, file.fileName, refFile, refPos, refEnd);
}
// If the file was previously found via a node_modules search, but is now being processed as a root file,
// then everything it sucks in may also be marked incorrectly, and needs to be checked again.
if (file && lookUp(sourceFilesFoundSearchingNodeModules, file.path) && currentNodeModulesDepth == 0) {
sourceFilesFoundSearchingNodeModules[file.path] = false;
if (!options.noResolve) {
processReferencedFiles(file, getDirectoryPath(fileName), isDefaultLib);
processTypeReferenceDirectives(file);
}
modulesWithElidedImports[file.path] = false;
processImportedModules(file, getDirectoryPath(fileName));
}
// See if we need to reprocess the imports due to prior skipped imports
if (file && lookUp(modulesWithElidedImports, file.path)) {
if (currentNodeModulesJsDepth < maxNodeModulesJsDepth) {
else if (file && lookUp(modulesWithElidedImports, file.path)) {
if (currentNodeModulesDepth < maxNodeModulesJsDepth) {
modulesWithElidedImports[file.path] = false;
processImportedModules(file, getDirectoryPath(fileName));
}
@ -1942,6 +1954,7 @@ namespace ts {
filesByName.set(path, file);
if (file) {
sourceFilesFoundSearchingNodeModules[path] = (currentNodeModulesDepth > 0);
file.path = path;
if (host.useCaseSensitiveFileNames()) {
@ -2075,13 +2088,10 @@ namespace ts {
const isJsFileFromNodeModules = isFromNodeModulesSearch && hasJavaScriptFileExtension(resolution.resolvedFileName);
if (isFromNodeModulesSearch) {
sourceFilesFoundSearchingNodeModules[resolvedPath] = true;
}
if (isJsFileFromNodeModules) {
currentNodeModulesJsDepth++;
currentNodeModulesDepth++;
}
const elideImport = isJsFileFromNodeModules && currentNodeModulesJsDepth > maxNodeModulesJsDepth;
const elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModulesJsDepth;
const shouldAddFile = resolution && !options.noResolve && i < file.imports.length && !elideImport;
if (elideImport) {
@ -2096,8 +2106,8 @@ namespace ts {
file.imports[i].end);
}
if (isJsFileFromNodeModules) {
currentNodeModulesJsDepth--;
if (isFromNodeModulesSearch) {
currentNodeModulesDepth--;
}
}
}

View file

@ -479,17 +479,27 @@ class ProjectRunner extends RunnerBase {
it("Baseline of emitted result (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
if (testCase.baselineCheck) {
const errs: Error[] = [];
ts.forEach(compilerResult.outputFiles, outputFile => {
Harness.Baseline.runBaseline("Baseline of emitted result (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
try {
return Harness.IO.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind));
}
catch (e) {
return undefined;
}
});
// There may be multiple files with different baselines. Run all and report at the end, else
// it stops copying the remaining emitted files from 'local/projectOutput' to 'local/project'.
try {
Harness.Baseline.runBaseline("Baseline of emitted result (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
try {
return Harness.IO.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind));
}
catch (e) {
return undefined;
}
});
}
catch (e) {
errs.push(e);
}
});
if (errs.length) {
throw Error(errs.join("\n "));
}
}
});

View file

@ -8,6 +8,8 @@ export {};
//// [app.ts]
import "A"
//// [index.js]
"use strict";
//// [app.js]
"use strict";
require("A");

View file

@ -13,7 +13,5 @@ export declare var y;
import y = require("a");
//// [ref.js]
var x = 1;
//// [b.js]
"use strict";

View file

@ -12,7 +12,5 @@ export declare var y;
//// [b.ts]
import y = require("a");
//// [ref.js]
var x = 1;
//// [b.js]
"use strict";

View file

@ -31,6 +31,9 @@ exports.x = 1;
//// [file2.js]
"use strict";
exports.y = 1;
//// [file4.js]
"use strict";
exports.z1 = 1;
//// [file1.js]
"use strict";
var file1_1 = require("folder2/file1");

View file

@ -0,0 +1,10 @@
var m2 = require('m2');
var rel = require('./relative');
/**
* @param {string} p1 The first param
*/
exports.f1 = function (p1) {
return 42;
};
exports.f2 = m2;
exports.rel = rel.relativeProp;

View file

@ -0,0 +1 @@
exports.relativeProp = true;

View file

@ -2,5 +2,6 @@ define(["require", "exports", "m1"], function (require, exports, m1) {
"use strict";
m1.f1("test");
m1.f2.a = "10"; // Error: Should be number
m1.rel = 42; // Error: Should be boolean
m1.f2.person.age = "10"; // OK if stopped at 2 modules: person will be "any".
});

View file

@ -1,4 +1,5 @@
maxDepthExceeded/root.ts(3,1): error TS2322: Type 'string' is not assignable to type 'number'.
maxDepthExceeded/root.ts(4,1): error TS2322: Type 'number' is not assignable to type 'boolean'.
==== entry.js (0 errors) ====
@ -10,8 +11,12 @@ maxDepthExceeded/root.ts(3,1): error TS2322: Type 'string' is not assignable to
"person": m3.person
};
==== index.js (0 errors) ====
==== relative.js (0 errors) ====
exports.relativeProp = true;
==== maxDepthExceeded/node_modules/m1/index.js (0 errors) ====
var m2 = require('m2');
var rel = require('./relative');
/**
* @param {string} p1 The first param
@ -22,11 +27,17 @@ maxDepthExceeded/root.ts(3,1): error TS2322: Type 'string' is not assignable to
exports.f2 = m2;
==== maxDepthExceeded/root.ts (1 errors) ====
exports.rel = rel.relativeProp;
==== maxDepthExceeded/root.ts (2 errors) ====
import * as m1 from "m1";
m1.f1("test");
m1.f2.a = "10"; // Error: Should be number
~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'number'.
m1.rel = 42; // Error: Should be boolean
~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'boolean'.
m1.f2.person.age = "10"; // OK if stopped at 2 modules: person will be "any".

View file

@ -8,10 +8,13 @@
"resolvedInputFiles": [
"lib.d.ts",
"maxDepthExceeded/node_modules/m2/entry.js",
"maxDepthExceeded/node_modules/m1/relative.js",
"maxDepthExceeded/node_modules/m1/index.js",
"maxDepthExceeded/root.ts"
],
"emittedFiles": [
"maxDepthExceeded/root.js"
"maxDepthExceeded/built/node_modules/m1/relative.js",
"maxDepthExceeded/built/node_modules/m1/index.js",
"maxDepthExceeded/built/root.js"
]
}

View file

@ -0,0 +1,10 @@
var m2 = require('m2');
var rel = require('./relative');
/**
* @param {string} p1 The first param
*/
exports.f1 = function (p1) {
return 42;
};
exports.f2 = m2;
exports.rel = rel.relativeProp;

View file

@ -0,0 +1 @@
exports.relativeProp = true;

View file

@ -2,4 +2,5 @@
var m1 = require("m1");
m1.f1("test");
m1.f2.a = "10"; // Error: Should be number
m1.rel = 42; // Error: Should be boolean
m1.f2.person.age = "10"; // OK if stopped at 2 modules: person will be "any".

View file

@ -1,4 +1,5 @@
maxDepthExceeded/root.ts(3,1): error TS2322: Type 'string' is not assignable to type 'number'.
maxDepthExceeded/root.ts(4,1): error TS2322: Type 'number' is not assignable to type 'boolean'.
==== entry.js (0 errors) ====
@ -10,8 +11,12 @@ maxDepthExceeded/root.ts(3,1): error TS2322: Type 'string' is not assignable to
"person": m3.person
};
==== index.js (0 errors) ====
==== relative.js (0 errors) ====
exports.relativeProp = true;
==== maxDepthExceeded/node_modules/m1/index.js (0 errors) ====
var m2 = require('m2');
var rel = require('./relative');
/**
* @param {string} p1 The first param
@ -22,11 +27,17 @@ maxDepthExceeded/root.ts(3,1): error TS2322: Type 'string' is not assignable to
exports.f2 = m2;
==== maxDepthExceeded/root.ts (1 errors) ====
exports.rel = rel.relativeProp;
==== maxDepthExceeded/root.ts (2 errors) ====
import * as m1 from "m1";
m1.f1("test");
m1.f2.a = "10"; // Error: Should be number
~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'number'.
m1.rel = 42; // Error: Should be boolean
~~~~~~
!!! error TS2322: Type 'number' is not assignable to type 'boolean'.
m1.f2.person.age = "10"; // OK if stopped at 2 modules: person will be "any".

View file

@ -8,10 +8,13 @@
"resolvedInputFiles": [
"lib.d.ts",
"maxDepthExceeded/node_modules/m2/entry.js",
"maxDepthExceeded/node_modules/m1/relative.js",
"maxDepthExceeded/node_modules/m1/index.js",
"maxDepthExceeded/root.ts"
],
"emittedFiles": [
"maxDepthExceeded/root.js"
"maxDepthExceeded/built/node_modules/m1/relative.js",
"maxDepthExceeded/built/node_modules/m1/index.js",
"maxDepthExceeded/built/root.js"
]
}

View file

@ -1,4 +1,5 @@
var m2 = require('m2');
var rel = require('./relative');
/**
* @param {string} p1 The first param
@ -8,3 +9,5 @@ exports.f1 = function(p1) {
};
exports.f2 = m2;
exports.rel = rel.relativeProp;

View file

@ -0,0 +1 @@
exports.relativeProp = true;

View file

@ -1,4 +1,6 @@
import * as m1 from "m1";
m1.f1("test");
m1.f2.a = "10"; // Error: Should be number
m1.rel = 42; // Error: Should be boolean
m1.f2.person.age = "10"; // OK if stopped at 2 modules: person will be "any".

View file

@ -1,5 +1,9 @@
{
"compilerOptions": {
"allowJs": true
}
"allowJs": true,
"maxNodeModuleJsDepth": 1, // Note: Module m1 is already included as a root file
"outDir": "built"
},
"include": ["**/*"],
"exclude": ["node_modules/m2/**/*"]
}