- Add VariableSpec class with magnitude field validation - Add Formula class supporting multiple input/output variables - Support d4rt_code as string or object with code field - Add comprehensive tests for parsing and serialization - Fix broken test import in pruebas_d4rt_test.dart Follows README.md format requirements exactly
192 lines
5.8 KiB
Dart
192 lines
5.8 KiB
Dart
// Copyright (c) 2015, 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:markdown/markdown.dart';
|
|
import 'package:path/path.dart';
|
|
import 'package:pub_semver/pub_semver.dart';
|
|
|
|
import 'common/generate_common.dart';
|
|
import 'dart/generate_dart_client.dart';
|
|
import 'dart/generate_dart_common.dart';
|
|
import 'dart/generate_dart_interface.dart';
|
|
import 'java/generate_java.dart' as java show Api, api, JavaGenerator;
|
|
|
|
final bool _stampPubspecVersion = false;
|
|
|
|
/// Parse the 'service.md' into a model and generate both Dart and Java
|
|
/// libraries.
|
|
Future<void> main(List<String> args) async {
|
|
final codeGeneratorDir = dirname(Platform.script.toFilePath());
|
|
|
|
// Parse service.md into a model.
|
|
final file = File(
|
|
normalize(join(codeGeneratorDir, '../../../runtime/vm/service/service.md')),
|
|
);
|
|
final document = Document();
|
|
final buf = StringBuffer(file.readAsStringSync());
|
|
final nodes = document.parseLines(buf.toString().split('\n'));
|
|
print('Parsed ${file.path}.');
|
|
print('Service protocol version ${ApiParseUtil.parseVersionString(nodes)}.');
|
|
|
|
// Generate code from the model.
|
|
print('');
|
|
|
|
await _generateDartClient(codeGeneratorDir, nodes);
|
|
await _generateDartInterface(codeGeneratorDir, nodes);
|
|
await _generateJava(codeGeneratorDir, nodes);
|
|
}
|
|
|
|
Future<void> _generateDartClient(
|
|
String codeGeneratorDir, List<Node> nodes) async {
|
|
final outputFilePath = await _generateDartCommon(
|
|
api: VmServiceApi(),
|
|
nodes: nodes,
|
|
codeGeneratorDir: codeGeneratorDir,
|
|
packageName: 'vm_service',
|
|
interfaceName: 'VmService',
|
|
);
|
|
print('Wrote Dart client to $outputFilePath.');
|
|
}
|
|
|
|
Future<void> _generateDartInterface(
|
|
String codeGeneratorDir, List<Node> nodes) async {
|
|
final outputFilePath = await _generateDartCommon(
|
|
api: VmServiceInterfaceApi(),
|
|
nodes: nodes,
|
|
codeGeneratorDir: codeGeneratorDir,
|
|
packageName: 'vm_service_interface',
|
|
interfaceName: 'VmServiceInterface',
|
|
);
|
|
print('Wrote Dart interface to $outputFilePath.');
|
|
}
|
|
|
|
Future<String> _generateDartCommon({
|
|
required Api api,
|
|
required List<Node> nodes,
|
|
required String codeGeneratorDir,
|
|
required String packageName,
|
|
required String interfaceName,
|
|
}) async {
|
|
final outDirPath = normalize(
|
|
join(
|
|
codeGeneratorDir,
|
|
'../..',
|
|
packageName,
|
|
'lib/src',
|
|
),
|
|
);
|
|
final outDir = Directory(outDirPath);
|
|
if (!outDir.existsSync()) {
|
|
outDir.createSync(recursive: true);
|
|
}
|
|
|
|
final outputFile = File(
|
|
join(
|
|
outDirPath,
|
|
'$packageName.dart',
|
|
),
|
|
);
|
|
final generator = DartGenerator(interfaceName: interfaceName);
|
|
|
|
// Generate the code.
|
|
api.parse(nodes);
|
|
api.generate(generator);
|
|
outputFile.writeAsStringSync(generator.toString());
|
|
|
|
// Clean up the code.
|
|
await _runDartFormat(outDirPath);
|
|
|
|
if (_stampPubspecVersion) {
|
|
// Update the pubspec file.
|
|
Version version = ApiParseUtil.parseVersionSemVer(nodes);
|
|
_stampPubspec(version);
|
|
|
|
// Validate that the changelog contains an entry for the current version.
|
|
_checkUpdateChangelog(version);
|
|
}
|
|
return outputFile.path;
|
|
}
|
|
|
|
Future<void> _runDartFormat(String outDirPath) async {
|
|
ProcessResult result = Process.runSync('dart', ['format', outDirPath]);
|
|
if (result.exitCode != 0) {
|
|
print('dart format: ${result.stdout}\n${result.stderr}');
|
|
throw result.exitCode;
|
|
}
|
|
}
|
|
|
|
Future<void> _generateJava(String codeGeneratorDir, List<Node> nodes) async {
|
|
var srcDirPath = normalize(join(codeGeneratorDir, '..', 'java', 'src'));
|
|
var generator = java.JavaGenerator(srcDirPath);
|
|
|
|
final scriptPath = Platform.script.toFilePath();
|
|
final kSdk = '/sdk/';
|
|
final scriptLocation =
|
|
scriptPath.substring(scriptPath.indexOf(kSdk) + kSdk.length);
|
|
java.api = java.Api(scriptLocation);
|
|
java.api.parse(nodes);
|
|
java.api.generate(generator);
|
|
|
|
// We generate files into the java/src/ folder; ensure the generated files
|
|
// aren't committed to git (but manually maintained files in the same
|
|
// directory are).
|
|
List<String> generatedPaths = generator.allWrittenFiles
|
|
.map((path) => relative(path, from: 'java'))
|
|
.toList();
|
|
generatedPaths.sort();
|
|
File gitignoreFile = File(join(codeGeneratorDir, '..', 'java', '.gitignore'));
|
|
gitignoreFile.writeAsStringSync('''
|
|
# This is a generated file.
|
|
|
|
${generatedPaths.join('\n')}
|
|
''');
|
|
|
|
// Generate a version file.
|
|
Version version = ApiParseUtil.parseVersionSemVer(nodes);
|
|
File file = File(join('java', 'version.properties'));
|
|
file.writeAsStringSync('version=${version.major}.${version.minor}\n');
|
|
|
|
print('Wrote Java to $srcDirPath.');
|
|
}
|
|
|
|
// Push the major and minor versions into the pubspec.
|
|
void _stampPubspec(Version version) {
|
|
final String pattern = 'version: ';
|
|
File file = File('pubspec.yaml');
|
|
String text = file.readAsStringSync();
|
|
bool found = false;
|
|
|
|
text = text.split('\n').map((line) {
|
|
if (line.startsWith(pattern)) {
|
|
found = true;
|
|
Version v = Version.parse(line.substring(pattern.length));
|
|
String? pre = v.preRelease.isEmpty ? null : v.preRelease.join('-');
|
|
String? build = v.build.isEmpty ? null : v.build.join('+');
|
|
v = Version(version.major, version.minor, v.patch,
|
|
pre: pre, build: build);
|
|
return '$pattern${v.toString()}';
|
|
} else {
|
|
return line;
|
|
}
|
|
}).join('\n');
|
|
|
|
if (!found) throw '`$pattern` not found';
|
|
|
|
file.writeAsStringSync(text);
|
|
}
|
|
|
|
void _checkUpdateChangelog(Version version) {
|
|
// Look for `## major.minor`.
|
|
String check = '## ${version.major}.${version.minor}';
|
|
|
|
File file = File('CHANGELOG.md');
|
|
String text = file.readAsStringSync();
|
|
bool containsReleaseNotes =
|
|
text.split('\n').any((line) => line.startsWith(check));
|
|
if (!containsReleaseNotes) {
|
|
throw '`$check` not found in the CHANGELOG.md file';
|
|
}
|
|
}
|