TypeScript def builder
This commit is contained in:
parent
31006f54e2
commit
7a93ebc833
4 changed files with 172 additions and 1 deletions
|
@ -17,6 +17,22 @@ builders:
|
||||||
generate_for:
|
generate_for:
|
||||||
- "lib/src/models/**.dart"
|
- "lib/src/models/**.dart"
|
||||||
- "test/**.dart"
|
- "test/**.dart"
|
||||||
|
typescript_definition:
|
||||||
|
target: "angel_serialize_generator"
|
||||||
|
import: "package:angel_serialize_generator/angel_serialize_generator.dart"
|
||||||
|
builder_factories:
|
||||||
|
- typescriptDefinitionBuilder
|
||||||
|
auto_apply: root_package
|
||||||
|
build_to: source
|
||||||
|
build_extensions:
|
||||||
|
.dart:
|
||||||
|
- ".d.ts"
|
||||||
|
required_inputs:
|
||||||
|
- .dart
|
||||||
|
defaults:
|
||||||
|
generate_for:
|
||||||
|
- "lib/src/models/**.dart"
|
||||||
|
- "test/**.dart"
|
||||||
targets:
|
targets:
|
||||||
_book:
|
_book:
|
||||||
sources:
|
sources:
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:analyzer/dart/element/element.dart';
|
||||||
import 'package:analyzer/dart/element/type.dart';
|
import 'package:analyzer/dart/element/type.dart';
|
||||||
import 'package:angel_serialize/angel_serialize.dart';
|
import 'package:angel_serialize/angel_serialize.dart';
|
||||||
import 'package:build/build.dart';
|
import 'package:build/build.dart';
|
||||||
|
import 'package:code_buffer/code_buffer.dart';
|
||||||
import 'package:code_builder/code_builder.dart';
|
import 'package:code_builder/code_builder.dart';
|
||||||
import 'package:recase/recase.dart';
|
import 'package:recase/recase.dart';
|
||||||
import 'package:source_gen/source_gen.dart' hide LibraryBuilder;
|
import 'package:source_gen/source_gen.dart' hide LibraryBuilder;
|
||||||
|
@ -15,6 +16,8 @@ part 'model.dart';
|
||||||
|
|
||||||
part 'serialize.dart';
|
part 'serialize.dart';
|
||||||
|
|
||||||
|
part 'typescript.dart';
|
||||||
|
|
||||||
Builder jsonModelBuilder(_) {
|
Builder jsonModelBuilder(_) {
|
||||||
return new PartBuilder(
|
return new PartBuilder(
|
||||||
const [const JsonModelGenerator()],
|
const [const JsonModelGenerator()],
|
||||||
|
@ -29,6 +32,10 @@ Builder serializerBuilder(_) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Builder typescriptDefinitionBuilder(_) {
|
||||||
|
return const TypeScriptDefinitionBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts a [DartType] to a [TypeReference].
|
/// Converts a [DartType] to a [TypeReference].
|
||||||
TypeReference convertTypeReference(DartType t) {
|
TypeReference convertTypeReference(DartType t) {
|
||||||
return new TypeReference((b) {
|
return new TypeReference((b) {
|
||||||
|
@ -60,7 +67,6 @@ bool isListModelType(InterfaceType t) {
|
||||||
isModelClass(t.typeArguments[0]);
|
isModelClass(t.typeArguments[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Determines if a [DartType] is a `Map` with the second type argument being a `Model`.
|
/// Determines if a [DartType] is a `Map` with the second type argument being a `Model`.
|
||||||
bool isMapToModelType(InterfaceType t) {
|
bool isMapToModelType(InterfaceType t) {
|
||||||
return t.name == 'Map' &&
|
return t.name == 'Map' &&
|
||||||
|
|
148
angel_serialize_generator/lib/typescript.dart
Normal file
148
angel_serialize_generator/lib/typescript.dart
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
part of angel_serialize_generator;
|
||||||
|
|
||||||
|
class TypeScriptDefinitionBuilder implements Builder {
|
||||||
|
final bool autoSnakeCaseNames;
|
||||||
|
|
||||||
|
const TypeScriptDefinitionBuilder({this.autoSnakeCaseNames: true});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, List<String>> get buildExtensions {
|
||||||
|
return {
|
||||||
|
'.dart': ['.d.ts']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> compileToTypeScriptType(String fieldName, InterfaceType type,
|
||||||
|
List<CodeBuffer> ext, BuildStep buildStep) async {
|
||||||
|
String typeScriptType = 'any';
|
||||||
|
|
||||||
|
var types = const {
|
||||||
|
num: 'number',
|
||||||
|
bool: 'boolean',
|
||||||
|
String: 'string',
|
||||||
|
Symbol: 'Symbol',
|
||||||
|
};
|
||||||
|
|
||||||
|
types.forEach((t, tsType) {
|
||||||
|
if (new TypeChecker.fromRuntime(t).isAssignableFromType(type))
|
||||||
|
typeScriptType = tsType;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isListModelType(type)) {
|
||||||
|
var arg = await compileToTypeScriptType(
|
||||||
|
fieldName, type.typeArguments[0], ext, buildStep);
|
||||||
|
typeScriptType = '$arg[]';
|
||||||
|
} else if (isMapToModelType(type)) {
|
||||||
|
var key = await compileToTypeScriptType(
|
||||||
|
fieldName, type.typeArguments[0], ext, buildStep);
|
||||||
|
var value = await compileToTypeScriptType(
|
||||||
|
fieldName, type.typeArguments[1], ext, buildStep);
|
||||||
|
var modelType = type.typeArguments[1];
|
||||||
|
var ctx = await buildContext(
|
||||||
|
modelType.element,
|
||||||
|
new ConstantReader(
|
||||||
|
serializableTypeChecker.firstAnnotationOf(modelType.element)),
|
||||||
|
buildStep,
|
||||||
|
buildStep.resolver,
|
||||||
|
autoSnakeCaseNames,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
typeScriptType = ctx.modelClassNameRecase.pascalCase +
|
||||||
|
new ReCase(fieldName).pascalCase;
|
||||||
|
|
||||||
|
ext.add(new CodeBuffer()
|
||||||
|
..writeln('interface $typeScriptType {')
|
||||||
|
..indent()
|
||||||
|
..writeln('[key: $key]: $value;')
|
||||||
|
..outdent()
|
||||||
|
..writeln('}'));
|
||||||
|
} else if (const TypeChecker.fromRuntime(List).isAssignableFromType(type)) {
|
||||||
|
typeScriptType = 'any[]';
|
||||||
|
} else if (isModelClass(type)) {
|
||||||
|
var ctx = await buildContext(
|
||||||
|
type.element,
|
||||||
|
new ConstantReader(
|
||||||
|
serializableTypeChecker.firstAnnotationOf(type.element)),
|
||||||
|
buildStep,
|
||||||
|
buildStep.resolver,
|
||||||
|
autoSnakeCaseNames,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
typeScriptType = ctx.modelClassNameRecase.pascalCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeScriptType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future build(BuildStep buildStep) async {
|
||||||
|
var contexts = <BuildContext>[];
|
||||||
|
var lib = new LibraryReader(await buildStep.inputLibrary);
|
||||||
|
var elements =
|
||||||
|
lib.annotatedWith(const TypeChecker.fromRuntime(Serializable));
|
||||||
|
|
||||||
|
for (var element in elements) {
|
||||||
|
if (element.element.kind != ElementKind.CLASS)
|
||||||
|
throw 'Only classes can be annotated with a @Serializable() annotation.';
|
||||||
|
|
||||||
|
contexts.add(await buildContext(
|
||||||
|
element.element,
|
||||||
|
element.annotation,
|
||||||
|
buildStep,
|
||||||
|
await buildStep.resolver,
|
||||||
|
true,
|
||||||
|
autoSnakeCaseNames != false));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contexts.isEmpty) return;
|
||||||
|
|
||||||
|
var buf = new CodeBuffer(
|
||||||
|
trailingNewline: true,
|
||||||
|
sourceUrl: buildStep.inputId.uri,
|
||||||
|
);
|
||||||
|
|
||||||
|
// declare module `foo` {
|
||||||
|
//buf
|
||||||
|
// ..writeln("declare module '${buildStep.inputId.package}' {")
|
||||||
|
// ..indent();
|
||||||
|
|
||||||
|
for (var ctx in contexts) {
|
||||||
|
// interface Bar { ... }
|
||||||
|
buf
|
||||||
|
..writeln('interface ${ctx.modelClassNameRecase.pascalCase} {')
|
||||||
|
..indent();
|
||||||
|
|
||||||
|
var ext = <CodeBuffer>[];
|
||||||
|
|
||||||
|
for (var field in ctx.fields) {
|
||||||
|
// Skip excluded fields
|
||||||
|
if (ctx.excluded[field.name]?.canSerialize == false) continue;
|
||||||
|
|
||||||
|
var alias = ctx.resolveFieldName(field.name);
|
||||||
|
var typeScriptType = await compileToTypeScriptType(
|
||||||
|
field.name, field.type, ext, buildStep);
|
||||||
|
|
||||||
|
// foo: string;
|
||||||
|
buf.writeln('$alias: $typeScriptType;');
|
||||||
|
}
|
||||||
|
|
||||||
|
buf
|
||||||
|
..outdent()
|
||||||
|
..writeln('}');
|
||||||
|
|
||||||
|
for (var b in ext) {
|
||||||
|
b.copyInto(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//buf
|
||||||
|
// ..outdent()
|
||||||
|
// ..writeln('}');
|
||||||
|
|
||||||
|
buildStep.writeAsString(
|
||||||
|
buildStep.inputId.changeExtension('.d.ts'),
|
||||||
|
buf.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ environment:
|
||||||
dependencies:
|
dependencies:
|
||||||
angel_serialize: ^2.0.0-alpha
|
angel_serialize: ^2.0.0-alpha
|
||||||
build_config: ">=0.2.4 <2.0.0"
|
build_config: ">=0.2.4 <2.0.0"
|
||||||
|
code_buffer: ^1.0.0
|
||||||
code_builder: ^3.0.0
|
code_builder: ^3.0.0
|
||||||
id: ^1.0.0
|
id: ^1.0.0
|
||||||
recase: ^1.0.0
|
recase: ^1.0.0
|
||||||
|
|
Loading…
Reference in a new issue