export async function run()

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();
}