public StandardLro(ServiceDetails svc, MethodDescriptor desc) : base(svc, desc)
            {
                OperationInfo lroData = desc.GetExtension(OperationsExtensions.OperationInfo);

                if (lroData is null)
                {
                    throw new InvalidOperationException("LRO method must contain a `google.api.operation` option.");
                }
                ApiCallTyp = Typ.Generic(typeof(ApiCall <,>), RequestTyp, Typ.Of <Operation>());
                if (string.IsNullOrEmpty(lroData.ResponseType) || string.IsNullOrEmpty(lroData.MetadataType))
                {
                    throw new InvalidOperationException($"Both response-type and metadata-type must be present for method: '{desc.FullName}'.");
                }
                var responseTypeMsg = svc.Catalog.GetMessageByName(lroData.ResponseType);
                var metadataTypeMsg = svc.Catalog.GetMessageByName(lroData.MetadataType);

                if (responseTypeMsg is null || metadataTypeMsg is null)
                {
                    throw new InvalidOperationException(
                              $"Response-type and Metadata-type must both exist in method '{desc.FullName}': '{lroData.ResponseType}', '{lroData.MetadataType}'.");
                }
                OperationResponseTyp = ProtoTyp.Of(responseTypeMsg);
                OperationMetadataTyp = ProtoTyp.Of(metadataTypeMsg);
                SyncReturnTyp        = Typ.Generic(typeof(Operation <,>), OperationResponseTyp, OperationMetadataTyp);
            }
                public Field(ServiceDetails svc, MessageDescriptor msg, string fieldName)
                {
                    Descs = fieldName.Split('.').Aggregate((msg, result: ImmutableList <FieldDescriptor> .Empty), (acc, part) =>
                    {
                        // TODO: Check nested fields aren't repeated.
                        var fieldDesc = acc.msg.FindFieldByName(part);
                        if (fieldDesc == null)
                        {
                            throw new InvalidOperationException($"Field '{part}' does not exist in message: {acc.msg.FullName}");
                        }
                        return(fieldDesc.FieldType == FieldType.Message ? fieldDesc.MessageType : null, acc.result.Add(fieldDesc));
                    }, acc => acc.result);
                    var lastDesc = Descs.Last();

                    Typ            = ProtoTyp.Of(lastDesc);
                    IsMap          = lastDesc.IsMap;
                    IsRepeated     = lastDesc.IsRepeated;
                    IsWrapperType  = ProtoTyp.IsWrapperType(lastDesc);
                    IsRequired     = lastDesc.GetExtension(FieldBehaviorExtensions.FieldBehavior).Any(x => x == FieldBehavior.Required);
                    ParameterName  = lastDesc.CSharpFieldName();
                    PropertyName   = lastDesc.CSharpPropertyName();
                    IsDeprecated   = Descs.Any(x => x.IsDeprecated());
                    DocLines       = lastDesc.Declaration.DocLines();
                    FieldResources = svc.Catalog.GetResourceDetailsByField(lastDesc);
                }
        private MethodDetails(ServiceDetails svc, MethodDescriptor desc)
        {
            Svc                     = svc;
            ProtoRpcName            = desc.Name;
            SyncMethodName          = desc.Name;
            SyncSnippetMethodName   = $"{desc.Name}RequestObject";
            SyncTestMethodName      = $"{desc.Name}RequestObject";
            AsyncMethodName         = $"{desc.Name}Async";
            AsyncSnippetMethodName  = $"{desc.Name}RequestObjectAsync";
            AsyncTestMethodName     = $"{desc.Name}RequestObjectAsync";
            SettingsName            = $"{desc.Name}Settings";
            RequestTyp              = ProtoTyp.Of(desc.InputType);
            ResponseTyp             = ProtoTyp.Of(desc.OutputType);
            ApiCallFieldName        = $"_call{desc.Name}";
            ModifyApiCallMethodName = $"Modify_{desc.Name}ApiCall";
            ModifyRequestMethodName = $"Modify_{RequestTyp.Name}";
            DocLines                = desc.Declaration.DocLines().ToList();
            Signatures              = desc.GetExtension(ClientExtensions.MethodSignature).Select(sig => new Signature(svc, desc.InputType, sig)).ToList();
            RequestMessageDesc      = desc.InputType;
            ResponseMessageDesc     = desc.OutputType;
            var http    = desc.GetExtension(AnnotationsExtensions.Http);
            var routing = desc.GetExtension(RoutingExtensions.Routing);

            RoutingHeaders = ReadRoutingHeaders(routing, http, desc.InputType).ToList();
            (MethodRetry, MethodRetryStatusCodes, Expiration) = LoadTiming(svc, desc);
            // The method is considered deprecated if the RPC, request or response messages are deprecated.
            // In reality, it would be very odd to deprecate the messages without deprecating the RPC, but this makes it consistent.
            IsDeprecated = desc.IsDeprecated() || RequestMessageDesc.IsDeprecated() || ResponseMessageDesc.IsDeprecated();
        }
                private MethodDeclarationSyntax AbstractRequestMethod(bool sync, bool callSettings, IEnumerable <ParameterInfo> parameters, DocumentationCommentTriviaSyntax returnsXmlDoc = null)
                {
                    var returnTyp        = sync ? MethodDetails.SyncReturnTyp : MethodDetails.AsyncReturnTyp;
                    var methodName       = sync ? MethodDetails.SyncMethodName : MethodDetails.AsyncMethodName;
                    var finalParam       = callSettings ? _def.CallSettingsParam : _def.CancellationTokenParam;
                    var finalParamXmlDoc = callSettings ? _def.CallSettingsXmlDoc : _def.CancellationTokenXmlDoc;

                    returnsXmlDoc = returnsXmlDoc ?? (sync ?
                                                      MethodDetails is MethodDetails.Paginated ? _def.ReturnsSyncPaginatedXmlDoc : _def.ReturnsSyncXmlDoc :
                                                      MethodDetails is MethodDetails.Paginated ? _def.ReturnsAsyncPaginatedXmlDoc : _def.ReturnsAsyncXmlDoc);
                    if (callSettings)
                    {
                        return(Method(Public | Virtual, Ctx.Type(returnTyp), methodName)(parameters.Select(x => x.Parameter).Append(finalParam).ToArray())
                               .MaybeWithAttribute(MethodDetails.IsDeprecated || _sig.HasDeprecatedField, () => Ctx.Type <ObsoleteAttribute>())()
                               .WithBody(This.Call(methodName)(New(Ctx.Type(MethodDetails.RequestTyp))()
                                                               .WithInitializer(NestInit(parameters, 0).ToArray()), finalParam))
                               .WithXmlDoc(parameters.Select(x => x.XmlDoc).Prepend(_def.SummaryXmlDoc).Append(finalParamXmlDoc).Append(returnsXmlDoc).ToArray()));

                        IEnumerable <ObjectInitExpr> NestInit(IEnumerable <ParameterInfo> ps, int ofs)
                        {
                            var byField = ps.GroupBy(x => (x.FieldDescs ?? Enumerable.Empty <FieldDescriptor>()).Skip(ofs).SkipLast(1).FirstOrDefault())
                                          .OrderBy(x => x.Key?.Index);

                            foreach (var f in byField)
                            {
                                if (f.Key == null)
                                {
                                    // No more nesting, these are the actual fields that need filling.
                                    foreach (var param in f.OrderBy(x => x.FieldDescs?.Last().Index ?? int.MaxValue))
                                    {
                                        // Note: even if the signature includes a deprecated field, we don't indicate that in the
                                        // ObjectInitExpr, as we don't want or need the pragma when the method we're generating is obsolete.
                                        yield return((param.InitExpr as ObjectInitExpr) ??
                                                     new ObjectInitExpr(param.ResourcePropertyName ?? param.FieldDescs.Last().CSharpPropertyName(), param.InitExpr));
                                    }
                                }
                                else
                                {
                                    // Nested field.
                                    var code = New(Ctx.Type(ProtoTyp.Of(f.Key)))().WithInitializer(NestInit(f, ofs + 1).ToArray());
                                    yield return(new ObjectInitExpr(f.Key.CSharpPropertyName(), code));
                                }
                            }
                        }
                    }
                    else
                    {
                        return(Method(Public | Virtual, Ctx.Type(returnTyp), methodName)(parameters.Select(x => x.Parameter).Append(finalParam).ToArray())
                               .MaybeWithAttribute(MethodDetails.IsDeprecated || _sig.HasDeprecatedField, () => Ctx.Type <ObsoleteAttribute>())()
                               .WithBody(This.Call(methodName)(parameters.Select(x => (object)x.Parameter).Append(
                                                                   Ctx.Type <CallSettings>().Call(nameof(CallSettings.FromCancellationToken))(finalParam))))
                               .WithXmlDoc(parameters.Select(x => x.XmlDoc).Prepend(_def.SummaryXmlDoc).Append(finalParamXmlDoc).Append(returnsXmlDoc).ToArray()));
                    }
                }
