コード例 #1
0
ファイル: SliceLiteral.cs プロジェクト: Azure/autorest.go
        /// <summary>
        /// Generates a slice literal of the specified type name and optional values.
        /// </summary>
        /// <param name="typeName">The fully qualified slice type name.</param>
        /// <param name="values">Optional slice values.  Pass null to omit values.</param>
        /// <returns>The root node in this slice literal AST.</returns>
        public static Node Generate(string typeName, IEnumerable <Node> values)
        {
            if (string.IsNullOrWhiteSpace(typeName))
            {
                throw new ArgumentException(nameof(typeName));
            }

            if (values != null && !values.Any())
            {
                throw new ArgumentException("pass null for no slice elements");
            }

            var openBracket  = new OpenDelimiter(BinaryDelimiterType.Bracket);
            var closeBracket = openBracket.AddClosingDelimiter();

            var id = new Identifier(typeName);

            closeBracket.AddChild(id);

            var openBrace = new OpenDelimiter(BinaryDelimiterType.Brace);

            if (values != null)
            {
                var seq = DelimitedSequence.Generate(UnaryDelimiterType.Comma, values.ToList());
                openBrace.AddChild(seq);
            }

            openBrace.AddClosingDelimiter();
            id.AddChild(openBrace);

            return(openBracket);
        }
コード例 #2
0
        /// <summary>
        /// Generates a switch-case block with the specified clauses.
        /// </summary>
        /// <param name="condition">Optional condition expression.</param>
        /// <param name="cases">List of cases, must be at least one.</param>
        /// <param name="defaultAction">Optional default action.</param>
        /// <returns>The root node in this switch block AST.</returns>
        public static Node Generate(Node condition, IReadOnlyList <SwitchCase> cases, Node defaultAction)
        {
            if (cases == null || cases.Count == 0)
            {
                throw new ArgumentException(nameof(cases));
            }

            Switch switchStmt;

            if (condition != null)
            {
                switchStmt = new Switch(condition);
            }
            else
            {
                switchStmt = new Switch();
            }

            var openBrace = new OpenDelimiter(BinaryDelimiterType.Brace);

            foreach (var c in cases)
            {
                openBrace.AddChild(new Case(c.Predicate, c.Action));
                openBrace.AddChild(new Terminal());
            }

            if (defaultAction != null)
            {
                openBrace.AddChild(new Default(defaultAction));
            }

            openBrace.AddClosingDelimiter();
            switchStmt.AddChild(openBrace);
            return(switchStmt);
        }
コード例 #3
0
        /// <summary>
        /// Determines if this delimiter is part of a slice literal (e.g. []string{"foo"}).
        /// </summary>
        /// <param name="delimiter">The OpenDelimiter object to inspect.</param>
        /// <returns>True if this node is part of a slice literal.</returns>
        private bool IsStartOfSliceLiteral(OpenDelimiter delimiter)
        {
            if (delimiter.Type != BinaryDelimiterType.Brace)
            {
                return(false);
            }

            Node n     = delimiter.Parent;
            int  trips = 0;

            while (n != null)
            {
                if (n is Identifier)
                {
                    ++trips;
                }
                else if (n is CloseDelimiter && ((CloseDelimiter)n).Type == BinaryDelimiterType.Bracket)
                {
                    ++trips;
                }
                else if (n is OpenDelimiter && ((OpenDelimiter)n).Type == BinaryDelimiterType.Bracket)
                {
                    ++trips;
                }

                if (trips == 3)
                {
                    return(true);
                }

                n = n.Parent;
            }

            return(false);
        }
コード例 #4
0
        /// <summary>
        /// Generates a for block with the specified loop conditions and body.
        /// </summary>
        /// <param name="init">The optional init statement.</param>
        /// <param name="condition">The optional condition statement.</param>
        /// <param name="post">The optional post statement.</param>
        /// <param name="body">The body of the for loop.</param>
        /// <returns>The root node of the for block AST.</returns>
        public static Node Generate(Node init, Node condition, Node post, IReadOnlyList <Node> body)
        {
            if (init != null || condition != null || post != null)
            {
                throw new NotImplementedException("init, condition and post are NYI");
            }

            if (body == null || body.Count == 0)
            {
                throw new ArgumentException(nameof(body));
            }

            var forBlock = new For();

            var openBrace = new OpenDelimiter(BinaryDelimiterType.Brace);

            foreach (var node in body)
            {
                openBrace.AddChild(node);
            }
            openBrace.AddClosingDelimiter();
            forBlock.AddChild(openBrace);

            return(forBlock);
        }
