private IEnumerable <MethodDeclarationSyntax> ParseMethods() { var paramName = _def.ResourceNameTyp.Name.ToLowerCamelCase(); var name = Parameter(_ctx.Type <string>(), paramName); var allowUnparsed = Parameter(_ctx.Type <bool>(), "allowUnparsed"); var result = Parameter(_ctx.Type(_def.ResourceNameTyp), "result").Out(); var resultLocal = Local(_ctx.Type(_def.ResourceNameTyp), "result"); var resourceName = Local(_ctx.Type <TemplatedResourceName>(), paramName == "resourceName" ? "resourceName2" : "resourceName"); var unparsedResourceName = Local(_ctx.Type <UnparsedResourceName>(), "unparsedResourceName"); MethodDeclarationSyntax parseSplitHelper; if (PatternDetails.SelectMany(x => x.PathSegments).Any(x => x.Segment.IsComplex)) { var s = Parameter(_ctx.Type <string>(), "s"); var separators = Parameter(_ctx.ArrayType <char[]>(), "separators"); var i0 = Local(_ctx.Type <int>(), "i0"); var i1 = Local(_ctx.Type <int>(), "i1"); var i = Local(_ctx.Type <int>(), "i"); var pshResult = Local(_ctx.ArrayType <string[]>(), "result"); parseSplitHelper = Method(Private | Static, _ctx.ArrayType <string[]>(), "ParseSplitHelper")(s, separators) .WithBody( pshResult.WithInitializer(NewArray(_ctx.ArrayType <string[]>(), separators.Access(nameof(Array.Length)).Plus(1))), i0.WithInitializer(0), For(i.WithInitializer(0), i.LessThanOrEqual(separators.Access(nameof(Array.Length))), i.PlusPlus())( i1.WithInitializer(i.LessThan(separators.Access(nameof(Array.Length))).ConditionalOperator( s.Call(nameof(string.IndexOf))(separators.ElementAccess(i), i0), s.Access(nameof(string.Length)))), If(i1.LessThan(0).Or(i1.Equality(i0))).Then(Return(Null)), pshResult.ElementAccess(i).Assign(s.Call(nameof(string.Substring))(i0, i1.Minus(i0))), i0.Assign(i1.Plus(1))), Return(pshResult)); } else { parseSplitHelper = null; } var tryParse2 = Method(Public | Static, _ctx.Type <bool>(), "TryParse")(name, allowUnparsed, result) .WithBody( _ctx.Type(typeof(GaxPreconditions)).Call(nameof(GaxPreconditions.CheckNotNull))(name, Nameof(name)), resourceName, PatternDetails.Zip(FromMethods(), (pattern, create) => { IEnumerable <(object code, IEnumerable <ExpressionSyntax> args)> codeAndArgs = pattern.PathSegments .Where(x => x.Segment.ParameterCount > 0) .Select((seg, segmentIndex) => { if (seg.Segment.IsComplex) { var splitResult = Local(_ctx.ArrayType <string[]>(), $"split{segmentIndex}") .WithInitializer(This.Call(parseSplitHelper)( resourceName.ElementAccess(segmentIndex), NewArray(_ctx.ArrayType <char[]>())(seg.Segment.Separators.ToArray()))); var splitIf = If(splitResult.Equality(Null)).Then( result.Assign(Null), Return(false)); var args = Enumerable.Range(0, seg.Segment.ParameterCount).Select(i => splitResult.ElementAccess(i)); return((object)new object[] { splitResult, splitIf }, args); } else { return((object)null, new[] { resourceName.ElementAccess(segmentIndex) }); } }); var elements = codeAndArgs.SelectMany(x => x.args); return(If(pattern.PathTemplateField.Call(nameof(PathTemplate.TryParseName))(name, Out(resourceName))).Then( codeAndArgs.Select(x => x.code), result.Assign(This.Call(create)(elements.ToArray())), Return(true))); }),
public ClassDeclarationSyntax GenerateServiceClass(SourceFileContext ctx) { var cls = Class(Modifier.Public, ServiceTyp, ctx.Type <BaseClientService>()).WithXmlDoc(XmlDoc.Summary($"The {ClassName} Service.")); using (ctx.InClass(cls)) { var discoveryVersionTyp = Typ.Manual("Google.Apis.Discovery", "DiscoveryVersion"); var version = Field(Modifier.Public | Modifier.Const, ctx.Type <string>(), "Version") .WithInitializer(ApiVersion) .WithXmlDoc(XmlDoc.Summary("The API version.")); var discoveryVersion = Field(Modifier.Public | Modifier.Static, ctx.Type(discoveryVersionTyp), "DiscoveryVersionUsed") .WithInitializer(ctx.Type(discoveryVersionTyp).Access(nameof(DiscoveryVersion.Version_1_0))) .WithXmlDoc(XmlDoc.Summary("The discovery version used to generate this service.")); var parameterlessCtor = Ctor(Modifier.Public, cls, ThisInitializer(New(ctx.Type <BaseClientService.Initializer>())()))() .WithBody() .WithXmlDoc(XmlDoc.Summary("Constructs a new service.")); var initializerParam = Parameter(ctx.Type <BaseClientService.Initializer>(), "initializer"); var featuresArrayInitializer = ApiFeatures.Any() ? NewArray(ctx.ArrayType(Typ.Of <string[]>()))(ApiFeatures.ToArray()) : NewArray(ctx.ArrayType(Typ.Of <string[]>()), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0))); var features = Property(Modifier.Public | Modifier.Override, ctx.Type <IList <string> >(), "Features") .WithGetBody(featuresArrayInitializer) .WithXmlDoc(XmlDoc.Summary("Gets the service supported features.")); var nameProperty = Property(Modifier.Public | Modifier.Override, ctx.Type <string>(), "Name") .WithGetBody(ApiName) .WithXmlDoc(XmlDoc.Summary("Gets the service name.")); // Note: the following 4 properties have special handling post-generation, in terms // of adding the #if directives in. var baseUri = Property(Modifier.Public | Modifier.Override, ctx.Type <string>(), "BaseUri") .WithGetBody(IdentifierName("BaseUriOverride").NullCoalesce(BaseUri)) .WithXmlDoc(XmlDoc.Summary("Gets the service base URI.")); var basePath = Property(Modifier.Public | Modifier.Override, ctx.Type <string>(), "BasePath") .WithGetBody(BasePath) .WithXmlDoc(XmlDoc.Summary("Gets the service base path.")); var batchUri = Property(Modifier.Public | Modifier.Override, ctx.Type <string>(), "BatchUri") .WithGetBody(BatchUri) .WithXmlDoc(XmlDoc.Summary("Gets the batch base URI; ", XmlDoc.C("null"), " if unspecified.")); var batchPath = Property(Modifier.Public | Modifier.Override, ctx.Type <string>(), "BatchPath") .WithGetBody(BatchPath) .WithXmlDoc(XmlDoc.Summary("Gets the batch base path; ", XmlDoc.C("null"), " if unspecified.")); var resourceProperties = Resources.Select(resource => resource.GenerateProperty(ctx)).ToArray(); var parameterizedCtor = Ctor(Modifier.Public, cls, BaseInitializer(initializerParam))(initializerParam) .WithBlockBody(resourceProperties.Zip(Resources).Select(pair => pair.First.Assign(New(ctx.Type(pair.Second.Typ))(This))).ToArray()) .WithXmlDoc( XmlDoc.Summary("Constructs a new service."), XmlDoc.Param(initializerParam, "The service initializer.")); cls = cls.AddMembers(version, discoveryVersion, parameterlessCtor, parameterizedCtor, features, nameProperty, baseUri, basePath, batchUri, batchPath); if (AuthScopes.Any()) { var scopeClass = Class(Modifier.Public, Typ.Manual(PackageName, "Scope")) .WithXmlDoc(XmlDoc.Summary($"Available OAuth 2.0 scopes for use with the {Title}.")); using (ctx.InClass(scopeClass)) { foreach (var scope in AuthScopes) { var field = Field(Modifier.Public | Modifier.Static, ctx.Type <string>(), scope.Name) .WithInitializer(scope.Value) .WithXmlDoc(XmlDoc.Summary(scope.Description)); scopeClass = scopeClass.AddMembers(field); } } var scopeConstantsClass = Class(Modifier.Public | Modifier.Static, Typ.Manual(PackageName, "ScopeConstants")) .WithXmlDoc(XmlDoc.Summary($"Available OAuth 2.0 scope constants for use with the {Title}.")); using (ctx.InClass(scopeConstantsClass)) { foreach (var scope in AuthScopes) { var field = Field(Modifier.Public | Modifier.Const, ctx.Type <string>(), scope.Name) .WithInitializer(scope.Value) .WithXmlDoc(XmlDoc.Summary(scope.Description)); scopeConstantsClass = scopeConstantsClass.AddMembers(field); } } cls = cls.AddMembers(scopeClass, scopeConstantsClass); } // TODO: Find an example of this... foreach (var method in Methods) { cls = cls.AddMembers(method.GenerateDeclarations(ctx).ToArray()); } cls = cls.AddMembers(resourceProperties); } return(cls); }