Skip to content

Commit

Permalink
Support for tsconfig.json files in command-line compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
ahejlsberg committed Jan 15, 2015
1 parent cbecae3 commit f9f95ba
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 27 deletions.
108 changes: 97 additions & 11 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,18 @@ module ts {
type: "boolean",
description: Diagnostics.Print_this_message,
},
{
name: "listFiles",
type: "boolean",
},
{
name: "locale",
type: "string",
},
{
name: "mapRoot",
type: "string",
isFilePath: true,
description: Diagnostics.Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations,
paramType: Diagnostics.LOCATION,
},
Expand Down Expand Up @@ -90,6 +95,7 @@ module ts {
{
name: "outDir",
type: "string",
isFilePath: true,
description: Diagnostics.Redirect_output_structure_to_the_directory,
paramType: Diagnostics.DIRECTORY,
},
Expand All @@ -98,6 +104,14 @@ module ts {
type: "boolean",
description: Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code
},
{
name: "project",
shortName: "p",
type: "string",
isFilePath: true,
description: Diagnostics.Compile_the_project_in_the_given_directory,
paramType: Diagnostics.DIRECTORY
},
{
name: "removeComments",
type: "boolean",
Expand All @@ -111,6 +125,7 @@ module ts {
{
name: "sourceRoot",
type: "string",
isFilePath: true,
description: Diagnostics.Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations,
paramType: Diagnostics.LOCATION,
},
Expand Down Expand Up @@ -141,17 +156,6 @@ module ts {
}
];

var shortOptionNames: Map<string> = {};
var optionNameMap: Map<CommandLineOption> = {};

forEach(optionDeclarations, option => {
optionNameMap[option.name.toLowerCase()] = option;

if (option.shortName) {
shortOptionNames[option.shortName] = option.name;
}
});

export function parseCommandLine(commandLine: string[]): ParsedCommandLine {
// Set default compiler option values
var options: CompilerOptions = {
Expand All @@ -160,7 +164,15 @@ module ts {
};
var filenames: string[] = [];
var errors: Diagnostic[] = [];
var shortOptionNames: Map<string> = {};
var optionNameMap: Map<CommandLineOption> = {};

forEach(optionDeclarations, option => {
optionNameMap[option.name.toLowerCase()] = option;
if (option.shortName) {
shortOptionNames[option.shortName] = option.name;
}
});
parseStrings(commandLine);
return {
options,
Expand Down Expand Up @@ -256,4 +268,78 @@ module ts {
parseStrings(args);
}
}

export function readConfigFile(filename: string): any {
try {
var text = sys.readFile(filename);
return /\S/.test(text) ? JSON.parse(text) : {};
}
catch (e) {
}
}

export function parseConfigFile(json: any, basePath?: string): ParsedCommandLine {
var errors: Diagnostic[] = [];

return {
options: getCompilerOptions(),

This comment has been minimized.

Copy link
@mihailik

mihailik Jan 16, 2015

Contributor

Looks like when JSON config is used, any *.ts file sitting next to it is automatically included in the build.

Why is that? Handling of a config doesn't seem to be much related to a particular behaviour of scanning directories.

filenames: getFiles(),
errors
};

function getCompilerOptions(): CompilerOptions {
var options: CompilerOptions = {};
var optionNameMap: Map<CommandLineOption> = {};
forEach(optionDeclarations, option => {
optionNameMap[option.name] = option;
});
var jsonOptions = json["compilerOptions"];
if (jsonOptions) {
for (var id in jsonOptions) {
if (hasProperty(optionNameMap, id)) {
var opt = optionNameMap[id];
var optType = opt.type;
var value = jsonOptions[id];
var expectedType = typeof optType === "string" ? optType : "string";
if (typeof value === expectedType) {
if (typeof optType !== "string") {
var key = value.toLowerCase();
if (hasProperty(optType, key)) {
value = optType[key];
}
else {
errors.push(createCompilerDiagnostic(opt.error));
value = 0;
}
}
if (opt.isFilePath) {
value = normalizePath(combinePaths(basePath, value));
}
options[opt.name] = value;
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
}
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, id));
}
}
}
return options;
}

function getFiles(): string[] {
var references: string[] = json["references"] instanceof Array ? json["references"] : []
var files = map(references, s => combinePaths(basePath, s));
var sysFiles = sys.readDirectory(basePath, ".ts");
for (var i = 0; i < sysFiles.length; i++) {
var name = sysFiles[i];
if (!fileExtensionIs(name, ".d.ts") || !contains(sysFiles, name.substr(0, name.length - 5) + ".ts")) {
files.push(name);
}
}
return files;
}
}
}
15 changes: 14 additions & 1 deletion src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,19 @@ module ts {
return <T>result;
}

export function extend<T>(first: Map<T>, second: Map<T>): Map<T> {
var result: Map<T> = {};
for (var id in first) {
result[id] = first[id];
}
for (var id in second) {
if (!hasProperty(result, id)) {
result[id] = second[id];
}
}
return result;
}

export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U {
var result: U;
for (var id in map) {
Expand Down Expand Up @@ -568,7 +581,7 @@ module ts {
export function combinePaths(path1: string, path2: string) {
if (!(path1 && path1.length)) return path2;
if (!(path2 && path2.length)) return path1;
if (path2.charAt(0) === directorySeparator) return path2;
if (getRootLength(path2) !== 0) return path2;
if (path1.charAt(path1.length - 1) === directorySeparator) return path1 + path2;
return path1 + directorySeparator + path2;
}
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 @@ -378,6 +378,7 @@ module ts {
Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
Unsupported_file_encoding: { code: 5013, category: DiagnosticCategory.Error, key: "Unsupported file encoding." },
Unknown_compiler_option_0: { code: 5023, category: DiagnosticCategory.Error, key: "Unknown compiler option '{0}'." },
Compiler_option_0_requires_a_value_of_type_1: { code: 5024, category: DiagnosticCategory.Error, key: "Compiler option '{0}' requires a value of type {1}." },
Could_not_write_file_0_Colon_1: { code: 5033, category: DiagnosticCategory.Error, key: "Could not write file '{0}': {1}" },
Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5038, category: DiagnosticCategory.Error, key: "Option mapRoot cannot be specified without specifying sourcemap option." },
Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5039, category: DiagnosticCategory.Error, key: "Option sourceRoot cannot be specified without specifying sourcemap option." },
Expand All @@ -397,6 +398,7 @@ module ts {
Specify_module_code_generation_Colon_commonjs_or_amd: { code: 6016, category: DiagnosticCategory.Message, key: "Specify module code generation: 'commonjs' or 'amd'" },
Print_this_message: { code: 6017, category: DiagnosticCategory.Message, key: "Print this message." },
Print_the_compiler_s_version: { code: 6019, category: DiagnosticCategory.Message, key: "Print the compiler's version." },
Compile_the_project_in_the_given_directory: { code: 6020, category: DiagnosticCategory.Message, key: "Compile the project in the given directory." },
Syntax_Colon_0: { code: 6023, category: DiagnosticCategory.Message, key: "Syntax: {0}" },
options: { code: 6024, category: DiagnosticCategory.Message, key: "options" },
file: { code: 6025, category: DiagnosticCategory.Message, key: "file" },
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1610,6 +1610,10 @@
"category": "Error",
"code": 5023
},
"Compiler option '{0}' requires a value of type {1}.": {
"category": "Error",
"code": 5024
},
"Could not write file '{0}': {1}": {
"category": "Error",
"code": 5033
Expand Down Expand Up @@ -1686,6 +1690,10 @@
"category": "Message",
"code": 6019
},
"Compile the project in the given directory.": {
"category": "Message",
"code": 6020
},
"Syntax: {0}": {
"category": "Message",
"code": 6023
Expand Down
9 changes: 8 additions & 1 deletion src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ module ts {
var seenNoDefaultLib = options.noLib;
var commonSourceDirectory: string;

//options = extend(options, {
// module: ModuleKind.None,
// target: ScriptTarget.ES3
//});

forEach(rootNames, name => processRootFile(name, false));
if (!seenNoDefaultLib) {
processRootFile(host.getDefaultLibFilename(options), true);
Expand Down Expand Up @@ -146,7 +151,9 @@ module ts {
function invokeEmitter(targetSourceFile?: SourceFile) {
var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver();
return emitFiles(resolver, getEmitHost(), targetSourceFile);
} function getSourceFile(filename: string) {
}

function getSourceFile(filename: string) {
filename = host.getCanonicalFileName(filename);
return hasProperty(filesByName, filename) ? filesByName[filename] : undefined;
}
Expand Down
63 changes: 63 additions & 0 deletions src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module ts {
createDirectory(directoryName: string): void;
getExecutingFilePath(): string;
getCurrentDirectory(): string;
readDirectory(path: string, extension?: string): string[];
getMemoryUsage? (): number;
exit(exitCode?: number): void;
}
Expand All @@ -28,6 +29,13 @@ module ts {
declare var global: any;
declare var __filename: string;

declare class Enumerator {
public atEnd(): boolean;
public moveNext(): boolean;
public item(): any;
constructor(o: any);
}

export var sys: System = (function () {

function getWScriptSystem(): System {
Expand Down Expand Up @@ -100,6 +108,34 @@ module ts {
}
}

function getNames(collection: any): string[] {
var result: string[] = [];
for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
result.push(e.item().Name);
}
return result.sort();
}

function readDirectory(path: string, extension?: string): string[] {
var result: string[] = [];
visitDirectory(path);
return result;
function visitDirectory(path: string) {
var folder = fso.GetFolder(path || ".");
var files = getNames(folder.files);
for (var i = 0; i < files.length; i++) {
var name = files[i];
if (!extension || fileExtensionIs(name, extension)) {
result.push(combinePaths(path, name));
}
}
var subfolders = getNames(folder.subfolders);
for (var i = 0; i < subfolders.length; i++) {
visitDirectory(combinePaths(path, subfolders[i]));
}
}
}

return {
args,
newLine: "\r\n",
Expand Down Expand Up @@ -129,6 +165,7 @@ module ts {
getCurrentDirectory() {
return new ActiveXObject("WScript.Shell").CurrentDirectory;
},
readDirectory,
exit(exitCode?: number): void {
try {
WScript.Quit(exitCode);
Expand Down Expand Up @@ -185,6 +222,31 @@ module ts {
_fs.writeFileSync(fileName, data, "utf8");
}

function readDirectory(path: string, extension?: string): string[] {
var result: string[] = [];
visitDirectory(path);
return result;
function visitDirectory(path: string) {
var files = _fs.readdirSync(path || ".").sort();
var directories: string[] = [];
for (var i = 0; i < files.length; i++) {
var name = combinePaths(path, files[i]);
var stat = _fs.statSync(name);
if (stat.isFile()) {
if (!extension || fileExtensionIs(name, extension)) {
result.push(name);
}
}
else if (stat.isDirectory()) {
directories.push(name);
}
}
for (var i = 0; i < directories.length; i++) {
visitDirectory(directories[i]);
}
}
}

return {
args: process.argv.slice(2),
newLine: _os.EOL,
Expand Down Expand Up @@ -231,6 +293,7 @@ module ts {
getCurrentDirectory() {
return process.cwd();
},
readDirectory,
getMemoryUsage() {
if (global.gc) {
global.gc();
Expand Down
Loading

0 comments on commit f9f95ba

Please sign in to comment.