| // 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}', | |
| ); | |
| } | |
| } |