blob: dcc2651cb300487a8c438e023fb7f54fdeed97de [file] [log] [blame]
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
import 'config.dart';
import 'context.dart';
import 'generator/generator.dart';
import 'parser/parser.dart';
import 'transformer/transform.dart';
import 'utils.dart';
extension Swift2ObjCGeneratorMethod on Swift2ObjCGenerator {
/// Used to generate the wrapper swift file.
Future<void> generate({required Logger? logger}) => _generateWrapper(
this,
Context(logger ?? (Logger.detached('dev/null')..level = Level.OFF)),
);
}
Future<void> _generateWrapper(
Swift2ObjCGenerator config,
Context context,
) async {
final Directory tempDir;
final bool deleteTempDirWhenDone;
var lazyTarget = config.target;
Future<String> target() async => lazyTarget ??= await hostTargetTriple;
var lazySdkPath = config.sdk;
Future<Uri> sdkPath() async => lazySdkPath ??= await hostSdk;
if (config.tempDir == null) {
tempDir = Directory.systemTemp.createTempSync(defaultTempDirPrefix);
deleteTempDirWhenDone = true;
} else {
tempDir = Directory.fromUri(config.tempDir!);
deleteTempDirWhenDone = false;
}
tempDir.createSync();
final sourceModules = <String?>[];
final mergedSymbolgraph = ParsedSymbolgraph();
final allInputConfigs = [...config.inputs, builtInInputConfig];
for (final input in allInputConfigs) {
if (input is HasSymbolgraphCommand) {
await _generateSymbolgraphJson(
(input as HasSymbolgraphCommand).symbolgraphCommand(
await target(),
path.absolute((await sdkPath()).path),
),
tempDir,
);
}
final symbolgraphFileName = switch (input) {
FilesInputConfig() => '${input.tempModuleName}$symbolgraphFileSuffix',
ModuleInputConfig() => '${input.module}$symbolgraphFileSuffix',
JsonFileInputConfig() => path.absolute(input.jsonFile.path),
};
final symbolgraphJsonPath = path.join(tempDir.path, symbolgraphFileName);
final symbolgraphJson = readJsonFile(symbolgraphJsonPath);
sourceModules.add(switch (input) {
FilesInputConfig() => null,
ModuleInputConfig() => input.module,
JsonFileInputConfig() => parseModuleName(symbolgraphJson),
});
mergedSymbolgraph.merge(parseSymbolgraph(input, symbolgraphJson));
}
final declarations = parseDeclarations(context, mergedSymbolgraph);
final transformedDeclarations = transform(
context,
declarations,
filter: config.include,
);
final wrapperCode = generate(
transformedDeclarations,
importedModuleNames: sourceModules.nonNulls.toList(),
preamble: config.preamble,
);
File.fromUri(config.outputFile).writeAsStringSync(wrapperCode);
if (deleteTempDirWhenDone) {
tempDir.deleteSync(recursive: true);
}
}
Future<void> _generateSymbolgraphJson(
Command symbolgraphCommand,
Directory workingDirectory,
) async {
final result = await Process.run(
symbolgraphCommand.executable,
symbolgraphCommand.args,
workingDirectory: workingDirectory.path,
);
if (result.exitCode != 0) {
throw ProcessException(
symbolgraphCommand.executable,
symbolgraphCommand.args,
'Error generating symbol graph \n${result.stdout} \n${result.stderr}',
);
}
}