コード例 #5
0
        /// <summary>
        /// Generates an if block with the specified condition and body.
        /// if condition {
        ///   ...body...
        /// }
        /// </summary>
        /// <param name="condition">The conditional of the if statement.</param>
        /// <param name="body">The body to execute if the condition is true.</param>
        /// <returns>The root node of the if block AST.</returns>
        public static Node Generate(Node condition, IReadOnlyList <Node> body)
        {
            if (condition == null)
            {
                throw new ArgumentNullException(nameof(condition));
            }

            if (body == null || body.Count == 0)
            {
                throw new ArgumentException(nameof(body));
            }

            var ifBlock = new If();

            ifBlock.AddChild(condition);

            var openBrace = new OpenDelimiter(BinaryDelimiterType.Brace);

            foreach (var node in body)
            {
                openBrace.AddChild(node);
            }
            openBrace.AddClosingDelimiter();
            ifBlock.AddChild(openBrace);

            return(ifBlock);
        }
コード例 #6
0
        /// <summary>
        /// Generates a function signature from the specified parameters.
        /// </summary>
        /// <param name="receiver">Optional signature for a receiver.</param>
        /// <param name="name">The name of the function.</param>
        /// <param name="parameters">Optional list of parameters.  Pass null if there are no parameters.</param>
        /// <param name="returns">Optional list of return values.  Pass null if there are no return values.</param>
        /// <returns>The root node in the function signature AST.</returns>
        public static Node Generate(FuncParamSig receiver, string name, IReadOnlyList <FuncParamSig> parameters, IReadOnlyList <FuncReturnSig> returns)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException(nameof(name));
            }

            var func = new Func();

            if (receiver != null)
            {
                var recvOpenParen = new OpenDelimiter(BinaryDelimiterType.Paren);
                recvOpenParen.AddChild(receiver);
                recvOpenParen.AddClosingDelimiter();
                func.AddChild(recvOpenParen);
            }

            func.AddChild(new Identifier(name));

            // build parameters
            var paramsStart = new OpenDelimiter(BinaryDelimiterType.Paren);

            if (parameters != null)
            {
                paramsStart.AddChild(DelimitedSequence.Generate(UnaryDelimiterType.Comma, parameters));
            }

            paramsStart.AddClosingDelimiter();
            func.AddChild(paramsStart);

            if (returns != null)
            {
                // multiple return values or a single return value
                // that has a name must be enclosed in parentheses
                if (returns.Count == 1)
                {
                    var ret = returns[0];
                    if (ret.IsNamed)
                    {
                        var returnOpenParen = new OpenDelimiter(BinaryDelimiterType.Paren);
                        returnOpenParen.AddChild(ret);
                        returnOpenParen.AddClosingDelimiter();
                        func.AddChild(returnOpenParen);
                    }
                    else
                    {
                        func.AddChild(ret);
                    }
                }
                else
                {
                    var returnOpenParen = new OpenDelimiter(BinaryDelimiterType.Paren);
                    returnOpenParen.AddChild(DelimitedSequence.Generate(UnaryDelimiterType.Comma, returns));
                    returnOpenParen.AddClosingDelimiter();
                    func.AddChild(returnOpenParen);
                }
            }

            return(func);
        }
コード例 #7
0
        /// <summary>
        /// Determines if this delimiter starts an empty braces sequence (e.g. {}).
        /// </summary>
        /// <param name="delimiter">The OpenDelimiter object to inspect.</param>
        /// <returns>True if this is node is empty braces.</returns>
        private bool IsEmptyBraces(OpenDelimiter delimiter)
        {
            if (delimiter.Type != BinaryDelimiterType.Brace)
            {
                return(false);
            }

            return(delimiter.Children[0] is CloseDelimiter);
        }