Пример #5
0
 public Paginated(ServiceDetails svc, MethodDescriptor desc,
                  FieldDescriptor responseResourceField, int pageSizeFieldNumber, int pageTokenFieldNumber) : base(svc, desc)
 {
     ResourceTyp          = ProtoTyp.Of(responseResourceField, forceRepeated: false);
     ApiCallTyp           = Typ.Generic(typeof(ApiCall <,>), RequestTyp, ResponseTyp);
     SyncReturnTyp        = Typ.Generic(typeof(PagedEnumerable <,>), ResponseTyp, ResourceTyp);
     AsyncReturnTyp       = Typ.Generic(typeof(PagedAsyncEnumerable <,>), ResponseTyp, ResourceTyp);
     SyncGrpcType         = Typ.Generic(typeof(GrpcPagedEnumerable <, ,>), RequestTyp, ResponseTyp, ResourceTyp);
     AsyncGrpcType        = Typ.Generic(typeof(GrpcPagedAsyncEnumerable <, ,>), RequestTyp, ResponseTyp, ResourceTyp);
     ResourcesFieldName   = responseResourceField.CSharpPropertyName();
     PageSizeFieldNumber  = pageSizeFieldNumber;
     PageTokenFieldNumber = pageTokenFieldNumber;
 }
 public Paginated(ServiceDetails svc, MethodDescriptor desc,
                  FieldDescriptor responseResourceField, int pageSizeFieldNumber, int pageTokenFieldNumber) : base(svc, desc)
 {
     ResourceTyp = ProtoTyp.Of(responseResourceField, forceRepeated: false);
     // For map fields, ResourceTyp is a constructed KeyValuePair<,> type: we need the open type in a cref.
     ResourceTypForCref = responseResourceField.IsMap
         ? Typ.Generic(typeof(KeyValuePair <,>), Typ.GenericParam("TKey"), Typ.GenericParam("TValue"))
         : ResourceTyp;
     ApiCallTyp           = Typ.Generic(typeof(ApiCall <,>), RequestTyp, ResponseTyp);
     SyncReturnTyp        = Typ.Generic(typeof(PagedEnumerable <,>), ResponseTyp, ResourceTyp);
     AsyncReturnTyp       = Typ.Generic(typeof(PagedAsyncEnumerable <,>), ResponseTyp, ResourceTyp);
     SyncGrpcType         = Typ.Generic(typeof(GrpcPagedEnumerable <, ,>), RequestTyp, ResponseTyp, ResourceTyp);
     AsyncGrpcType        = Typ.Generic(typeof(GrpcPagedAsyncEnumerable <, ,>), RequestTyp, ResponseTyp, ResourceTyp);
     ResourcesFieldName   = responseResourceField.CSharpPropertyName();
     PageSizeFieldNumber  = pageSizeFieldNumber;
     PageTokenFieldNumber = pageTokenFieldNumber;
 }
