예제 #1
0
        public override void ExitMethodDecl(GolangParser.MethodDeclContext context)
        {
            bool signatureOnly = false;

            if (!Parameters.TryGetValue(context.receiver()?.parameters(), out List <ParameterInfo> receiverParameters) || (object)receiverParameters == null)
            {
                receiverParameters = new List <ParameterInfo>();
            }

            if (Parameters.TryGetValue(context.signature()?.parameters(), out List <ParameterInfo> functionParameters) && (object)functionParameters != null)
            {
                signatureOnly = true;
            }
            else if (!Parameters.TryGetValue(context.function()?.signature()?.parameters(), out functionParameters) || (object)functionParameters == null)
            {
                functionParameters = new List <ParameterInfo>();
            }

            IEnumerable <ParameterInfo> parameters = receiverParameters.Concat(functionParameters);

            string functionSignature = FunctionSignature.Generate(m_originalFunctionName, parameters);

            if (!Metadata.Functions.TryGetValue(functionSignature, out m_currentFunction))
            {
                throw new InvalidOperationException($"Failed to find metadata for method function \"{functionSignature}\".");
            }

            MethodSignature method = m_currentFunction.Signature as MethodSignature;

            if ((object)method == null)
            {
                throw new InvalidOperationException($"Failed to find signature metadata for method function \"{m_currentFunctionName}\".");
            }

            bool      hasDefer   = m_currentFunction.HasDefer;
            bool      hasPanic   = m_currentFunction.HasPanic;
            bool      hasRecover = m_currentFunction.HasRecover;
            bool      useFuncExecutionContext = hasDefer || hasPanic || hasRecover;
            Signature signature = method.Signature;
            string    receiverParametersSignature = method.GenerateReceiverParametersSignature(useFuncExecutionContext);
            string    parametersSignature         = signature.GenerateParametersSignature(useFuncExecutionContext);
            string    resultSignature             = signature.GenerateResultSignature();

            if (signature.Parameters.Length == 0)
            {
                parametersSignature = $"({receiverParametersSignature})";
            }
            else
            {
                parametersSignature = $"({receiverParametersSignature}, {parametersSignature})";
            }

            // Scope of an extension function is based on scope of the receiver type
            string scope = char.IsUpper(method.ReceiverParameters[0].Type.TypeName[0]) ? "public" : "private";

            resultSignature = $"{scope} static {resultSignature}";

            // Replace function markers
            m_targetFile.Replace(m_functionResultTypeMarker, resultSignature);
            m_targetFile.Replace(m_functionParametersMarker, parametersSignature);

            if (useFuncExecutionContext)
            {
                List <string> funcExecContextByRefParams = new List <string>(method.GetByRefReceiverParameters(false));

                funcExecContextByRefParams.AddRange(signature.GetByRefParameters(false));

                if (funcExecContextByRefParams.Count > 0)
                {
                    List <string> lambdaByRefParameters = new List <string>(method.GetByRefReceiverParameters(true));

                    lambdaByRefParameters.AddRange(signature.GetByRefParameters(true));

                    m_targetFile.Replace(m_functionExecContextMarker, $" => func({string.Join(", ", funcExecContextByRefParams)}, ({string.Join(", ", lambdaByRefParameters)}, Defer {(hasDefer ? "defer" : "_")}, Panic {(hasPanic ? "panic" : "_")}, Recover {(hasRecover ? "recover" : "_")}) =>");
                }
                else
                {
                    m_targetFile.Replace(m_functionExecContextMarker, $" => func(({(hasDefer ? "defer" : "_")}, {(hasPanic ? "panic" : "_")}, {(hasRecover ? "recover" : "_")}) =>");
                }
            }
            else
            {
                m_targetFile.Replace(m_functionExecContextMarker, "");
            }

            m_currentFunction      = null;
            m_currentFunctionName  = null;
            m_originalFunctionName = null;
            m_inFunction           = false;

            if (useFuncExecutionContext)
            {
                m_targetFile.Append(");");
            }
            else if (signatureOnly)
            {
                m_targetFile.Append(";");
            }

            m_targetFile.Append(CheckForCommentsRight(context));
        }