コード例 #8
0
        /// <summary>
        /// Generates a function call for the specified values.
        /// Example: package.Func(one, &two, three)
        /// </summary>
        /// <param name="name">The fully qualified name of the function to call.</param>
        /// <param name="parameters">The optional list of parameters.  Pass null if there are no parameters.</param>
        /// <returns>The root node for this function call AST.</returns>
        public static Node Generate(string name, IReadOnlyList <FuncCallParam> parameters)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException(nameof(name));
            }

            if (parameters != null && parameters.Count == 0)
            {
                throw new ArgumentException("pass null if there are no arguments");
            }

            var funcCall = new Identifier(name);

            var paramsStart = new OpenDelimiter(BinaryDelimiterType.Paren);

            funcCall.AddChild(paramsStart);

            if (parameters != null)
            {
                var seq = new Node[parameters.Count];

                // build a comma separated list of params
                for (int i = 0; i < parameters.Count; ++i)
                {
                    var param = parameters[i];

                    Node p = null;
                    if (param.Pass == TypeModifier.ByReference)
                    {
                        p = UnaryOpSequence.Generate(UnaryOperatorType.Ampersand, param.Param);
                    }
                    else if (param.Pass == TypeModifier.ByValue)
                    {
                        p = param.Param;
                    }

                    seq[i] = p;
                }

                paramsStart.AddChild(DelimitedSequence.Generate(UnaryDelimiterType.Comma, seq));
            }

            paramsStart.AddClosingDelimiter();

            return(funcCall);
        }
コード例 #9
0
ファイル: TypeConversion.cs プロジェクト: Azure/autorest.go
        /// <summary>
        /// Generates a type conversion sequence for the specified values.
        /// E.g. toTypeName(expression).
        /// </summary>
        /// <param name="expression">The expression to which the type conversion is applied.</param>
        /// <param name="toTypeName">The name of the type.</param>
        /// <returns>The root node in this type conversion AST.</returns>
        public static Node Generate(Node expression, string toTypeName)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }
            if (string.IsNullOrWhiteSpace(toTypeName))
            {
                throw new ArgumentException(nameof(toTypeName));
            }

            var typeName  = new TypeName(toTypeName);
            var openParen = new OpenDelimiter(BinaryDelimiterType.Paren);

            openParen.AddChild(expression);
            openParen.AddClosingDelimiter();
            typeName.AddChild(openParen);
            return(typeName);
        }
コード例 #10
0
ファイル: StructDefinition.cs プロジェクト: Azure/autorest.go
        /// <summary>
        /// Generates a struct definition with the specified name and fields.
        /// If the struct is to contain no fields pass null for the fields parameter.
        /// </summary>
        /// <param name="name">The name of the struct to be created.</param>
        /// <param name="fields">Optional list of fields.  Pass null if the struct has no fields.</param>
        /// <returns>Root node for this struct definition's AST.</returns>
        public static Node Generate(string name, IReadOnlyList <StructFieldDef> fields)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException(nameof(name));
            }

            if (fields != null && fields.Count == 0)
            {
                throw new ArgumentException("pass null for no struct fields");
            }

            var typeDef = new TypeDef();

            typeDef.AddChild(new Identifier(name));

            var structDef = new StructDef();
            var defStart  = new OpenDelimiter(BinaryDelimiterType.Brace);

            if (fields != null)
            {
                foreach (var field in fields)
                {
                    var id = new Identifier(field.Name);
                    id.AddChild(new TypeName(field.TypeName));

                    if (field.Tag != null)
                    {
                        id.AddChild(new Tag(field.Tag));
                    }

                    defStart.AddChild(id);
                }
            }

            defStart.AddClosingDelimiter();
            structDef.AddChild(defStart);

            typeDef.AddChild(structDef);
            return(typeDef);
        }
コード例 #11
0
        /// <summary>
        /// Determines if this delimiter is part of a control block.
        /// </summary>
        /// <param name="delimiter">The OpenDelimiter object to inspect.</param>
        /// <returns>True if this delimiter is part of a control block.</returns>
        private bool IsOpeningBraceInControlBlock(OpenDelimiter delimiter)
        {
            if (delimiter.Type != BinaryDelimiterType.Brace)
            {
                return(false);
            }

            Node n = delimiter.Parent;

            while (n != null)
            {
                if (n is If || n is For || n is Switch)
                {
                    return(true);
                }

                n = n.Parent;
            }

            return(false);
        }
