in tsc/src/main.ts [570:791]
export async function run(this: void, options: Options): Promise<void> {
if (options.help) {
return;
}
if (options.version) {
console.log(require('../package.json').version);
return;
}
if (options.package !== undefined && options.publishedPackages !== undefined) {
console.log(`Only package or publishedPackages can be set but not both.`);
process.exitCode = - 1;
return;
}
options = Options.resolvePathToConfig(options);
if (options.package && !await pfs.isFile(options.package)) {
console.error(`The package.json file referenced by the package option doesn't exist. The value is ${options.package}`);
process.exitCode = -1;
return;
} else if (options.publishedPackages !== undefined) {
let failed: boolean = false;
for (const item of options.publishedPackages) {
if (!await pfs.isFile(item.package)) {
console.error(`The package.json file referenced by the 'publishedPackages' option doesn't exist. The value is ${JSON.stringify(item, undefined, 0)}`);
failed = true;
}
if (!await pfs.isFile(item.project)) {
console.error(`The project file referenced by the 'publishedPackages' options doesn't exist. The value is ${JSON.stringify(item, undefined, 0)}`);
failed = true;
}
}
if (failed) {
process.exitCode = -1;
return;
}
}
let writer: Writer | undefined = options.outputWriter;
if (writer === undefined) {
if (options.stdout) {
writer = new StdoutWriter();
} else if (options.out) {
writer = new FileWriter(options.out);
}
}
if (writer === undefined) {
console.log(`Either a output file using --out or --stdout must be specified.`);
process.exitCode = -1;
return;
}
const workspaceRoot = tss.normalizePath(options.workspaceRoot ?? process.cwd());
if (!await pfs.isDirectory(workspaceRoot)) {
console.error(`The workspace root doesn't denote a folder on disk. The value is ${workspaceRoot}`);
process.exitCode = -1;
return;
}
if (typeof options.source === 'string') {
if (!await pfs.isFile(options.source)) {
console.error(`The source option doesn't denote a valid file on disk. The value is ${options.source}`);
process.exitCode = -1;
return;
}
if (path.basename(options.source) !== 'package.json') {
console.error(`The source option can only point to a package.json file. The value is ${options.source}`);
process.exitCode = -1;
return;
}
}
// We have read the config from file. See if we need to put back a -p to successfully
// parse the command line.
const args: string[] = [];
let needsProject: boolean = true;
for (let i = 0; i < ts.sys.args.length; i++) {
const arg = ts.sys.args[i];
if (arg === '-p' || arg === '--project' || arg.startsWith('-p=') || arg.startsWith('--project=')) {
needsProject = false;
}
if (arg === '--config') {
i++;
continue;
}
if (arg.startsWith('--config=')) {
continue;
}
args.push(arg);
}
if (needsProject && typeof options.p === 'string') {
args.push('-p', options.p);
}
// Push in memory file onto the args so that the TS compiler sees them.
if (options.files !== undefined) {
for (const filename of options.files.keys()) {
args.push(filename);
}
}
const config: ts.ParsedCommandLine | ConfigOptions = ConfigOptions.is(options.p) ? options.p : ts.parseCommandLine(args);
const idGenerator = createIdGenerator(options);
const emitter = createEmitter(options, writer, idGenerator);
emitter.start();
const builder = new Builder({
idGenerator,
emitSource: !options.noContents
});
const emitterContext: EmitterContext = {
get edge() {
return builder.edge;
},
get vertex() {
return builder.vertex;
},
emit(element: Vertex | Edge): void {
emitter.emit(element);
},
flush(): Promise<void> {
return emitter.flush();
}
};
const metaData = builder.vertex.metaData(Version);
const source: Source | number = await async function() {
const result: Source = builder.vertex.source(URI.file(workspaceRoot).toString(true));
if (typeof options.source === 'string') {
try {
const pjc = JSON.parse(await fs.promises.readFile(options.source, { encoding: 'utf8' })) as { repository?: RepositoryInfo; };
if (pjc.repository !== undefined && typeof pjc.repository.type === 'string' && typeof pjc.repository.url === 'string') {
result.repository = Object.assign({}, pjc.repository);
}
} catch (error) {
console.error(`Reading package.json file to obtain repository source failed.`);
return -1;
}
} else if (options.source !== undefined && options.source.repository !== undefined) {
result.repository = {
url: options.source.repository.url,
type: options.source.repository.type
};
}
return result;
}();
if (typeof source === 'number') {
process.exitCode = source;
return;
}
emitter.emit(metaData);
emitter.emit(source);
const capabilities = builder.vertex.capabilities(true);
capabilities.declarationProvider = false;
emitter.emit(capabilities);
let logger: InternalLogger;
if (options.log === '') { // --log not provided
// The trace is written to stdout so we can't log anything.
if (options.stdout) {
logger = new InternalNullLogger();
} else {
logger = new StreamLogger(process.stdout);
}
} else if (options.log === true) { // --log without a file name
if (options.stdout === undefined && options.out !== undefined) {
logger = new FileLogger(`${options.out}.log`, true);
} else if (options.stdout) {
logger = new InternalNullLogger();
} else {
logger = new StreamLogger(process.stdout);
}
} else if ((typeof options.log === 'string') && options.log.length > 0) { // --log filename
logger = new FileLogger(options.log, !options.stdout);
} else {
logger = new InternalNullLogger();
}
logger.begin();
let packageInfo: string | Map<string, string> | undefined;
if (options.package !== undefined) {
packageInfo = options.package;
} else {
packageInfo = new Map();
if (options.publishedPackages !== undefined) {
for (const item of options.publishedPackages) {
const packagePath = tss.normalizePath(item.package);
const projectPath = tss.normalizePath(item.project);
packageInfo.set(projectPath, packagePath);
}
}
}
let exportMonikers: ExportMonikers | undefined;
if (typeof packageInfo === 'string') {
const packageJson = PackageJson.read(packageInfo);
if (packageJson !== undefined) {
exportMonikers = new ExportMonikers(emitterContext, workspaceRoot, packageJson);
}
packageInfo = undefined;
}
const processProjectOptions: ProcessProjectOptions = {
workspaceRoot: workspaceRoot,
projectName: options.projectName,
typeAcquisition: options.typeAcquisition,
noProjectReferences: options.noProjectReferences,
stdout: options.stdout,
dataMode: options.moniker === 'strict' ? DataMode.free : DataMode.keep,
packageInfo: packageInfo,
reporter: logger,
processed: new Map(),
files: options.files
};
const dataManager: DataManager = new DataManager(emitterContext, processProjectOptions.workspaceRoot, processProjectOptions.reporter, processProjectOptions.dataMode);
const importMonikers: ImportMonikers = new ImportMonikers(emitterContext, processProjectOptions.workspaceRoot);
dataManager.begin();
await processProject(config, emitterContext, new TypingsInstaller(), dataManager, importMonikers, exportMonikers, processProjectOptions);
dataManager.end();
await emitter.end();
logger.end();
}