Skip to content

Commit 62370a0

Browse files
committed
addressed PR feedback
1 parent 25cc97b commit 62370a0

7 files changed

Lines changed: 80 additions & 17 deletions

File tree

src/compiler/commandLineParser.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,8 @@ namespace ts {
300300
// use type = object to copy the value as-is
301301
name: "rootDirs",
302302
type: "object",
303-
isTSConfigOnly: true
303+
isTSConfigOnly: true,
304+
isFilePath: true
304305
},
305306
{
306307
name: "traceModuleResolution",
@@ -595,7 +596,36 @@ namespace ts {
595596
}
596597
}
597598
if (opt.isFilePath) {
598-
value = normalizePath(combinePaths(basePath, value));
599+
switch (typeof value) {
600+
case "string":
601+
value = normalizePath(combinePaths(basePath, value));
602+
break;
603+
case "object":
604+
// "object" options with 'isFilePath' = true expected to be string arrays
605+
let paths: string[] = [];
606+
let invalidOptionType = false;
607+
if (!isArray(value)) {
608+
invalidOptionType = true;
609+
}
610+
else {
611+
for (const element of <any[]>value) {
612+
if (typeof element === "string") {
613+
paths.push(normalizePath(combinePaths(basePath, element)));
614+
}
615+
else {
616+
invalidOptionType = true;
617+
break;
618+
}
619+
}
620+
}
621+
if (invalidOptionType) {
622+
errors.push(createCompilerDiagnostic(Diagnostics.Option_0_should_have_array_of_strings_as_a_value, opt.name));
623+
}
624+
else {
625+
value = paths;
626+
}
627+
break;
628+
}
599629
if (value === "") {
600630
value = ".";
601631
}

src/compiler/core.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ namespace ts {
7474
GreaterThan = 1
7575
}
7676

77-
export interface StringSet extends Map<any> { }
77+
/* @internal */
78+
export function isArray(obj: any): boolean {
79+
return Array.isArray ? Array.isArray(obj) : typeof obj === "object" && obj instanceof Array;
80+
}
7881

7982
/**
8083
* Iterates through 'array' by index and performs the callback on each element of array until the callback

src/compiler/diagnosticMessages.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2296,7 +2296,6 @@
22962296
"category": "Error",
22972297
"code": 6064
22982298
},
2299-
23002299
"Enables experimental support for ES7 decorators.": {
23012300
"category": "Message",
23022301
"code": 6065
@@ -2469,6 +2468,18 @@
24692468
"category": "Message",
24702469
"code": 6109
24712470
},
2471+
"Base url: '{0}'.": {
2472+
"category": "Message",
2473+
"code": 6110
2474+
},
2475+
"Option '{0}' should have array of strings as a value.": {
2476+
"category": "Error",
2477+
"code": 6111
2478+
},
2479+
"Checking if '{0}' is the longest matching prefix for '{1}' - '{2}'.": {
2480+
"category": "Message",
2481+
"code": 6112
2482+
},
24722483
"Variable '{0}' implicitly has an '{1}' type.": {
24732484
"category": "Error",
24742485
"code": 7005

src/compiler/program.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ namespace ts {
179179
// NOTE: traceEnabled check is delibirately no inside the 'trace' at evert callside to avoid runtime impact of calling vararg function
180180
const traceEnabled = isTraceEnabled(compilerOptions, host);
181181

182+
if (traceEnabled) {
183+
trace(host, Diagnostics.Base_url_Colon_0, baseUrl);
184+
}
185+
182186
if (isRootedDiskPath(moduleName)) {
183187
if (traceEnabled) {
184188
trace(host, Diagnostics.Resolving_rooted_module_name_0_use_it_as_a_candidate_location, moduleName);
@@ -211,6 +215,7 @@ namespace ts {
211215
function baseUrlResolveRelativeModuleName(moduleName: string, containingFile: string, baseUrl: string, supportedExtensions: string[], compilerOptions: CompilerOptions, host: ModuleResolutionHost, traceEnabled: boolean): ResolvedModuleWithFailedLookupLocations {
212216
const failedLookupLocations: string[] = [];
213217

218+
// we always pass absolute path to containing file so candidate location is also absolute
214219
const containingDirectory = getDirectoryPath(containingFile);
215220
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
216221

@@ -225,14 +230,24 @@ namespace ts {
225230

226231
let matchedPrefix: string;
227232
for (const rootDir of compilerOptions.rootDirs) {
228-
let normalizedRoot = getNormalizedAbsolutePath(rootDir, baseUrl);
233+
// rootDirs are expected to be absolute
234+
let normalizedRoot = normalizePath(rootDir);
229235
if (!endsWith(normalizedRoot, directorySeparator)) {
230236
normalizedRoot += directorySeparator;
231237
}
232-
if (startsWith(candidate, normalizedRoot) && (matchedPrefix === undefined || matchedPrefix.length < normalizedRoot.length)) {
238+
const isLongestMatchingPrefix =
239+
startsWith(candidate, normalizedRoot) &&
240+
(matchedPrefix === undefined || matchedPrefix.length < normalizedRoot.length);
241+
242+
if (traceEnabled) {
243+
trace(host, Diagnostics.Checking_if_0_is_the_longest_matching_prefix_for_1_2, normalizedRoot, candidate, isLongestMatchingPrefix);
244+
}
245+
246+
if (isLongestMatchingPrefix) {
233247
matchedPrefix = normalizedRoot;
234248
}
235249
}
250+
236251
if (matchedPrefix) {
237252
const suffix = candidate.substr(matchedPrefix.length);
238253
if (traceEnabled) {
@@ -241,19 +256,20 @@ namespace ts {
241256

242257
return baseUrlResolveNonRelativeModuleName(suffix, baseUrl, supportedExtensions, compilerOptions, host, traceEnabled);
243258
}
244-
return { resolvedModule: undefined, failedLookupLocations };
259+
260+
// rootDirs does not contain prefix for candidate - fallthrough to load file from candidate location.
245261
}
246262
else {
247263
if (traceEnabled) {
248264
trace(host, Diagnostics.rootDirs_option_is_not_specified_using_0_as_candidate_location, candidate);
249265
}
250-
251-
const resolvedFileName = loadModuleFromFile(supportedExtensions, candidate, failedLookupLocations, host, traceEnabled);
252-
return {
253-
resolvedModule: resolvedFileName ? { resolvedFileName } : undefined,
254-
failedLookupLocations
255-
};
256266
}
267+
268+
const resolvedFileName = loadModuleFromFile(supportedExtensions, candidate, failedLookupLocations, host, traceEnabled);
269+
return {
270+
resolvedModule: resolvedFileName ? { resolvedFileName } : undefined,
271+
failedLookupLocations
272+
};
257273
}
258274

259275
function baseUrlResolveNonRelativeModuleName(moduleName: string, baseUrl: string, supportedExtensions: string[], compilerOptions: CompilerOptions, host: ModuleResolutionHost, traceEnabled: boolean): ResolvedModuleWithFailedLookupLocations {

src/harness/harness.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,9 @@ namespace Harness {
10051005
if (options.inferredBaseUrl) {
10061006
options.inferredBaseUrl = ts.getNormalizedAbsolutePath(options.inferredBaseUrl, currentDirectory);
10071007
}
1008+
if (options.rootDirs) {
1009+
options.rootDirs = ts.map(options.rootDirs, d => ts.getNormalizedAbsolutePath(d, currentDirectory));
1010+
}
10081011

10091012
const programFiles: TestFile[] = inputFiles.slice();
10101013
// Files from built\local that are requested by test "@includeBuiltFiles" to be in the context.

tests/cases/compiler/pathMappingBasedModuleResolution10_2.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
]
1515
},
1616
"rootDirs": [
17-
".",
18-
"./generated"
17+
"./src/",
18+
"./src/generated"
1919
]
2020
}
2121
}

tests/cases/unittests/moduleResolution.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,8 @@ import b = require("./moduleB.ts");
485485
]
486486
},
487487
rootDirs: [
488-
".",
489-
"./generated/"
488+
"/root",
489+
"/root/generated/"
490490
]
491491
};
492492
{

0 commit comments

Comments
 (0)