Пример #7
0
        private static MemberDeclarationSyntax PaginatedPartialInterfaceClass(SourceFileContext ctx, Typ typ, MessageDescriptor messageDesc)
        {
            var partialInterfaceCls = Class(Public | Partial, typ, baseTypes: ctx.Type <IPageRequest>());

            if (messageDesc.FindFieldByName("page_size") is null)
            {
                //DiREGapic scenario where `max_results` is an option for a page size-semantic field.
                var maxResMessage = messageDesc.FindFieldByName("max_results");
                if (maxResMessage is null)
                {
                    throw new InvalidOperationException("Paginated request should have either page_size or max_results field.");
                }

                using (ctx.InClass(partialInterfaceCls))
                {
                    var underlyingProperty = Property(DontCare, ctx.TypeDontCare, "MaxResults");

                    var getBody = ProtoTyp.Of(maxResMessage) == Typ.Of <int>()
                        ? Return(underlyingProperty)
                        : Return(CheckedCast(ctx.Type <int>(), underlyingProperty));

                    var assignFrom = ProtoTyp.Of(maxResMessage) == Typ.Of <int>()
                        ? Value
                        : CheckedCast(ctx.Type(ProtoTyp.Of(maxResMessage)), Value);
                    var setBody = underlyingProperty.Assign(assignFrom);

                    var property = Property(Public, ctx.Type <int>(), "PageSize")
                                   .WithGetBody(getBody)
                                   .WithSetBody(setBody)
                                   .WithXmlDoc(XmlDoc.InheritDoc);
                    partialInterfaceCls = partialInterfaceCls.AddMembers(property);
                }
            }

            return(partialInterfaceCls);
        }
Пример #8
0
        private static ClassDeclarationSyntax GenerateClass(string ns, SourceFileContext ctx, IEnumerable <FileDescriptor> packageFileDescriptors)
        {
            var typ = Typ.Manual(ns, ClassName);
            var cls = Class(Internal | Static, typ)
                      .WithXmlDoc(XmlDoc.Summary("Static class to provide common access to package-wide API metadata."));

            var yieldStatements      = packageFileDescriptors.Select(GenerateYieldStatement).ToArray();
            var fileDescriptorMethod = Method(Private | Static, ctx.Type(Typ.Of <IEnumerable <FileDescriptor> >()), "GetFileDescriptors")()
                                       .WithBlockBody(yieldStatements);

            var apiMetadataType = ctx.Type <ApiMetadata>();
            var property        = AutoProperty(Internal | Static, apiMetadataType, PropertyName)
                                  .WithInitializer(New(apiMetadataType)(ns, IdentifierName(fileDescriptorMethod.Identifier)))
                                  .WithXmlDoc(XmlDoc.Summary("The ", apiMetadataType, " for services in this package."));

            return(cls.AddMembers(property, fileDescriptorMethod));

            YieldStatementSyntax GenerateYieldStatement(FileDescriptor descriptor)
            {
                var type = ctx.Type(ProtoTyp.OfReflectionClass(descriptor));

                return(YieldStatement(SyntaxKind.YieldReturnStatement, type.Access("Descriptor")));
            }
        }