Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ module ts {
type: "boolean",
description: Diagnostics.Do_not_emit_comments_to_output,
},
{
name: "rootDir",
type: "string",
isFilePath: true,
description: Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir,
paramType: Diagnostics.LOCATION,
},
{
name: "separateCompilation",
type: "boolean",
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/diagnosticInformationMap.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,8 @@ module ts {
Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: 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: DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." },
Preserve_new_lines_when_emitting_code: { code: 6057, category: 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: 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: 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: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." },
Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." },
Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." },
Expand Down
9 changes: 9 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1968,6 +1968,15 @@
"category": "Message",
"code": 6057
},
"Specifies the root directory of input files. Use to control the output directory structure with --outDir.": {
"category": "Message",
"code": 6058
},
"File '{0}' is not under rootDir '{1}'. RootDir is expected to contain all source files.": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use lowercase 'r' for 'RootDir', use single quotes :

"under 'rootDir' '{1}'. 'rootDir' is expected..."

"category": "Error",
"code": 6059
},


"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
Expand Down
103 changes: 69 additions & 34 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,66 @@ module ts {
}
}

function computecommonSourceDirectory(sourceFiles: SourceFile[]): string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compute**_C**_ommon

let commonPathComponents: string[];
let currentDirectory = host.getCurrentDirectory();
forEach(files, sourceFile => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you meant sourceFiles here not files.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also use a for..of unless you're really hesitant to use a label.

// Each file contributes into common source file path
if (isDeclarationFile(sourceFile)) {
return;
}

let sourcePathComponents = getNormalizedPathComponents(sourceFile.fileName, currentDirectory);
sourcePathComponents.pop(); // FileName is not part of directory
if (commonPathComponents) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (!commonPathComponents) {
    // first file
    commonPathComponents = sourcePathComponents;
    continue; // or return if you don't change forEach to a for..of
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem it though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i did add the return.. not sure why i need to move the else clause though

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm saying instead of having a big if statement body, just check perform the else clause when applicable

for (let i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cache the min

if (commonPathComponents[i] !== sourcePathComponents[i]) {
if (i === 0) {
diagnostics.add(createCompilerDiagnostic(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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean.

if (sourcePathComponents.length < commonPathComponents.length) {
commonPathComponents.length = sourcePathComponents.length;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could technically use n here but it might not be readable

}
}
else {
// first file
commonPathComponents = sourcePathComponents;
}

});

return getNormalizedPathFromPathComponents(commonPathComponents);
}

function checkSourceFilesBelongToPath(soruceFiles: SourceFile[], rootDirectory: string): boolean {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

soruceFiles -> sourceFiles

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why so soruce?

let allFilesBelongToPath = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

                           ~~~~~~~~~~~~~~~~~~~~~
Warning (508, 28) DR1000: Variable 'allFilesBelongToPath' is declared but never read from.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

 return allFilesBelongToPath;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to report all violations instead of just the first one.

if (files) {
let currentDirectory = host.getCurrentDirectory();
let absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory));

for (var sourceFile of files) {
if (!isDeclarationFile(sourceFile)) {
let absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory));
if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) {
diagnostics.add(createCompilerDiagnostic(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) {
Expand Down Expand Up @@ -515,41 +575,16 @@ module ts {
(options.mapRoot && // there is --mapRoot specified and there would be multiple js files generated
(!options.out || firstExternalModuleSourceFile !== undefined))) {

let commonPathComponents: string[];
forEach(files, sourceFile => {
// Each file contributes into common source file path
if (!(sourceFile.flags & NodeFlags.DeclarationFile)
&& !fileExtensionIs(sourceFile.fileName, ".js")) {
let sourcePathComponents = getNormalizedPathComponents(sourceFile.fileName, host.getCurrentDirectory());
sourcePathComponents.pop(); // FileName is not part of directory
if (commonPathComponents) {
for (let i = 0; i < Math.min(commonPathComponents.length, sourcePathComponents.length); i++) {
if (commonPathComponents[i] !== sourcePathComponents[i]) {
if (i === 0) {
diagnostics.add(createCompilerDiagnostic(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;
}
}
});
if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) {
// If a rootDir is specified and is valid use it as the commonSourceDirectory
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, host.getCurrentDirectory());
}
else {
// Compute the commonSourceDirectory from the input files
commonSourceDirectory = computecommonSourceDirectory(files);
}

commonSourceDirectory = getNormalizedPathFromPathComponents(commonPathComponents);
if (commonSourceDirectory) {
if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== 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
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1650,6 +1650,7 @@ module ts {
preserveConstEnums?: boolean;
project?: string;
removeComments?: boolean;
rootDir?: string;
sourceMap?: boolean;
sourceRoot?: string;
suppressImplicitAnyIndexErrors?: boolean;
Expand Down
5 changes: 4 additions & 1 deletion src/harness/projectsRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface ProjectRunnerTestCase {
runTest?: boolean; // Run the resulting test
bug?: string; // If there is any bug associated with this test case
noResolve?: boolean;
rootDir?: string; // --rootDir
}

interface ProjectRunnerTestCaseResolutionInfo extends ProjectRunnerTestCase {
Expand Down Expand Up @@ -160,7 +161,8 @@ class ProjectRunner extends RunnerBase {
mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? ts.sys.resolvePath(testCase.mapRoot) : testCase.mapRoot,
sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? ts.sys.resolvePath(testCase.sourceRoot) : testCase.sourceRoot,
module: moduleKind,
noResolve: testCase.noResolve
noResolve: testCase.noResolve,
rootDir: testCase.rootDir
};
}

Expand Down Expand Up @@ -344,6 +346,7 @@ class ProjectRunner extends RunnerBase {
baselineCheck: testCase.baselineCheck,
runTest: testCase.runTest,
bug: testCase.bug,
rootDir: testCase.rootDir,
resolvedInputFiles: ts.map(compilerResult.program.getSourceFiles(), inputFile => inputFile.fileName),
emittedFiles: ts.map(compilerResult.outputFiles, outputFile => outputFile.emittedFileName)
};
Expand Down
32 changes: 16 additions & 16 deletions tests/baselines/reference/APISample_compile.types
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void
var program = ts.createProgram(fileNames, options);
>program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7))
>ts.createProgram(fileNames, options) : ts.Program
>ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1201, 113))
>ts.createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1202, 113))
>ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20))
>createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1201, 113))
>createProgram : (rootNames: string[], options: ts.CompilerOptions, host?: ts.CompilerHost) => ts.Program, Symbol(ts.createProgram, Decl(typescript.d.ts, 1202, 113))
>fileNames : string[], Symbol(fileNames, Decl(APISample_compile.ts, 13, 24))
>options : ts.CompilerOptions, Symbol(options, Decl(APISample_compile.ts, 13, 44))

Expand All @@ -46,9 +46,9 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void
>ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) : ts.Diagnostic[]
>ts.getPreEmitDiagnostics(program).concat : { <U extends ts.Diagnostic[]>(...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46))
>ts.getPreEmitDiagnostics(program) : ts.Diagnostic[]
>ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1199, 98))
>ts.getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1200, 98))
>ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20))
>getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1199, 98))
>getPreEmitDiagnostics : (program: ts.Program) => ts.Diagnostic[], Symbol(ts.getPreEmitDiagnostics, Decl(typescript.d.ts, 1200, 98))
>program : ts.Program, Symbol(program, Decl(APISample_compile.ts, 14, 7))
>concat : { <U extends ts.Diagnostic[]>(...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }, Symbol(Array.concat, Decl(lib.d.ts, 1025, 13), Decl(lib.d.ts, 1030, 46))
>emitResult.diagnostics : ts.Diagnostic[], Symbol(ts.EmitResult.diagnostics, Decl(typescript.d.ts, 820, 29))
Expand All @@ -67,21 +67,21 @@ export function compile(fileNames: string[], options: ts.CompilerOptions): void
>line : number, Symbol(line, Decl(APISample_compile.ts, 20, 13))
>character : number, Symbol(character, Decl(APISample_compile.ts, 20, 19))
>diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter
>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1262, 26))
>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1263, 26))
>diagnostic.file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26))
>diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27))
>file : ts.SourceFile, Symbol(ts.Diagnostic.file, Decl(typescript.d.ts, 1062, 26))
>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1262, 26))
>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter, Symbol(ts.SourceFile.getLineAndCharacterOfPosition, Decl(typescript.d.ts, 1263, 26))
>diagnostic.start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1063, 25))
>diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27))
>start : number, Symbol(ts.Diagnostic.start, Decl(typescript.d.ts, 1063, 25))

