blob: 3711fd28dbe33e4934e5af88e856c275d76138e2 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'ast.dart';
import 'generator_tools.dart';
/// An abstract base class of generators.
///
/// This provides the structure that is common across generators for different languages.
abstract class Generator<T> {
/// Constructor.
const Generator();
/// Generates files for specified language with specified [generatorOptions]
void generate(
T generatorOptions,
Root root,
StringSink sink, {
required String dartPackageName,
});
}
/// An abstract base class that enforces code generation across platforms.
abstract class StructuredGenerator<T> extends Generator<T> {
/// Constructor.
const StructuredGenerator();
@override
void generate(
T generatorOptions,
Root root,
StringSink sink, {
required String dartPackageName,
}) {
final Indent indent = Indent(sink);
writeFilePrologue(
generatorOptions,
root,
indent,
dartPackageName: dartPackageName,
);
writeFileImports(
generatorOptions,
root,
indent,
dartPackageName: dartPackageName,
);
writeOpenNamespace(
generatorOptions,
root,
indent,
dartPackageName: dartPackageName,
);
writeGeneralUtilities(
generatorOptions,
root,
indent,
dartPackageName: dartPackageName,
);
if (root.apis.any((Api api) => api is AstProxyApi)) {
writeInstanceManager(
generatorOptions,
root,
indent,
dartPackageName: dartPackageName,
);
writeInstanceManagerApi(
generatorOptions,
root,
indent,
dartPackageName: dartPackageName,
);
writeProxyApiBaseCodec(generatorOptions, root, indent);
}
writeEnums(
generatorOptions,
root,
indent,
dartPackageName: dartPackageName,
);
writeDataClasses(
generatorOptions,
root,
indent,
dartPackageName: dartPackageName,
);
writeApis(
generatorOptions,
root,
indent,
dartPackageName: dartPackageName,
);
writeCloseNamespace(
generatorOptions,
root,
indent,
dartPackageName: dartPackageName,
);
}
/// Adds specified headers to [indent].
void writeFilePrologue(
T generatorOptions,
Root root,
Indent indent, {
required String dartPackageName,
});
/// Writes specified imports to [indent].
void writeFileImports(
T generatorOptions,
Root root,
Indent indent, {
required String dartPackageName,
});
/// Writes code to [indent] that opens file namespace if needed.
///
/// This method is not required, and does not need to be overridden.
void writeOpenNamespace(
T generatorOptions,
Root root,
Indent indent, {
required String dartPackageName,
}) {}
/// Writes code to [indent] that closes file namespace if needed.
///
/// This method is not required, and does not need to be overridden.
void writeCloseNamespace(
T generatorOptions,
Root root,
Indent indent, {
required String dartPackageName,
}) {}
/// Writes any necessary helper utilities to [indent] if needed.
///
/// This method is not required, and does not need to be overridden.
void writeGeneralUtilities(
T generatorOptions,
Root root,
Indent indent, {
required String dartPackageName,
}) {}
/// Writes all enums to [indent].
///
/// Can be overridden to add extra code before/after enums.
void writeEnums(
T generatorOptions,
Root root,
Indent indent, {
required String dartPackageName,
}) {
for (final Enum anEnum in root.enums) {
writeEnum(
generatorOptions,
root,
indent,
anEnum,
dartPackageName: dartPackageName,
);
}
}
/// Writes a single Enum to [indent]. This is needed in most generators.
void writeEnum(
T generatorOptions,
Root root,
Indent indent,
Enum anEnum, {
required String dartPackageName,
}) {}
/// Writes all data classes to [indent].
///
/// Can be overridden to add extra code before/after apis.
void writeDataClasses(
T generatorOptions,
Root root,
Indent indent, {
required String dartPackageName,
}) {
for (final Class classDefinition in root.classes) {
writeDataClass(
generatorOptions,
root,
indent,
classDefinition,
dartPackageName: dartPackageName,
);
}
}
/// Writes a single data class to [indent].
void writeDataClass(
T generatorOptions,
Root root,
Indent indent,
Class classDefinition, {
required String dartPackageName,
});
/// Writes a single class encode method to [indent].
void writeClassEncode(
T generatorOptions,
Root root,
Indent indent,
Class classDefinition, {
required String dartPackageName,
}) {}
/// Writes a single class decode method to [indent].
void writeClassDecode(
T generatorOptions,
Root root,
Indent indent,
Class classDefinition, {
required String dartPackageName,
}) {}
/// Writes all apis to [indent].
///
/// Can be overridden to add extra code before/after classes.
void writeApis(
T generatorOptions,
Root root,
Indent indent, {
required String dartPackageName,
}) {
for (final Api api in root.apis) {
switch (api) {
case AstHostApi():
writeHostApi(
generatorOptions,
root,
indent,
api,
dartPackageName: dartPackageName,
);
case AstFlutterApi():
writeFlutterApi(
generatorOptions,
root,
indent,
api,
dartPackageName: dartPackageName,
);
case AstProxyApi():
writeProxyApi(
generatorOptions,
root,
indent,
api,
dartPackageName: dartPackageName,
);
}
}
}
/// Writes a single Flutter Api to [indent].
void writeFlutterApi(
T generatorOptions,
Root root,
Indent indent,
AstFlutterApi api, {
required String dartPackageName,
});
/// Writes a single Host Api to [indent].
void writeHostApi(
T generatorOptions,
Root root,
Indent indent,
AstHostApi api, {
required String dartPackageName,
});
/// Writes the implementation of an `InstanceManager` to [indent].
void writeInstanceManager(
T generatorOptions,
Root root,
Indent indent, {
required String dartPackageName,
}) {}
/// Writes the implementation of the API for the `InstanceManager` to
/// [indent].
void writeInstanceManagerApi(
T generatorOptions,
Root root,
Indent indent, {
required String dartPackageName,
}) {}
/// Writes the base codec to be used by all ProxyApis.
///
/// This codec should use `128` as the identifier for objects that exist in
/// an `InstanceManager`. The write implementation should convert an instance
/// to an identifier. The read implementation should covert the identifier
/// to an instance.
///
/// This will serve as the default codec for all ProxyApis. If a ProxyApi
/// needs to create its own codec (it has methods/fields/constructor that use
/// a data class) it should extend this codec and not `StandardMessageCodec`.
void writeProxyApiBaseCodec(
T generatorOptions,
Root root,
Indent indent,
) {}
/// Writes a single Proxy Api to [indent].
void writeProxyApi(
T generatorOptions,
Root root,
Indent indent,
AstProxyApi api, {
required String dartPackageName,
}) {}
}