首页 > 解决方案 > 使用 F# 编译器服务解析计算表达式

问题描述

我开发了一个 F# REST 服务框架,该框架最近已投入生产使用,我正在开发的后续工具之一是自动OpenAPI规范生成器。生成器使用FSharp.Compiler.Services库来检查作为服务入口点公开的每个函数并生成 API 规范,包括每个参数的模式。这些参数通常是单例联合类型,它们使用特殊的rules计算表达式来定义验证规则,如下所示:

type AccoutNubmerValidationError =
| AccountNumberMustBeTenDigitsLong of string
| AccountNumberMustBeNumerical of string

/// Account Number must be a 10-digit numerical string
[<Struct; Validated>] type AccoutNumber = private AccountNumber of string

module AccountNumber = 
    let create : string -> Result<AccountNumber, AccountNumberValidationError> =
        rules {
            rule (Rules.length 10) AccountNumberBeTenDigitsLong
            rule (Rules.pattern "^[\d]{10}$") AccountNumberMustBeNumerical
        }

我想解析rule计算表达式中的每一个(这是类CustomOperation上的a ) ,RulesBuilder这样我就可以在 OpenApi 架构上为. 虽然我可以识别正确的绑定并且我有主体,但我还没有弄清楚我需要做什么来解析该表达式并提取每个规则的值。 lengthpatternAccountNumberFSharpExpr

如果有任何关于如何使用 F# Compiler Services 解析计算表达式主体的文档,我还没有找到它。有没有人可以分享任何经验来帮助我解决这个问题?

编辑