var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
>message : string, Symbol(message, Decl(APISample_compile.ts, 21, 11))
>ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') : string
>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1200, 67))
>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1201, 67))
>ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20))
>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1200, 67))
>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string, Symbol(ts.flattenDiagnosticMessageText, Decl(typescript.d.ts, 1201, 67))
>diagnostic.messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1065, 23))
>diagnostic : ts.Diagnostic, Symbol(diagnostic, Decl(APISample_compile.ts, 19, 27))
>messageText : string | ts.DiagnosticMessageChain, Symbol(ts.Diagnostic.messageText, Decl(typescript.d.ts, 1065, 23))
Expand Down Expand Up @@ -153,16 +153,16 @@ compile(process.argv.slice(2), {

target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS
>target : ts.ScriptTarget, Symbol(target, Decl(APISample_compile.ts, 31, 45))
>ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1117, 16))
>ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1115, 5))
>ts.ScriptTarget.ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1118, 16))
>ts.ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1116, 5))
>ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20))
>ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1115, 5))
>ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1117, 16))
>ScriptTarget : typeof ts.ScriptTarget, Symbol(ts.ScriptTarget, Decl(typescript.d.ts, 1116, 5))
>ES5 : ts.ScriptTarget, Symbol(ts.ScriptTarget.ES5, Decl(typescript.d.ts, 1118, 16))
>module : ts.ModuleKind, Symbol(module, Decl(APISample_compile.ts, 32, 32))
>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1108, 17))
>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1106, 5))
>ts.ModuleKind.CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1109, 17))
>ts.ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1107, 5))
>ts : typeof ts, Symbol(ts, Decl(APISample_compile.ts, 9, 20))
>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1106, 5))
>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1108, 17))
>ModuleKind : typeof ts.ModuleKind, Symbol(ts.ModuleKind, Decl(typescript.d.ts, 1107, 5))
>CommonJS : ts.ModuleKind, Symbol(ts.ModuleKind.CommonJS, Decl(typescript.d.ts, 1109, 17))

});
Loading