diff --git a/bin/tsc.js b/bin/tsc.js index 870baaf7146..b7e61329337 100644 --- a/bin/tsc.js +++ b/bin/tsc.js @@ -1399,6 +1399,8 @@ var ts; Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: ts.DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." }, Do_not_emit_declarations_for_code_that_has_an_internal_annotation: { code: 6056, category: ts.DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." }, Preserve_new_lines_when_emitting_code: { code: 6057, category: ts.DiagnosticCategory.Message, key: "Preserve new-lines when emitting code." }, + Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir: { code: 6058, category: ts.DiagnosticCategory.Message, key: "Specifies the root directory of input files. Use to control the output directory structure with --outDir." }, + File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files: { code: 6059, category: ts.DiagnosticCategory.Error, key: "File '{0}' is not under 'rootDir' '{1}'. 'rootDir' is expected to contain all source files." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." }, @@ -11553,7 +11555,7 @@ var ts; return type; } function combineTypeMappers(mapper1, mapper2) { - return function (t) { return mapper2(mapper1(t)); }; + return function (t) { return instantiateType(mapper1(t), mapper2); }; } function instantiateTypeParameter(typeParameter, mapper) { var result = createType(512); @@ -24663,6 +24665,53 @@ var ts; return findSourceFile(fileName, false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos); } } + function computeCommonSourceDirectory(sourceFiles) { + var commonPathComponents; + var currentDirectory = host.getCurrentDirectory(); + ts.forEach(files, function (sourceFile) { + if (ts.isDeclarationFile(sourceFile)) { + return; + } + var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, currentDirectory); + sourcePathComponents.pop(); + if (!commonPathComponents) { + commonPathComponents = sourcePathComponents; + return; + } + for (var i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { + if (commonPathComponents[i] !== sourcePathComponents[i]) { + if (i === 0) { + diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); + return; + } + commonPathComponents.length = i; + break; + } + } + if (sourcePathComponents.length < commonPathComponents.length) { + commonPathComponents.length = sourcePathComponents.length; + } + }); + return ts.getNormalizedPathFromPathComponents(commonPathComponents); + } + function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { + var allFilesBelongToPath = true; + if (sourceFiles) { + var currentDirectory = host.getCurrentDirectory(); + var absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + for (var _i = 0; _i < sourceFiles.length; _i++) { + var sourceFile = sourceFiles[_i]; + if (!ts.isDeclarationFile(sourceFile)) { + var absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { + diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); + allFilesBelongToPath = false; + } + } + } + } + return allFilesBelongToPath; + } function verifyCompilerOptions() { if (options.separateCompilation) { if (options.sourceMap) { @@ -24710,34 +24759,13 @@ var ts; options.sourceRoot || (options.mapRoot && (!options.out || firstExternalModuleSourceFile !== undefined))) { - var commonPathComponents; - ts.forEach(files, function (sourceFile) { - if (!(sourceFile.flags & 2048) - && !ts.fileExtensionIs(sourceFile.fileName, ".js")) { - var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, host.getCurrentDirectory()); - sourcePathComponents.pop(); - if (commonPathComponents) { - for (var i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) { - if (commonPathComponents[i] !== sourcePathComponents[i]) { - if (i === 0) { - diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); - return; - } - commonPathComponents.length = i; - break; - } - } - if (sourcePathComponents.length < commonPathComponents.length) { - commonPathComponents.length = sourcePathComponents.length; - } - } - else { - commonPathComponents = sourcePathComponents; - } - } - }); - commonSourceDirectory = ts.getNormalizedPathFromPathComponents(commonPathComponents); - if (commonSourceDirectory) { + if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { + commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, host.getCurrentDirectory()); + } + else { + commonSourceDirectory = computeCommonSourceDirectory(files); + } + if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { commonSourceDirectory += ts.directorySeparator; } } @@ -24864,6 +24892,13 @@ var ts; type: "boolean", description: ts.Diagnostics.Do_not_emit_comments_to_output }, + { + name: "rootDir", + type: "string", + isFilePath: true, + description: ts.Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir, + paramType: ts.Diagnostics.LOCATION + }, { name: "separateCompilation", type: "boolean" diff --git a/bin/tsserver.js b/bin/tsserver.js index 5f71004b16b..6c0670b47d5 100644 --- a/bin/tsserver.js +++ b/bin/tsserver.js @@ -1399,6 +1399,8 @@ var ts; Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: ts.DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." }, Do_not_emit_declarations_for_code_that_has_an_internal_annotation: { code: 6056, category: ts.DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." }, Preserve_new_lines_when_emitting_code: { code: 6057, category: ts.DiagnosticCategory.Message, key: "Preserve new-lines when emitting code." }, + Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir: { code: 6058, category: ts.DiagnosticCategory.Message, key: "Specifies the root directory of input files. Use to control the output directory structure with --outDir." }, + File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files: { code: 6059, category: ts.DiagnosticCategory.Error, key: "File '{0}' is not under 'rootDir' '{1}'. 'rootDir' is expected to contain all source files." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." }, @@ -2796,6 +2798,13 @@ var ts; type: "boolean", description: ts.Diagnostics.Do_not_emit_comments_to_output }, + { + name: "rootDir", + type: "string", + isFilePath: true, + description: ts.Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir, + paramType: ts.Diagnostics.LOCATION + }, { name: "separateCompilation", type: "boolean" @@ -11896,7 +11905,7 @@ var ts; return type; } function combineTypeMappers(mapper1, mapper2) { - return function (t) { return mapper2(mapper1(t)); }; + return function (t) { return instantiateType(mapper1(t), mapper2); }; } function instantiateTypeParameter(typeParameter, mapper) { var result = createType(512); @@ -25006,6 +25015,53 @@ var ts; return findSourceFile(fileName, false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos); } } + function computeCommonSourceDirectory(sourceFiles) { + var commonPathComponents; + var currentDirectory = host.getCurrentDirectory(); + ts.forEach(files, function (sourceFile) { + if (ts.isDeclarationFile(sourceFile)) { + return; + } + var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, currentDirectory); + sourcePathComponents.pop(); + if (!commonPathComponents) { + commonPathComponents = sourcePathComponents; + return; + } + for (var i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { + if (commonPathComponents[i] !== sourcePathComponents[i]) { + if (i === 0) { + diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); + return; + } + commonPathComponents.length = i; + break; + } + } + if (sourcePathComponents.length < commonPathComponents.length) { + commonPathComponents.length = sourcePathComponents.length; + } + }); + return ts.getNormalizedPathFromPathComponents(commonPathComponents); + } + function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { + var allFilesBelongToPath = true; + if (sourceFiles) { + var currentDirectory = host.getCurrentDirectory(); + var absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + for (var _i = 0; _i < sourceFiles.length; _i++) { + var sourceFile = sourceFiles[_i]; + if (!ts.isDeclarationFile(sourceFile)) { + var absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { + diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); + allFilesBelongToPath = false; + } + } + } + } + return allFilesBelongToPath; + } function verifyCompilerOptions() { if (options.separateCompilation) { if (options.sourceMap) { @@ -25053,34 +25109,13 @@ var ts; options.sourceRoot || (options.mapRoot && (!options.out || firstExternalModuleSourceFile !== undefined))) { - var commonPathComponents; - ts.forEach(files, function (sourceFile) { - if (!(sourceFile.flags & 2048) - && !ts.fileExtensionIs(sourceFile.fileName, ".js")) { - var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, host.getCurrentDirectory()); - sourcePathComponents.pop(); - if (commonPathComponents) { - for (var i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) { - if (commonPathComponents[i] !== sourcePathComponents[i]) { - if (i === 0) { - diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); - return; - } - commonPathComponents.length = i; - break; - } - } - if (sourcePathComponents.length < commonPathComponents.length) { - commonPathComponents.length = sourcePathComponents.length; - } - } - else { - commonPathComponents = sourcePathComponents; - } - } - }); - commonSourceDirectory = ts.getNormalizedPathFromPathComponents(commonPathComponents); - if (commonSourceDirectory) { + if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { + commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, host.getCurrentDirectory()); + } + else { + commonSourceDirectory = computeCommonSourceDirectory(files); + } + if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { commonSourceDirectory += ts.directorySeparator; } } @@ -34835,6 +34870,9 @@ var ts; if (lineText.charAt(i) == " ") { indentPosition--; } + else if (lineText.charAt(i) == "\t") { + indentPosition -= editorOptions.IndentSize; + } else { break; } diff --git a/bin/typescript.d.ts b/bin/typescript.d.ts index 2ce77b9fb70..f86da199763 100644 --- a/bin/typescript.d.ts +++ b/bin/typescript.d.ts @@ -1095,6 +1095,7 @@ declare module "typescript" { preserveConstEnums?: boolean; project?: string; removeComments?: boolean; + rootDir?: string; sourceMap?: boolean; sourceRoot?: string; suppressImplicitAnyIndexErrors?: boolean; diff --git a/bin/typescript.js b/bin/typescript.js index 6c206d1b87e..6db943d4742 100644 --- a/bin/typescript.js +++ b/bin/typescript.js @@ -2133,6 +2133,8 @@ var ts; Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: ts.DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." }, Do_not_emit_declarations_for_code_that_has_an_internal_annotation: { code: 6056, category: ts.DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." }, Preserve_new_lines_when_emitting_code: { code: 6057, category: ts.DiagnosticCategory.Message, key: "Preserve new-lines when emitting code." }, + Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir: { code: 6058, category: ts.DiagnosticCategory.Message, key: "Specifies the root directory of input files. Use to control the output directory structure with --outDir." }, + File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files: { code: 6059, category: ts.DiagnosticCategory.Error, key: "File '{0}' is not under 'rootDir' '{1}'. 'rootDir' is expected to contain all source files." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." }, @@ -14105,7 +14107,7 @@ var ts; return type; } function combineTypeMappers(mapper1, mapper2) { - return function (t) { return mapper2(mapper1(t)); }; + return function (t) { return instantiateType(mapper1(t), mapper2); }; } function instantiateTypeParameter(typeParameter, mapper) { var result = createType(512 /* TypeParameter */); @@ -29095,6 +29097,57 @@ var ts; return findSourceFile(fileName, false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos); } } + function computeCommonSourceDirectory(sourceFiles) { + var commonPathComponents; + var currentDirectory = host.getCurrentDirectory(); + ts.forEach(files, function (sourceFile) { + // Each file contributes into common source file path + if (ts.isDeclarationFile(sourceFile)) { + return; + } + var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, currentDirectory); + sourcePathComponents.pop(); // The base file name is not part of the common directory path + if (!commonPathComponents) { + // first file + commonPathComponents = sourcePathComponents; + return; + } + for (var i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { + if (commonPathComponents[i] !== sourcePathComponents[i]) { + if (i === 0) { + diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); + return; + } + // New common path found that is 0 -> i-1 + commonPathComponents.length = i; + break; + } + } + // If the sourcePathComponents was shorter than the commonPathComponents, truncate to the sourcePathComponents + if (sourcePathComponents.length < commonPathComponents.length) { + commonPathComponents.length = sourcePathComponents.length; + } + }); + return ts.getNormalizedPathFromPathComponents(commonPathComponents); + } + function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { + var allFilesBelongToPath = true; + if (sourceFiles) { + var currentDirectory = host.getCurrentDirectory(); + var absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + for (var _i = 0; _i < sourceFiles.length; _i++) { + var sourceFile = sourceFiles[_i]; + if (!ts.isDeclarationFile(sourceFile)) { + var absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { + diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); + allFilesBelongToPath = false; + } + } + } + } + return allFilesBelongToPath; + } function verifyCompilerOptions() { if (options.separateCompilation) { if (options.sourceMap) { @@ -29147,38 +29200,15 @@ var ts; options.sourceRoot || (options.mapRoot && (!options.out || firstExternalModuleSourceFile !== undefined))) { - var commonPathComponents; - ts.forEach(files, function (sourceFile) { - // Each file contributes into common source file path - if (!(sourceFile.flags & 2048 /* DeclarationFile */) - && !ts.fileExtensionIs(sourceFile.fileName, ".js")) { - var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, host.getCurrentDirectory()); - sourcePathComponents.pop(); // FileName is not part of directory - if (commonPathComponents) { - for (var i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) { - if (commonPathComponents[i] !== sourcePathComponents[i]) { - if (i === 0) { - diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); - return; - } - // New common path found that is 0 -> i-1 - commonPathComponents.length = i; - break; - } - } - // If the fileComponent path completely matched and less than already found update the length - if (sourcePathComponents.length < commonPathComponents.length) { - commonPathComponents.length = sourcePathComponents.length; - } - } - else { - // first file - commonPathComponents = sourcePathComponents; - } - } - }); - commonSourceDirectory = ts.getNormalizedPathFromPathComponents(commonPathComponents); - if (commonSourceDirectory) { + if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { + // If a rootDir is specified and is valid use it as the commonSourceDirectory + commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, host.getCurrentDirectory()); + } + else { + // Compute the commonSourceDirectory from the input files + commonSourceDirectory = computeCommonSourceDirectory(files); + } + if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { // Make sure directory path ends with directory separator so this string can directly // used to replace with "" to get the relative path of the source file and the relative path doesn't // start with / making it rooted path @@ -29309,6 +29339,13 @@ var ts; type: "boolean", description: ts.Diagnostics.Do_not_emit_comments_to_output }, + { + name: "rootDir", + type: "string", + isFilePath: true, + description: ts.Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir, + paramType: ts.Diagnostics.LOCATION + }, { name: "separateCompilation", type: "boolean" diff --git a/bin/typescriptServices.d.ts b/bin/typescriptServices.d.ts index e6d06765c27..cd8ee05add4 100644 --- a/bin/typescriptServices.d.ts +++ b/bin/typescriptServices.d.ts @@ -1095,6 +1095,7 @@ declare module ts { preserveConstEnums?: boolean; project?: string; removeComments?: boolean; + rootDir?: string; sourceMap?: boolean; sourceRoot?: string; suppressImplicitAnyIndexErrors?: boolean; diff --git a/bin/typescriptServices.js b/bin/typescriptServices.js index 6c206d1b87e..6db943d4742 100644 --- a/bin/typescriptServices.js +++ b/bin/typescriptServices.js @@ -2133,6 +2133,8 @@ var ts; Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: ts.DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." }, Do_not_emit_declarations_for_code_that_has_an_internal_annotation: { code: 6056, category: ts.DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." }, Preserve_new_lines_when_emitting_code: { code: 6057, category: ts.DiagnosticCategory.Message, key: "Preserve new-lines when emitting code." }, + Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir: { code: 6058, category: ts.DiagnosticCategory.Message, key: "Specifies the root directory of input files. Use to control the output directory structure with --outDir." }, + File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files: { code: 6059, category: ts.DiagnosticCategory.Error, key: "File '{0}' is not under 'rootDir' '{1}'. 'rootDir' is expected to contain all source files." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." }, @@ -14105,7 +14107,7 @@ var ts; return type; } function combineTypeMappers(mapper1, mapper2) { - return function (t) { return mapper2(mapper1(t)); }; + return function (t) { return instantiateType(mapper1(t), mapper2); }; } function instantiateTypeParameter(typeParameter, mapper) { var result = createType(512 /* TypeParameter */); @@ -29095,6 +29097,57 @@ var ts; return findSourceFile(fileName, false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos); } } + function computeCommonSourceDirectory(sourceFiles) { + var commonPathComponents; + var currentDirectory = host.getCurrentDirectory(); + ts.forEach(files, function (sourceFile) { + // Each file contributes into common source file path + if (ts.isDeclarationFile(sourceFile)) { + return; + } + var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, currentDirectory); + sourcePathComponents.pop(); // The base file name is not part of the common directory path + if (!commonPathComponents) { + // first file + commonPathComponents = sourcePathComponents; + return; + } + for (var i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { + if (commonPathComponents[i] !== sourcePathComponents[i]) { + if (i === 0) { + diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); + return; + } + // New common path found that is 0 -> i-1 + commonPathComponents.length = i; + break; + } + } + // If the sourcePathComponents was shorter than the commonPathComponents, truncate to the sourcePathComponents + if (sourcePathComponents.length < commonPathComponents.length) { + commonPathComponents.length = sourcePathComponents.length; + } + }); + return ts.getNormalizedPathFromPathComponents(commonPathComponents); + } + function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { + var allFilesBelongToPath = true; + if (sourceFiles) { + var currentDirectory = host.getCurrentDirectory(); + var absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + for (var _i = 0; _i < sourceFiles.length; _i++) { + var sourceFile = sourceFiles[_i]; + if (!ts.isDeclarationFile(sourceFile)) { + var absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { + diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); + allFilesBelongToPath = false; + } + } + } + } + return allFilesBelongToPath; + } function verifyCompilerOptions() { if (options.separateCompilation) { if (options.sourceMap) { @@ -29147,38 +29200,15 @@ var ts; options.sourceRoot || (options.mapRoot && (!options.out || firstExternalModuleSourceFile !== undefined))) { - var commonPathComponents; - ts.forEach(files, function (sourceFile) { - // Each file contributes into common source file path - if (!(sourceFile.flags & 2048 /* DeclarationFile */) - && !ts.fileExtensionIs(sourceFile.fileName, ".js")) { - var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, host.getCurrentDirectory()); - sourcePathComponents.pop(); // FileName is not part of directory - if (commonPathComponents) { - for (var i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) { - if (commonPathComponents[i] !== sourcePathComponents[i]) { - if (i === 0) { - diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); - return; - } - // New common path found that is 0 -> i-1 - commonPathComponents.length = i; - break; - } - } - // If the fileComponent path completely matched and less than already found update the length - if (sourcePathComponents.length < commonPathComponents.length) { - commonPathComponents.length = sourcePathComponents.length; - } - } - else { - // first file - commonPathComponents = sourcePathComponents; - } - } - }); - commonSourceDirectory = ts.getNormalizedPathFromPathComponents(commonPathComponents); - if (commonSourceDirectory) { + if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { + // If a rootDir is specified and is valid use it as the commonSourceDirectory + commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, host.getCurrentDirectory()); + } + else { + // Compute the commonSourceDirectory from the input files + commonSourceDirectory = computeCommonSourceDirectory(files); + } + if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { // Make sure directory path ends with directory separator so this string can directly // used to replace with "" to get the relative path of the source file and the relative path doesn't // start with / making it rooted path @@ -29309,6 +29339,13 @@ var ts; type: "boolean", description: ts.Diagnostics.Do_not_emit_comments_to_output }, + { + name: "rootDir", + type: "string", + isFilePath: true, + description: ts.Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir, + paramType: ts.Diagnostics.LOCATION + }, { name: "separateCompilation", type: "boolean"