我收到了“要求教程”的密切投票,所以我想澄清我的问题。在上面的示例中,我有一个FSharpMemberOrFunctionOrValue用于create绑定的实例,以及一个FSharpExpr用于表达式主体的实例。表达式看起来像这样(表示为 JSON 以使其可读):

        {
          "Type": "FSharpImplementationFileDeclaration.MemberOrFunctionOrValue",
          "Range": {
            "StartLine": 15,
            "StartCol": 4,
            "EndLine": 15,
            "EndCol": 9
          },
          "Properties": [
            [
              "v",
              "val create"
            ],
            [
              "vs",
              []
            ]
          ],
          "Childs": [
            {
              "Type": "BasicPatterns.Application",
              "Range": {
                "StartLine": 15,
                "StartCol": 4,
                "EndLine": 15,
                "EndCol": 9
              },
              "Properties": [],
              "Childs": [
                {
                  "Type": "BasicPatterns.Lambda",
                  "Range": {
                    "StartLine": 15,
                    "StartCol": 4,
                    "EndLine": 15,
                    "EndCol": 9
                  },
                  "Properties": [
                    [
                      "lambdaVar",
                      "val builder@"
                    ]
                  ],
                  "Childs": [
                    {
                      "Type": "BasicPatterns.Call",
                      "Range": {
                        "StartLine": 17,
                        "StartCol": 8,
                        "EndLine": 17,
                        "EndCol": 64
                      },
                      "Properties": [
                        [
                          "memberOrFunc",
                          "member Require"
                        ],
                        [
                          "typeArg2",
                          "type Microsoft.FSharp.Core.string"
                        ]
                      ],
                      "Childs": [
                        {
                          "Type": "BasicPatterns.Value",
                          "Range": {
                            "StartLine": 17,
                            "StartCol": 8,
                            "EndLine": 17,
                            "EndCol": 64
                          },
                          "Properties": [
                            [
                              "valueToGet",
                              "val builder@"
                            ]
                          ],
                          "Childs": []
                        },
                        {
                          "Type": "BasicPatterns.Call",
                          "Range": {
                            "StartLine": 16,
                            "StartCol": 8,
                            "EndLine": 16,
                            "EndCol": 63
                          },
                          "Properties": [
                            [
                              "memberOrFunc",
                              "member Require"
                            ],
                            [
                              "typeArg2",
                              "type Microsoft.FSharp.Core.string"
                            ]
                          ],
                          "Childs": [
                            {
                              "Type": "BasicPatterns.Value",
                              "Range": {
                                "StartLine": 16,
                                "StartCol": 8,
                                "EndLine": 16,
                                "EndCol": 63
                              },
                              "Properties": [
                                [
                                  "valueToGet",
                                  "val builder@"
                                ]
                              ],
                              "Childs": []
                            },
                            {
                              "Type": "BasicPatterns.Call",
                              "Range": {
                                "StartLine": 16,
                                "StartCol": 8,
                                "EndLine": 16,
                                "EndCol": 63
                              },
                              "Properties": [
                                [
                                  "memberOrFunc",
                                  "member Yield"
                                ],
                                [
                                  "typeArg2",
                                  "type Microsoft.FSharp.Core.obj * Microsoft.FSharp.Core.string"
                                ]
                              ],
                              "Childs": [
                                {
                                  "Type": "BasicPatterns.Value",
                                  "Range": {
                                    "StartLine": 16,
                                    "StartCol": 8,
                                    "EndLine": 16,
                                    "EndCol": 63
                                  },
                                  "Properties": [
                                    [
                                      "valueToGet",
                                      "val builder@"
                                    ]
                                  ],
                                  "Childs": []
                                },
                                {
                                  "Type": "BasicPatterns.Const",
                                  "Range": {
                                    "StartLine": 16,
                                    "StartCol": 8,
                                    "EndLine": 16,
                                    "EndCol": 63
                                  },
                                  "Properties": [
                                    [
                                      "constType",
                                      "type Microsoft.FSharp.Core.unit"
                                    ],
                                    [
                                      "constValueObj",
                                      null
                                    ]
                                  ],
                                  "Childs": []
                                }
                              ]
                            },
                            {
                              "Type": "BasicPatterns.Call",
                              "Range": {
                                "StartLine": 16,
                                "StartCol": 17,
                                "EndLine": 16,
                                "EndCol": 32
                              },
                              "Properties": [
                                [
                                  "memberOrFunc",
                                  "val raise"
                                ],
                                [
                                  "typeArg2",
                                  "type Microsoft.FSharp.Core.obj"
                                ]
                              ],
                              "Childs": [
                                {
                                  "Type": "BasicPatterns.Const",
                                  "Range": {
                                    "StartLine": 16,
                                    "StartCol": 17,
                                    "EndLine": 16,
                                    "EndCol": 32
                                  },
                                  "Properties": [
                                    [
                                      "constType",
                                      "type Microsoft.FSharp.Core.int32"
                                    ],
                                    [
                                      "constValueObj",
                                      1
                                    ]
                                  ],
                                  "Childs": []
                                }
                              ]
                            },
                            {
                              "Type": "BasicPatterns.Const",
                              "Range": {
                                "StartLine": 16,
                                "StartCol": 34,
                                "EndLine": 16,
                                "EndCol": 63
                              },
                              "Properties": [
                                [
                                  "constType",
                                  "type Microsoft.FSharp.Core.string"
                                ],
                                [
                                  "constValueObj",
                                  "Must be 10 digits in length"
                                ]
                              ],
                              "Childs": []
                            }
                          ]
                        },
                        {
                          "Type": "BasicPatterns.Call",
                          "Range": {
                            "StartLine": 17,
                            "StartCol": 17,
                            "EndLine": 17,
                            "EndCol": 43
                          },
                          "Properties": [
                            [
                              "memberOrFunc",
                              "val raise"
                            ],
                            [
                              "typeArg2",
                              "type Microsoft.FSharp.Core.obj"
                            ]
                          ],
                          "Childs": [
                            {
                              "Type": "BasicPatterns.Const",
                              "Range": {
                                "StartLine": 17,
                                "StartCol": 17,
                                "EndLine": 17,
                                "EndCol": 43
                              },
                              "Properties": [
                                [
                                  "constType",
                                  "type Microsoft.FSharp.Core.int32"
                                ],
                                [
                                  "constValueObj",
                                  1
                                ]
                              ],
                              "Childs": []
                            }
                          ]
                        },
                        {
                          "Type": "BasicPatterns.Const",
                          "Range": {
                            "StartLine": 17,
                            "StartCol": 45,
                            "EndLine": 17,
                            "EndCol": 64
                          },
                          "Properties": [
                            [
                              "constType",
                              "type Microsoft.FSharp.Core.string"
                            ],
                            [
                              "constValueObj",
                              "Must be numerical"
                            ]
                          ],
                          "Childs": []
                        }
                      ]
                    }
                  ]
                },
                {
                  "Type": "BasicPatterns.Call",
                  "Range": {
                    "StartLine": 15,
                    "StartCol": 4,
                    "EndLine": 15,
                    "EndCol": 9
                  },
                  "Properties": [
                    [
                      "memberOrFunc",
                      "val rules"
                    ]
                  ],
                  "Childs": []
                }
              ]
            }
          ]
        }

问题是,我什至没有看到对这个表达式树的Rules.length引用Rules.pattern。据推测,这一定是因为我正在创建一些中间部分应用的函数,该函数在程序的表达式树的其他地方表示。是否有确定的方法来确定我需要导航的表达式树的哪些部分,然后找到部分应用的函数中使用的实际常量值,以便我可以可靠地以编程方式使用它们?

标签: f#computation-expressionf#-compiler-services

解决方案


推荐阅读