パルカワ2

最近はFlutterをやっています

VSCodeのlaunch.jsonからInteliJのrunConfigurationsを自動生成する

毎日のようにはてなスターのスパムがきます。こんにちは。
仕事で作っているアプリは、Flutterを使っておりかつFlavorがたくさんあってそれぞれのFlavorごとにrunConfigurationsを用意している。また今後Flavorは増える予定である。
同僚には、VSCodeを使ってる人もInteliJを使ってる人もいるので、VSCodeのlaunch.jsonとInteliJのrunConfigurations両方を管理している。
片方追加したらもう片方も自動で追加してくれ〜という気持ちが出てきたので、VSCodeのlaunch.jsonからInteliJのrunConfigurationsを自動生成するようにスクリプトを作った。

launch.json というとJSONファイルっぽいけど、コメントがあったり最後の要素なのにケツカンマがあったりとJavaScriptのObjectっぽい。しょうがないのでevalした。
nodejsでやればいいだけだけど、nodejsに依存させたくなかったのでDartです。
あとは、これをGithub actionsとかで動かしてdiffをcommitするようにすればいい感じになる。

import 'dart:convert';
import 'dart:io';
import 'dart:isolate';

Future<void> main() async {
  final mapping = await _loadLaunchJson();
  final configurations = mapping["configurations"] as List<dynamic>;

  await Directory(".idea/runConfigurations").create(recursive: true);

  for (final config in configurations) {
    final runConfiguration = '''
<component name="ProjectRunConfigurationManager">
  <configuration default="false" name="${config["name"]}" type="FlutterRunConfigurationType" factoryName="Flutter" singleton="false">
    <option name="additionalArgs" value="${(config["args"] as List<String>).join(" ")}" />
    <option name="filePath" value="\$PROJECT_DIR\$/${config["program"]}" />
    <method v="2" />
  </configuration>
</component>
''';

    final filename = (config["name"] as String).replaceAll(" ", "") + ".xml";
    final runConfigurationFile = File(".idea/runConfigurations/$filename");
    await runConfigurationFile.writeAsString(runConfiguration);
  }
}

Future<Map<String, dynamic>> _loadLaunchJson() async {
  final launchJsonFile = File("./.vscode/launch.json");
  final launchJsonBody = await launchJsonFile.readAsString();

  // コメントがあったりケツカンマがあったりとJSONではないので必殺eval
  final uri = Uri.dataFromString(
    '''
    import "dart:isolate";
    void main(_, SendPort port) {
      port.send(${launchJsonBody});
    }
    ''',
    mimeType: 'application/dart',
  );
  final port = ReceivePort();
  await Isolate.spawnUri(uri, [], port.sendPort);

  final dynamic response = await port.first;
  return response as Map<String, dynamic>;
}

1000万年ぶりくらいにはてな記法書いた気がする。