From 7aefb07c1badda61219479a282d0c27f302287dd Mon Sep 17 00:00:00 2001 From: yjbanov Date: Tue, 19 Aug 2014 11:15:08 -0700 Subject: [PATCH 1/8] null-safe error extraction --- lib/runtime/error.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/runtime/error.dart b/lib/runtime/error.dart index f57ec7b..22d9c3c 100644 --- a/lib/runtime/error.dart +++ b/lib/runtime/error.dart @@ -13,7 +13,9 @@ class StreamyRpcException implements Exception { final Map response; /// Convenience accessor - List get errors => response != null ? response['error']['errors'] : null; + List get errors => response != null && response['error'] is Map + ? response['error']['errors'] + : null; Map get error => errors != null && errors.length > 0 ? errors[0] : null; String get message => error != null && error.containsKey('message') ? error['message'] : null; From fff5b8ce31dbae07975305f439853fa23524f3b8 Mon Sep 17 00:00:00 2001 From: yjbanov Date: Tue, 19 Aug 2014 11:15:22 -0700 Subject: [PATCH 2/8] make globals work for subclasses --- lib/generator/emitter.dart | 4 ++++ lib/mixins/global.dart | 2 +- lib/runtime/api.dart | 5 +++++ lib/runtime/global.dart | 10 +++++++++- test/generated/schema_object_test.dart | 12 ++++++++++++ 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/generator/emitter.dart b/lib/generator/emitter.dart index 76d1762..ca49e64 100644 --- a/lib/generator/emitter.dart +++ b/lib/generator/emitter.dart @@ -616,6 +616,10 @@ class Emitter { clazz.methods.add(new DartMethod('patch', schemaType, new DartTemplateBody(_template('object_patch'), {'type': schemaType}))); } + if (config.global) { + clazz.methods.add(new DartComplexField.getterOnly('streamyType', + new DartType('Type'), new DartConstantBody('=> ${clazz.name};'))); + } addApiType(clazz); diff --git a/lib/mixins/global.dart b/lib/mixins/global.dart index daa1881..9f66810 100644 --- a/lib/mixins/global.dart +++ b/lib/mixins/global.dart @@ -2,7 +2,7 @@ library streamy.trait.global; import 'package:streamy/streamy.dart' as streamy; -class Global { +class Global implements streamy.HasGlobal { var _global; diff --git a/lib/runtime/api.dart b/lib/runtime/api.dart index bd65edb..5b21d1c 100644 --- a/lib/runtime/api.dart +++ b/lib/runtime/api.dart @@ -20,3 +20,8 @@ abstract class Freezeable { bool get isFrozen; void freeze(); } + +abstract class HasGlobal { + Type get streamyType; + GlobalView get global; +} diff --git a/lib/runtime/global.dart b/lib/runtime/global.dart index 61ce324..f2a5358 100644 --- a/lib/runtime/global.dart +++ b/lib/runtime/global.dart @@ -66,7 +66,8 @@ abstract class GlobalView extends Observable with _FakeMap implements Map { static Map> typeToGlobals = {}; /// A real global view backed by a map of registered globals. - factory GlobalView(entity) => new _GlobalViewImpl(entity, typeToGlobals.putIfAbsent(entity.runtimeType, () => {})); + factory GlobalView(HasGlobal entity) => new _GlobalViewImpl(entity, + typeToGlobals.putIfAbsent(entity.streamyType, () => {})); /// A global view that doesn't have any globals. factory GlobalView.empty() => new _EmptyGlobalView(); @@ -77,6 +78,13 @@ abstract class GlobalView extends Observable with _FakeMap implements Map { static void register(Type type, String name, GlobalRegistration global) { typeToGlobals.putIfAbsent(type, () => {})[name] = global; } + + static void registerAll(Iterable types, String name, + GlobalRegistration global) { + types.forEach((Type type) { + typeToGlobals.putIfAbsent(type, () => {})[name] = global; + }); + } } class _GlobalViewImpl extends ChangeNotifier with _FakeMap implements GlobalView { diff --git a/test/generated/schema_object_test.dart b/test/generated/schema_object_test.dart index f8fb50f..03a4da0 100644 --- a/test/generated/schema_object_test.dart +++ b/test/generated/schema_object_test.dart @@ -267,6 +267,14 @@ main() { }, count: 1)); exDep.add(foo.id); }); + test('should work with sub-classes', () { + Foo.addGlobal('testGlobal', (e) { + expect(e.runtimeType, FooSubclass); + return 'magic'; + }); + var subject = new FooSubclass(); + expect(subject['global.testGlobal'], 'magic'); + }); }); group('patch()', () { test('works like clone() for a new basic entity', () { @@ -374,3 +382,7 @@ main() { }); }); } + +class FooSubclass extends Foo { + +} From 2152ef385d80ff48b2e12a7723ef8ba3f30d58d0 Mon Sep 17 00:00:00 2001 From: yjbanov Date: Tue, 19 Aug 2014 13:43:28 -0700 Subject: [PATCH 3/8] fix: root object must allow custom servicePath --- lib/generator/emitter.dart | 3 --- lib/templates/root_constructor.mustache | 2 +- test/generated/method_get_test.dart | 6 ++++++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/generator/emitter.dart b/lib/generator/emitter.dart index ca49e64..2e0b7f0 100644 --- a/lib/generator/emitter.dart +++ b/lib/generator/emitter.dart @@ -213,9 +213,6 @@ class Emitter { var ctorData = { 'http': api.httpConfig != null }; - if (api.httpConfig != null) { - ctorData['servicePath'] = api.httpConfig.servicePath; - } var ctor = new DartConstructor(root.name, body: new DartTemplateBody( _template('root_constructor'), ctorData)) ..parameters.add(new DartParameter('requestHandler', diff --git a/lib/templates/root_constructor.mustache b/lib/templates/root_constructor.mustache index 1876ae2..f65e7e9 100644 --- a/lib/templates/root_constructor.mustache +++ b/lib/templates/root_constructor.mustache @@ -1 +1 @@ -: super({{#http}}r'{{servicePath}}'{{/http}}); \ No newline at end of file +: super({{#http}}servicePath{{/http}}); \ No newline at end of file diff --git a/test/generated/method_get_test.dart b/test/generated/method_get_test.dart index c500620..d881e8e 100644 --- a/test/generated/method_get_test.dart +++ b/test/generated/method_get_test.dart @@ -72,4 +72,10 @@ main() { expect(f2.containsKey('baz'), isFalse); }); }); + group('Root object', () { + test('should allow specifying custom servicePath', () { + var root = new MethodGetTest(null, servicePath: '/differentPath'); + expect(root.servicePath, '/differentPath'); + }); + }); } From 15a17f5f84477fc149fb5c840b1b4df1362b6ede Mon Sep 17 00:00:00 2001 From: yjbanov Date: Wed, 20 Aug 2014 16:31:38 -0700 Subject: [PATCH 4/8] allow nested output files; remove version number in library name --- lib/generator.dart | 3 ++- lib/generator/emitter.dart | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/generator.dart b/lib/generator.dart index 58b8274..bf77fef 100644 --- a/lib/generator.dart +++ b/lib/generator.dart @@ -50,7 +50,7 @@ Future generateStreamyClientPackage( } } - var packageDirPath = '${outputDir.path}/${packageName}'; + var packageDirPath = outputDir.path; var libDirPath = '${packageDirPath}/lib'; new io.Directory(libDirPath).createSync(recursive: true); var basePath = '${libDirPath}/${client.config.outputPrefix}'; @@ -59,6 +59,7 @@ Future generateStreamyClientPackage( if (dartFile == null) return new Future.value(); var fileName = '${client.config.outputPrefix}${suffix}.dart'; var file = new io.File(path.join(libDirPath, fileName)); + new io.Directory(path.dirname(file.path)).createSync(recursive: true); file.writeAsStringSync(dartFile.render()); } diff --git a/lib/generator/emitter.dart b/lib/generator/emitter.dart index 2e0b7f0..5da471e 100644 --- a/lib/generator/emitter.dart +++ b/lib/generator/emitter.dart @@ -77,8 +77,8 @@ class Emitter { var objectFile, objectPrefix; var dispatchFile, dispatchPrefix; var libPrefix = api.name; - if (api.httpConfig != null && api.httpConfig.version != null) { - libPrefix = "$libPrefix.${api.httpConfig.version}"; + if (api.httpConfig != null) { + libPrefix = "$libPrefix"; } rootFile = new DartLibrary(libPrefix) ..imports['package:streamy/streamy.dart'] = 'streamy' From 96f146c6782fb980f82ebfe05785df2ccbfe9e7e Mon Sep 17 00:00:00 2001 From: yjbanov Date: Thu, 21 Aug 2014 11:44:08 -0700 Subject: [PATCH 5/8] make base entity library prefix more unique --- lib/generator/emitter.dart | 26 +++++++++++++++++--------- lib/templates/marshal.mustache | 2 +- lib/templates/object_ctor.mustache | 2 +- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/generator/emitter.dart b/lib/generator/emitter.dart index 5da471e..5b5b7b2 100644 --- a/lib/generator/emitter.dart +++ b/lib/generator/emitter.dart @@ -23,7 +23,9 @@ class Emitter { final Map templates; Emitter(this.config, this.templates); - + + static final BASE_PREFIX = '_streamy_base_'; + static final List TEMPLATES = const [ 'lazy_resource_getter', 'map', @@ -83,7 +85,7 @@ class Emitter { rootFile = new DartLibrary(libPrefix) ..imports['package:streamy/streamy.dart'] = 'streamy' ..imports['package:fixnum/fixnum.dart'] = 'fixnum' - ..imports[config.baseImport] = 'base' + ..imports[config.baseImport] = BASE_PREFIX ..imports['dart:async'] = null; var out = [rootFile]; switch (config.splitLevel) { @@ -122,24 +124,24 @@ class Emitter { resourceFile.imports ..['package:streamy/streamy.dart'] = 'streamy' ..['package:fixnum/fixnum.dart'] = 'fixnum' - ..[config.baseImport] = 'base' + ..[config.baseImport] = BASE_PREFIX ..[importPath('requests.dart')] = 'requests' ..[importPath('objects.dart')] = 'objects'; requestFile.imports ..['package:streamy/streamy.dart'] = 'streamy' ..['package:fixnum/fixnum.dart'] = 'fixnum' - ..[config.baseImport] = 'base' + ..[config.baseImport] = BASE_PREFIX ..[importPath('objects.dart')] = 'objects' ..[importPath('dispatch.dart')] = 'dispatch' ..['dart:async'] = null; objectFile.imports ..['package:streamy/streamy.dart'] = 'streamy' ..['package:fixnum/fixnum.dart'] = 'fixnum' - ..[config.baseImport] = 'base'; + ..[config.baseImport] = BASE_PREFIX; dispatchFile.imports ..['package:streamy/streamy.dart'] = 'streamy' ..['package:fixnum/fixnum.dart'] = 'fixnum' - ..[config.baseImport] = 'base' + ..[config.baseImport] = BASE_PREFIX ..[importPath('objects.dart')] = 'objects'; out.addAll([resourceFile, requestFile, objectFile, dispatchFile]); resourceFile.imports.addAll(api.imports); @@ -543,7 +545,7 @@ class Emitter { } SchemaDefinition processSchema(Schema schema) { - var base = new DartType(config.baseClass, 'base', const []); + var base = new DartType(config.baseClass, BASE_PREFIX, const []); var clazz = new DartClass(toProperIdentifier(schema.name), baseClass: base); clazz.mixins.addAll(schema.mixins.map((mixin) => toDartType(mixin, ''))); @@ -557,12 +559,17 @@ class Emitter { clazz.methods.add(new DartConstructor(clazz.name, body: new DartTemplateBody( ctor, { 'mapBacked': config.mapBackedFields, - 'wrap': false + 'wrap': false, + 'basePrefix': BASE_PREFIX, }))); if (config.mapBackedFields) { clazz.methods.add(new DartConstructor(clazz.name, named: 'wrap', - body: new DartTemplateBody(ctor, {'mapBacked': true, 'wrap': true})) + body: new DartTemplateBody(ctor, { + 'mapBacked': true, + 'wrap': true, + 'basePrefix': BASE_PREFIX, + })) ..parameters.add(new DartParameter('map', new DartType.map(const DartType.string(), const DartType.dynamic())))); } @@ -704,6 +711,7 @@ class Emitter { 'doubles': doubleFields, 'hasEntities': entityFields.isNotEmpty, 'hasFieldMapping': fieldMapping.isNotEmpty, + 'basePrefix': BASE_PREFIX, }; clazz.methods.add(new DartMethod('marshal$name', rt, new DartTemplateBody(marshal, serializerConfig)) diff --git a/lib/templates/marshal.mustache b/lib/templates/marshal.mustache index af83c8e..86205af 100644 --- a/lib/templates/marshal.mustache +++ b/lib/templates/marshal.mustache @@ -1,7 +1,7 @@ { {{! TODO(Alex): #fromFields behavior when #hasFieldMapping is broken. }} var res = new Map(){{#fromFields}}{{#fields}} ..[r'{{key}}'] = entity.{{identifier}}{{/fields}}{{/fromFields}}{{^fromFields}} - ..addAll(base.getMap(entity)){{/fromFields}};{{#hasInt64s}} + ..addAll({{basePrefix}}.getMap(entity)){{/fromFields}};{{#hasInt64s}} streamy.marshalToString(_int64s{{name}}, res);{{/hasInt64s}}{{#hasDoubles}} streamy.marshalToString(_doubles{{name}}, res);{{/hasDoubles}}{{#hasEntities}} streamy.handleEntities(this, _entities{{name}}, res, true);{{/hasEntities}}{{^fromFields}}{{#hasFieldMapping}} diff --git a/lib/templates/object_ctor.mustache b/lib/templates/object_ctor.mustache index b9d61ee..e8a5f7c 100644 --- a/lib/templates/object_ctor.mustache +++ b/lib/templates/object_ctor.mustache @@ -1,3 +1,3 @@ {{#mapBacked}}{ - base.setMap(this, {{#wrap}}map{{/wrap}}{{^wrap}}{}{{/wrap}}); + {{basePrefix}}.setMap(this, {{#wrap}}map{{/wrap}}{{^wrap}}{}{{/wrap}}); }{{/mapBacked}}{{^mapBacked}};{{/mapBacked}} \ No newline at end of file From 3eaea4d04d3e3fdf0a042ed8e3904f17a477767e Mon Sep 17 00:00:00 2001 From: yjbanov Date: Thu, 21 Aug 2014 17:43:20 -0700 Subject: [PATCH 6/8] add pub-server to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4c8d145..b1d271a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ test/benchmark_html.dart.* test/integration/bankapi test/integration/apigen_test/build test/integration/transformer_test/build +pub-server From d947a00cd7631908c6d4168bfb2a32f024928b3b Mon Sep 17 00:00:00 2001 From: yjbanov Date: Thu, 21 Aug 2014 18:23:27 -0700 Subject: [PATCH 7/8] fix conversion of API names to Dart identifiers --- lib/generator/emitter.dart | 84 +++++++++++++++++------------ lib/generator/service.dart | 2 +- lib/generator/util.dart | 63 +++++++++++++++++++--- test/generated/method_get_test.dart | 4 +- 4 files changed, 108 insertions(+), 45 deletions(-) diff --git a/lib/generator/emitter.dart b/lib/generator/emitter.dart index 5b5b7b2..00b54da 100644 --- a/lib/generator/emitter.dart +++ b/lib/generator/emitter.dart @@ -171,7 +171,7 @@ class Emitter { List processRoot(Api api, String resourcePrefix, String dispatchPrefix) { // Create the resource mixin class. - var resourceMixin = new DartClass('${toProperIdentifier(api.name)}ResourcesMixin'); + var resourceMixin = new DartClass('${_makeClassName(api.name)}ResourcesMixin'); if (api.description != null) { resourceMixin.comments.addAll(splitStringAcrossLines(api.description)); } @@ -180,10 +180,9 @@ class Emitter { var getterTemplate = _template('lazy_resource_getter'); api.resources.forEach((name, resource) { // Backing field. - var resName = toProperIdentifier(resource.name); - var lcResName = toProperIdentifier(resource.name, firstLetter: false); + var lcResName = _makePropertyName(resource.name); var fieldName = '_$lcResName'; - var type = new DartType('${resName}Resource', + var type = new DartType('${_makeClassName(resource.name)}Resource', resourcePrefix, const []); var field = new DartSimpleField(fieldName, type); resourceMixin.fields.add(field); @@ -200,8 +199,8 @@ class Emitter { } final marshallerType = new DartType('Marshaller', dispatchPrefix, const []); var mixinType = new DartType.from(resourceMixin); - var txClassName = toProperIdentifier('${api.name}Transaction'); - var root = new DartClass(toProperIdentifier(api.name), baseClass: baseType) + var txClassName = _makeClassName('${api.name}Transaction'); + var root = new DartClass(_makeClassName(api.name), baseClass: baseType) ..mixins.add(mixinType) ..fields.add(new DartSimpleField('marshaller', marshallerType, isFinal: true)) ..fields.add(new DartSimpleField('requestHandler', streamyImport('RequestHandler'), isFinal: true)) @@ -272,8 +271,7 @@ class Emitter { DartClass processResource(Resource resource, String requestPrefix, String objectPrefix) { - var name = toProperIdentifier(resource.name); - var clazz = new DartClass('${toProperIdentifier(resource.name)}Resource'); + var clazz = new DartClass('${_makeClassName(resource.name)}Resource'); var requestMethodTemplate = _template('request_method'); // Set up a _root field for the implementation RequestHandler, and a @@ -315,10 +313,10 @@ class Emitter { } var requestType = new DartType( - '${toProperIdentifier(resource.name)}${toProperIdentifier(method.name)}Request', + '${_makeClassName(resource.name)}${_makeClassName(method.name)}Request', requestPrefix, const []); - var m = new DartMethod(toProperIdentifier(method.name, firstLetter: false), requestType, + var m = new DartMethod(_makeMethodName(method.name), requestType, new DartTemplateBody(requestMethodTemplate, { 'requestType': requestType, 'parameters': pnames @@ -344,15 +342,17 @@ class Emitter { .expand((resource) => resource .methods .values - .map((method) => processRequest(api, toProperIdentifier(resource.name), method, objectPrefix, dispatchPrefix)) + .map((method) => processRequest(api, _makeClassName(resource.name), + method, objectPrefix, dispatchPrefix)) ) .toList(growable: false); - - DartClass processRequest(Api api, String resourceName, Method method, String objectPrefix, String dispatchPrefix) { + + DartClass processRequest(Api api, String resourceClassName, Method method, + String objectPrefix, String dispatchPrefix) { var paramGetter = _template('request_param_getter'); var paramSetter = _template('request_param_setter'); - var methodName = toProperIdentifier(method.name); - var clazz = new DartClass('$resourceName${methodName}Request', + var methodName = _makeClassName(method.name); + var clazz = new DartClass('$resourceClassName${methodName}Request', baseClass: streamyImport('HttpRequest')); // Determine payload type. @@ -395,10 +395,10 @@ class Emitter { method.parameters.forEach((name, param) { var type = toDartType(param.typeRef, objectPrefix); clazz.fields.add( - new DartComplexField(toProperIdentifier(name, firstLetter: false), type, + new DartComplexField(_makePropertyName(name), type, new DartTemplateBody(paramGetter, {'name': name}), new DartTemplateBody(paramSetter, {'name': name}))); - clazz.methods.add(new DartMethod(toProperIdentifier('remove_$name', firstLetter: false), type, + clazz.methods.add(new DartMethod(_makeRemoverName(name), type, new DartTemplateBody(_template('request_remove'), {'name': name}))); }); @@ -470,7 +470,7 @@ class Emitter { if (responseType != null && api.httpConfig != null) { clazz.methods.add(new DartMethod('unmarshalResponse', responseType, new DartTemplateBody(_template('request_unmarshal_response'), { - 'name': toProperIdentifier(method.responseType.schemaClass) + 'name': _makeClassName((method.responseType as SchemaTypeRef).schemaClass) })) ..parameters.add(new DartParameter('data', new DartType('Map', null, const [])))); } @@ -478,7 +478,7 @@ class Emitter { if (method.payloadType != null) { clazz.methods.add(new DartMethod('marshalPayload', new DartType('Map'), new DartTemplateBody(_template('request_marshal_payload'), { - 'name': toProperIdentifier(method.payloadType.schemaClass) + 'name': _makeClassName((method.payloadType as SchemaTypeRef).schemaClass) }))); } } @@ -546,7 +546,7 @@ class Emitter { SchemaDefinition processSchema(Schema schema) { var base = new DartType(config.baseClass, BASE_PREFIX, const []); - var clazz = new DartClass(toProperIdentifier(schema.name), baseClass: base); + var clazz = new DartClass(_makeClassName(schema.name), baseClass: base); clazz.mixins.addAll(schema.mixins.map((mixin) => toDartType(mixin, ''))); var globalFnDef = null; @@ -593,7 +593,7 @@ class Emitter { schema.properties.forEach((_, field) { // Add getter and setter, delegating to map access. - var name = toProperIdentifier(field.name, firstLetter: false); + var name = _makePropertyName(field.name); var type = toDartType(field.typeRef, null); if (config.mapBackedFields) { var f = new DartComplexField(name, type, @@ -601,7 +601,7 @@ class Emitter { new DartTemplateBody(setter, {'name': field.name})); clazz.fields.add(f); if (config.removers) { - var r = new DartMethod('remove${toProperIdentifier(field.name)}', type, + var r = new DartMethod(_makeRemoverName(field.name), type, new DartTemplateBody(remove, {'name': field.name})); clazz.methods.add(r); } @@ -639,16 +639,17 @@ class Emitter { doubleFields.add(name); break; case 'schema': - entityFields[name] = typeRef.schemaClass; + entityFields[name] = (typeRef as SchemaTypeRef).schemaClass; break; case 'list': - _accumulateMarshallingTypes(name, typeRef.subType, int64Fields, doubleFields, entityFields); + _accumulateMarshallingTypes(name, (typeRef as ListTypeRef).subType, + int64Fields, doubleFields, entityFields); break; } } void processSchemaForMarshaller(DartClass clazz, Schema schema, String objectPrefix) { - var name = toProperIdentifier(schema.name); + var name = _makeClassName(schema.name); var type = new DartType(name, objectPrefix, const []); var rt = new DartType.map(const DartType.string(), const DartType.dynamic()); var data = { @@ -665,17 +666,25 @@ class Emitter { schema .properties .forEach((_, field) { - _accumulateMarshallingTypes(field.name, field.typeRef, int64Fields, doubleFields, entityFields); - allFields.add({'key': field.name, 'identifier': toProperIdentifier(field.name, firstLetter: false)}); + _accumulateMarshallingTypes(field.name, field.typeRef, int64Fields, + doubleFields, entityFields); + allFields.add({ + 'key': field.name, + 'identifier': _makePropertyName(field.name), + }); }); var stringList = new DartType.list(const DartType.string()); var serialMap = new DartType('Map'); if (int64Fields.isNotEmpty) { - clazz.fields.add(new DartSimpleField('_int64s$name', stringList, isStatic: true, isFinal: true, initializer: stringListBody(int64Fields))); + clazz.fields.add(new DartSimpleField('_int64s$name', stringList, + isStatic: true, isFinal: true, + initializer: stringListBody(int64Fields))); } if (doubleFields.isNotEmpty) { - clazz.fields.add(new DartSimpleField('_doubles$name', stringList, isStatic: true, isFinal: true, initializer: stringListBody(doubleFields))); + clazz.fields.add(new DartSimpleField('_doubles$name', stringList, + isStatic: true, isFinal: true, + initializer: stringListBody(doubleFields))); } var fieldMapping = {}; @@ -695,10 +704,17 @@ class Emitter { if (entityFields.isNotEmpty) { var data = []; entityFields.forEach((name, schema) { - data.add({'key': name, 'value': '_handle${toProperIdentifier(schema)}'}); + data.add({ + 'key': name, + 'value': _makeHandlerName(schema), + }); }); clazz.fields.add(new DartComplexField.getterOnly('_entities$name', rt, - new DartTemplateBody(_template('map'), {'pairs': data, 'getter': true, 'const': false}))); + new DartTemplateBody(_template('map'), { + 'pairs': data, + 'getter': true, + 'const': false, + }))); } var serializerConfig = { 'entity': type, @@ -764,7 +780,7 @@ class Emitter { if (ref is ListTypeRef) { return new DartType.list(toDartType(ref.subType, objectPrefix)); } else if (ref is SchemaTypeRef) { - return new DartType(toProperIdentifier(ref.schemaClass), objectPrefix, const []); + return new DartType(_makeClassName(ref.schemaClass), objectPrefix, const []); } else { switch (ref.base) { case 'int64': @@ -782,7 +798,9 @@ class Emitter { case 'number': return const DartType.double(); case 'external': - return new DartType(ref.type, ref.importedFrom, const []); + ExternalTypeRef externalTypeRef = ref; + return new DartType(externalTypeRef.type, + externalTypeRef.importedFrom, const []); default: throw new Exception('Unhandled API type: $ref'); } diff --git a/lib/generator/service.dart b/lib/generator/service.dart index 36e45b3..28b7897 100644 --- a/lib/generator/service.dart +++ b/lib/generator/service.dart @@ -47,7 +47,7 @@ void _parseService(Api api, String importPath, analyzer.ClassDeclaration clazz) var method = new Method(m.name.name, new Path('/'), '', null, ref); res.methods[method.name] = method; // Need a request class for the method. - var name = '${res.name}${toProperIdentifier(m.name.name)}Request'; + var name = '${res.name}${_makeClassName(m.name.name)}Request'; m .parameters .parameters diff --git a/lib/generator/util.dart b/lib/generator/util.dart index 6f5da53..0e5f79f 100644 --- a/lib/generator/util.dart +++ b/lib/generator/util.dart @@ -1,8 +1,47 @@ part of streamy.generator; -String toProperIdentifier(String identifier, {firstLetter: true}) { - var first = !firstLetter; - var name = identifier +String _makePropertyName(String name) { + name = _fixIllegalChars(name); + if (_ILLEGAL_PROPERTY_NAMES.contains(name)) { + name = '\$${name}'; + } + return name; +} + +String _makeMethodName(String name) { + name = _fixIllegalChars(name); + if (_ILLEGAL_METHOD_NAMES.contains(name)) { + name = '\$${name}'; + } + return name; +} + +String _makeRemoverName(String name) { + name = _capitalize(_fixIllegalChars(name)); + return 'remove${name}'; +} + +String _makeHandlerName(String name) { + name = _capitalize(_fixIllegalChars(name)); + return '_handle${name}'; +} + +String _makeClassName(String name) { + name = _capitalize(_fixIllegalChars(name)); + if (_ILLEGAL_CLASS_NAMES.contains(name)) { + name = '\$${name}'; + } + return name; +} + +String _fixIllegalChars(String name) { + if (name.length == 0) { + throw new StateError('Empty property, schema, resource or method name'); + } + + // Make names like foo_bar_baz look like fooBarBaz + var first = true; + name = name .split('_') .map((piece) { if (first) { @@ -16,22 +55,30 @@ String toProperIdentifier(String identifier, {firstLetter: true}) { } }) .join(); - if (name.length == 0) { - throw new StateError('Empty property, schema, resource or method name'); - } + // Replace bad starting character with dollar sign (it has to be public) - if (!name.startsWith(IDENTIFIER_START)) { + if(!name.startsWith(IDENTIFIER_START)) { name = '\$${name.substring(1)}'; } + // Replace bad characters in the middle with underscore name = name.replaceAll(NON_IDENTIFIER_CHAR_MATCHER, '_'); if (name.startsWith('_')) { name = 'clean${name}'; } + return name; } - + +/// Turns the first letter in a string to a capital letter. +String _capitalize(String str) { + if (str == null || str.length == 0) { + return str; + } + return str[0].toUpperCase() + str.substring(1); +} + List splitStringAcrossLines(String src, [int maxLen = 80]) { var lines = []; var words = src.split(' '); diff --git a/test/generated/method_get_test.dart b/test/generated/method_get_test.dart index d881e8e..6ec6fba 100644 --- a/test/generated/method_get_test.dart +++ b/test/generated/method_get_test.dart @@ -42,13 +42,11 @@ main() { expect(MethodGetTest.API_TYPE, 'MethodGetTest'); expect(new MethodGetTest(null).apiType, 'MethodGetTest'); }); - /* TODO: fix test test('of MethodGetTestTransaction', () { expect(MethodGetTestTransaction.API_TYPE, 'MethodGetTestTransaction'); - expect(new MethodGetTestTransaction(null, null).apiType, + expect(new MethodGetTestTransaction(null, null, null).apiType, 'MethodGetTestTransaction'); }); - */ test('of Foo', () { expect(Foo.API_TYPE, 'Foo'); expect(new Foo().apiType, 'Foo'); From 631ca7b76e47162b1d8daa77604045d73390b128 Mon Sep 17 00:00:00 2001 From: yjbanov Date: Fri, 22 Aug 2014 15:25:49 -0700 Subject: [PATCH 8/8] fix reference to wrong request var in impl.dart --- lib/impl.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/impl.dart b/lib/impl.dart index b6bde54..26b1b14 100644 --- a/lib/impl.dart +++ b/lib/impl.dart @@ -39,7 +39,7 @@ class SimpleRequestHandler extends RequestHandler { if (resp.statusCode >= 200 && resp.statusCode < 300) { var responseJson = jsonParse(resp.body, trace); trace.record(new DeserializationStartEvent(resp.body.length)); - var responsePayload = req.unmarshalResponse(responseJson); + var responsePayload = request.unmarshalResponse(responseJson); trace.record(new DeserializationEndEvent()); ctrl.add(new Response(responsePayload, Source.RPC, new DateTime.now().millisecondsSinceEpoch));