コード例 #12
0
        public void Visit(OpenDelimiter delimiter)
        {
            // TODO: verify sequence ends with matching close delimiter, or if
            // this is a slice that the first child is a closing square bracket.

            switch (delimiter.Type)
            {
            case BinaryDelimiterType.Brace:
                if (_prev is CloseDelimiter || IsOpeningBraceInControlBlock(delimiter) || _prev is TypeName)
                {
                    _sb.Append(' ');
                }
                _sb.Append('{');
                if (!IsEmptyBraces(delimiter) && !IsStartOfSliceLiteral(delimiter))
                {
                    _sb.AppendLine();
                    ++_indentLevel;
                }
                break;

            case BinaryDelimiterType.Bracket:
                _sb.Append('[');
                break;

            case BinaryDelimiterType.Paren:
                _sb.Append('(');
                if (_prev is Import)
                {
                    _sb.AppendLine();
                    ++_indentLevel;
                }
                break;

            default:
                throw new InvalidOperationException($"unsupported open delimiter {delimiter.Type}");
            }

            _prev = delimiter;
        }
コード例 #13
0
ファイル: StructLiteral.cs プロジェクト: waqashaneef/autorest
        /// <summary>
        /// Generates a struct literal of the specified type name and optional field values.
        /// </summary>
        /// <param name="structTypeName">The fully qualified struct type name.</param>
        /// <param name="values">Optional field values.  Pass null to omit field initialization.</param>
        /// <returns>The root node in this struct literal AST.</returns>
        public static Node Generate(string structTypeName, IEnumerable <StructField> values)
        {
            if (string.IsNullOrWhiteSpace(structTypeName))
            {
                throw new ArgumentException(nameof(structTypeName));
            }

            if (values != null && !values.Any())
            {
                throw new ArgumentException("pass null to omit struct field initializers");
            }

            var id        = new Identifier(structTypeName);
            var openBrace = new OpenDelimiter(BinaryDelimiterType.Brace);

            if (values != null)
            {
                var initList = new List <Node>();
                foreach (var val in values)
                {
                    var root = DelimitedSequence.Generate(UnaryDelimiterType.Colon, new[]
                    {
                        new Identifier(val.FieldName),
                        val.Value
                    });

                    initList.Add(root);
                }

                var seqRoot = DelimitedSequence.Generate(UnaryDelimiterType.Comma, initList, true);
                openBrace.AddChild(seqRoot);
            }

            openBrace.AddClosingDelimiter();
            id.AddChild(openBrace);

            return(id);
        }
コード例 #14
0
ファイル: TestGenGoRpc.cs プロジェクト: Azure/autorest.go
        private static Node GetRegisterServer(string typeName)
        {
            var logParamName = "log";

            var func = FunctionSignature.Generate(null, "RegisterServer", new[]
            {
                new FuncParamSig(logParamName, TypeModifier.ByReference, "log.Logger")
            }, null);
            var funcBody = new OpenDelimiter(BinaryDelimiterType.Brace);

            funcBody.AddChild(BinaryOpSequence.Generate(BinaryOperatorType.Assignment, new Identifier(LoggerVarName), new Identifier(logParamName)));
            funcBody.AddChild(new Terminal());

            funcBody.AddChild(FunctionCall.Generate("rpc.Register", new[]
            {
                new FuncCallParam(StructLiteral.Generate(typeName, null), TypeModifier.ByReference)
            }));

            funcBody.AddClosingDelimiter();
            func.AddChild(funcBody);

            return(func);
        }
コード例 #15
0
        /// <summary>
        /// Generates a test case function for the specified method.
        /// </summary>
        /// <param name="mg">The method for which a test case will be generated.</param>
        /// <param name="rpcTypeName">The type name use for RPC dispatch.</param>
        /// <returns>The root node in this test case function AST.</returns>
        public static Tuple <Node, string> Generate(MethodGo mg, string rpcTypeName, string replyTypeName, string replyConvFuncName, string loggerVarName)
        {
            if (mg == null)
            {
                throw new ArgumentNullException(nameof(mg));
            }

            if (string.IsNullOrWhiteSpace(replyTypeName))
            {
                throw new ArgumentException(nameof(replyTypeName));
            }

            if (string.IsNullOrWhiteSpace(replyConvFuncName))
            {
                throw new ArgumentException(nameof(replyConvFuncName));
            }

            var errorVar     = "err";
            var jsonParamVar = "parameters";
            var replyVar     = "reply";

            var operationId = mg.SerializedName.ToString();

            if (!char.IsUpper(operationId[0]))
            {
                operationId = $"{char.ToUpperInvariant(operationId[0])}{operationId.Substring(1)}";
            }

            var rpcTypeVar = char.ToLowerInvariant(rpcTypeName[0]).ToString();

            var func = FunctionSignature.Generate(new FuncParamSig(rpcTypeVar, TypeModifier.ByReference, rpcTypeName),
                                                  operationId, new[]
            {
                new FuncParamSig(jsonParamVar, TypeModifier.ByValue, "json.RawMessage"),
                new FuncParamSig(replyVar, TypeModifier.ByReference, replyTypeName)
            }, new[]
            {
                new FuncReturnSig(null, TypeModifier.ByValue, "error")
            });

            var funcBody = new OpenDelimiter(BinaryDelimiterType.Brace);

            // generate a type used to unmarshal the parameters
            string unmarshalVar  = null;
            var    unmarshalType = GenerateTypeForParamsUnmarshal(mg);

            funcBody.AddChild(unmarshalType.Item1);
            funcBody.AddChild(new Terminal());

            unmarshalVar = unmarshalType.Item2.ToLowerInvariant();

            // do the unmarshaling and return on failure
            funcBody.AddChild(VariableDecl.Generate(unmarshalVar, unmarshalType.Item2));
            funcBody.AddChild(new Terminal());

            funcBody.AddChild(BinaryOpSequence.Generate(BinaryOperatorType.DeclareAndAssign, new Identifier(errorVar),
                                                        FunctionCall.Generate("json.Unmarshal", new[]
            {
                new FuncCallParam(new Identifier(jsonParamVar), TypeModifier.ByValue),
                new FuncCallParam(new Identifier(unmarshalVar), TypeModifier.ByReference)
            })));
            funcBody.AddChild(new Terminal());

            funcBody.AddChild(ErrorCheck.Generate(errorVar, OnError.ReturnError));
            funcBody.AddChild(new Terminal());

            var authVar = "auth";

            funcBody.AddChild(BinaryOpSequence.Generate(BinaryOperatorType.DeclareAndAssign,
                                                        DelimitedSequence.Generate(UnaryDelimiterType.Comma, new[]
            {
                new Identifier(authVar),
                new Identifier(errorVar)
            }),
                                                        FunctionCall.Generate($"{unmarshalVar}.{ReservedParamsFieldName}.Credentials.CreateBearerAuthorizer", null)));
            funcBody.AddChild(new Terminal());

            funcBody.AddChild(ErrorCheck.Generate(errorVar, OnError.ReturnError));
            funcBody.AddChild(new Terminal());

            // create the client and call the target function
            var clientVar = "client";

            // check if the client ctor has any parameters
            List <FuncCallParam> clientParams = null;

            if (!string.IsNullOrWhiteSpace(((MethodGroupGo)mg.MethodGroup).GlobalParameters))
            {
                clientParams = new List <FuncCallParam>();
                var globalParams = ((MethodGroupGo)mg.MethodGroup).GlobalParameters.Split(new[] { ',' });

                // each param is the var name followed by the type name, e.g. "subscriptionID string"
                foreach (var globalParam in globalParams)
                {
                    var paramName = globalParam.Substring(0, globalParam.IndexOf(' '));
                    clientParams.Add(new FuncCallParam(new Identifier($"{unmarshalVar}.{paramName.Capitalize()}"), TypeModifier.ByValue));
                }
            }

            funcBody.AddChild(FunctionCall.Generate($"{loggerVarName}.Println", new[]
            {
                new FuncCallParam(new Literal <string>(operationId), TypeModifier.ByValue)
            }));
            funcBody.AddChild(new Terminal());

            funcBody.AddChild(FunctionCall.Generate($"{loggerVarName}.Printf", new[]
            {
                new FuncCallParam(new Literal <string>("received %v\\n"), TypeModifier.ByValue),
                new FuncCallParam(new Identifier(unmarshalVar), TypeModifier.ByValue)
            }));
            funcBody.AddChild(new Terminal());

            // the client creation function name prefix is hard-coded in the Go generator
            var clientCtorName = $"{mg.CodeModel.Namespace}.New";

            if (!string.IsNullOrWhiteSpace(mg.MethodGroup.Name))
            {
                clientCtorName = $"{clientCtorName}{((MethodGroupGo)mg.MethodGroup).ClientName}";
            }

            funcBody.AddChild(BinaryOpSequence.Generate(
                                  BinaryOperatorType.DeclareAndAssign,
                                  new Identifier(clientVar),
                                  FunctionCall.Generate(clientCtorName, clientParams)));
            funcBody.AddChild(new Terminal());

            funcBody.AddChild(BinaryOpSequence.Generate(BinaryOperatorType.Assignment,
                                                        new Identifier($"{clientVar}.Authorizer"), new Identifier(authVar)));
            funcBody.AddChild(new Terminal());

            var rChanVar       = "rChan";
            var eChanVar       = "eChan";
            var responseVar    = "resp";
            var rawResponseVar = "rawResp";

            var isLro = mg.IsLongRunningOperation() && !mg.IsPageable;

            funcBody.AddChild(BinaryOpSequence.Generate(BinaryOperatorType.DeclareAndAssign,
                                                        DelimitedSequence.Generate(UnaryDelimiterType.Comma, new[]
            {
                new Identifier(isLro ? rChanVar : responseVar),
                new Identifier(isLro ? eChanVar : errorVar)
            }),
                                                        FunctionCall.Generate($"{clientVar}.{mg.Name}", GenerateApiCallParams(mg, unmarshalVar))));
            funcBody.AddChild(new Terminal());

            if (isLro)
            {
                funcBody.AddChild(BinaryOpSequence.Generate(BinaryOperatorType.Assignment,
                                                            new Identifier(errorVar), new Identifier($"<-{eChanVar}")));
                funcBody.AddChild(new Terminal());
            }

            funcBody.AddChild(ErrorCheck.Generate(errorVar, OnError.ReturnError));
            funcBody.AddChild(new Terminal());

            if (isLro)
            {
                funcBody.AddChild(BinaryOpSequence.Generate(BinaryOperatorType.DeclareAndAssign,
                                                            new Identifier(responseVar), new Identifier($"<-{rChanVar}")));
                funcBody.AddChild(new Terminal());
            }

            funcBody.AddChild(BinaryOpSequence.Generate(BinaryOperatorType.DeclareAndAssign,
                                                        DelimitedSequence.Generate(UnaryDelimiterType.Comma, new[]
            {
                new Identifier(rawResponseVar),
                new Identifier(errorVar)
            }),
                                                        FunctionCall.Generate(replyConvFuncName, new[]
            {
                new FuncCallParam(new Identifier(mg.HasReturnValue() ? $"{responseVar}.Response" : $"{responseVar}"), TypeModifier.ByReference),
                new FuncCallParam(mg.HasReturnValue() ? (Node) new Identifier(responseVar) : new Nil(), TypeModifier.ByValue)
            })));
            funcBody.AddChild(new Terminal());

            funcBody.AddChild(FunctionCall.Generate($"{loggerVarName}.Printf", new[]
            {
                new FuncCallParam(new Literal <string>("response %v\\n"), TypeModifier.ByValue),
                new FuncCallParam(new Identifier($"*{rawResponseVar}"), TypeModifier.ByValue)
            }));
            funcBody.AddChild(new Terminal());

            funcBody.AddChild(BinaryOpSequence.Generate(BinaryOperatorType.Assignment,
                                                        new Identifier($"*{replyVar}"), new Identifier($"*{rawResponseVar}")));
            funcBody.AddChild(new Terminal());

            funcBody.AddChild(ReturnStatement.Generate(new[]
            {
                errorVar
            }));

            funcBody.AddClosingDelimiter();
            func.AddChild(funcBody);
            return(new Tuple <Node, string>(func, operationId));
        }