Skip to content

Commit 1d6d26b

Browse files
authored
Merge pull request #1 from Zaid-Ajaj/master
Update fork
2 parents d105d7d + 1ca2fd7 commit 1d6d26b

File tree

18 files changed

+387
-111
lines changed

18 files changed

+387
-111
lines changed

README.md

+31-1
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ Analyzer that provides embedded **SQL syntax analysis** when writing queries usi
1616
- Free (MIT licensed)
1717
- Supports VS Code with [Ionide](https://github.com/ionide/ionide-vscode-fsharp) via F# Analyzers SDK
1818
- Supports Visual Studio
19+
- Supports CLI (via Ubik)
1920

2021
## NuGet
2122

2223
| Package | Stable | Prerelease |
2324
| -------------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
2425
| NpgsqlFSharpAnalyzer | [![NuGet Badge](https://buildstats.info/nuget/NpgsqlFSharpAnalyzer)](https://www.nuget.org/packages/NpgsqlFSharpAnalyzer/) | [![NuGet Badge](https://buildstats.info/nuget/NpgsqlFSharpAnalyzer?includePreReleases=true)](https://www.nuget.org/packages/NpgsqlFSharpAnalyzer/) |
25-
26+
| Ubik | [![NuGet Badge](https://buildstats.info/nuget/Ubik)](https://www.nuget.org/packages/Ubik/) | [![NuGet Badge](https://buildstats.info/nuget/Ubik?includePreReleases=true)](https://www.nuget.org/packages/Ubik/) |
2627

2728
## Using The Analyzer (Visual Studio)
2829

@@ -73,6 +74,35 @@ Make sure you have these settings in Ionide for FSharp
7374
```
7475
Which instructs Ionide to load the analyzers from the directory of the analyzers into which `NpgsqlFSharpAnalyzer` was installed.
7576

77+
# Using CLI with Ubik
78+
79+
### 1 - Configure the connection string to your development database
80+
The analyzer requires a connection string that points to the database you are developing against. You can configure this connection string by either creating a file called `NPGSQL_FSHARP` (without extension) somewhere next to your F# project or preferably in the root of your workspace. This file should contain that connection string and nothing else. An example of the contents of such file:
81+
```
82+
Host=localhost; Username=postgres; Password=postgres; Database=databaseName
83+
```
84+
> Remember to add an entry in your .gitingore file to make sure you don't commit the connection string to your source version control system.
85+
86+
Another way to configure the connection string is by setting the value of an environment variable named `NPGSQL_FSHARP` that contains the connection string.
87+
88+
The analyzer will try to locate and read the file first, then falls back to using the environment variable.
89+
90+
### 2 - Install Ubik as a dotnet CLI tool
91+
```
92+
dotnet tool install ubik --global
93+
```
94+
### 3 - Run Ubik in the directory of the project you want to analyze
95+
```bash
96+
cd ./path/to/project
97+
ubik
98+
99+
ubik ./path/to/Project.fsproj
100+
101+
ubik ./File1.fs ./AnotherFile.fs
102+
103+
ubik --version
104+
```
105+
76106
### Writing Long Multi-line Queries
77107

78108
When it is not convenient to write a query inline like this:

RELEASE_NOTES.md

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
### 3.18.0 - 2020-09-15
1+
### 3.20.0 - 2020-12-08
2+
* Correctly retain selected column non-nullability when casted or aliased to another type
3+
4+
### 3.18.0 - 2020-12-06
25
* Analyze SQL blocks from within lambda expressions
36

4-
### 3.17.0 - 2020-09-15
7+
### 3.17.0 - 2020-12-06
58
* Support for datetimeOffset and datetimeOffsetOrNone when reading columns of type timestamptz
69

7-
### 3.16.0 - 2020-09-15
10+
### 3.16.0 - 2020-12-06
811
* Analyze top level do expressions
912

1013
### 3.15.0 - 2020-09-15

build.fsx

+20
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,21 @@ let publishToNuget _ =
315315
if exitCode <> 0
316316
then failwith "Could not publish package"
317317

318+
let packUbik _ =
319+
Shell.cleanDir (__SOURCE_DIRECTORY__ </> "dist")
320+
let args =
321+
[
322+
"pack"
323+
"--configuration Release"
324+
sprintf "--output %s" (__SOURCE_DIRECTORY__ </> "dist")
325+
]
326+
327+
let exitCode = Shell.Exec("dotnet", String.concat " " args, "src" </> "Ubik")
328+
if exitCode <> 0
329+
then failwith "dotnet pack failed"
330+
331+
Target.create "PackUbik" packUbik
332+
Target.create "PublishUbik" publishToNuget
318333

319334
//-----------------------------------------------------------------------------
320335
// Target Declaration
@@ -352,6 +367,11 @@ Target.create "PackNoTests" dotnetPack
352367
==> "PublishToNuGet"
353368
==> "Release"
354369

370+
"DotnetBuild"
371+
==> "DotnetTest"
372+
==> "PackUbik"
373+
==> "PublishUbik"
374+
355375
"DotnetRestore"
356376
==> "WatchTests"
357377

src/FParsec/AssemblyInfo.fs

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ open System.Reflection
44

55
[<assembly: AssemblyTitleAttribute("FParsec")>]
66
[<assembly: AssemblyProductAttribute("NpgsqlFSharpAnalyzer")>]
7-
[<assembly: AssemblyVersionAttribute("3.18.0")>]
8-
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-09-15T00:00:00.0000000")>]
9-
[<assembly: AssemblyFileVersionAttribute("3.18.0")>]
10-
[<assembly: AssemblyInformationalVersionAttribute("3.18.0")>]
7+
[<assembly: AssemblyVersionAttribute("3.20.0")>]
8+
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-12-08T00:00:00.0000000")>]
9+
[<assembly: AssemblyFileVersionAttribute("3.20.0")>]
10+
[<assembly: AssemblyInformationalVersionAttribute("3.20.0")>]
1111
[<assembly: AssemblyMetadataAttribute("ReleaseChannel","release")>]
12-
[<assembly: AssemblyMetadataAttribute("GitHash","8d5412fe3dd28abc45fb45a7d97134d09ec1ce82")>]
12+
[<assembly: AssemblyMetadataAttribute("GitHash","e06231910314439545a22bad74899e40a4c2e458")>]
1313
do ()
1414

1515
module internal AssemblyVersionInformation =
1616
let [<Literal>] AssemblyTitle = "FParsec"
1717
let [<Literal>] AssemblyProduct = "NpgsqlFSharpAnalyzer"
18-
let [<Literal>] AssemblyVersion = "3.18.0"
19-
let [<Literal>] AssemblyMetadata_ReleaseDate = "2020-09-15T00:00:00.0000000"
20-
let [<Literal>] AssemblyFileVersion = "3.18.0"
21-
let [<Literal>] AssemblyInformationalVersion = "3.18.0"
18+
let [<Literal>] AssemblyVersion = "3.20.0"
19+
let [<Literal>] AssemblyMetadata_ReleaseDate = "2020-12-08T00:00:00.0000000"
20+
let [<Literal>] AssemblyFileVersion = "3.20.0"
21+
let [<Literal>] AssemblyInformationalVersion = "3.20.0"
2222
let [<Literal>] AssemblyMetadata_ReleaseChannel = "release"
23-
let [<Literal>] AssemblyMetadata_GitHash = "8d5412fe3dd28abc45fb45a7d97134d09ec1ce82"
23+
let [<Literal>] AssemblyMetadata_GitHash = "e06231910314439545a22bad74899e40a4c2e458"

src/NpgsqlFSharpAnalyzer.Core/AssemblyInfo.fs

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ open System.Reflection
44

55
[<assembly: AssemblyTitleAttribute("NpgsqlFSharpAnalyzer.Core")>]
66
[<assembly: AssemblyProductAttribute("NpgsqlFSharpAnalyzer")>]
7-
[<assembly: AssemblyVersionAttribute("3.18.0")>]
8-
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-09-15T00:00:00.0000000")>]
9-
[<assembly: AssemblyFileVersionAttribute("3.18.0")>]
10-
[<assembly: AssemblyInformationalVersionAttribute("3.18.0")>]
7+
[<assembly: AssemblyVersionAttribute("3.20.0")>]
8+
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-12-08T00:00:00.0000000")>]
9+
[<assembly: AssemblyFileVersionAttribute("3.20.0")>]
10+
[<assembly: AssemblyInformationalVersionAttribute("3.20.0")>]
1111
[<assembly: AssemblyMetadataAttribute("ReleaseChannel","release")>]
12-
[<assembly: AssemblyMetadataAttribute("GitHash","8d5412fe3dd28abc45fb45a7d97134d09ec1ce82")>]
12+
[<assembly: AssemblyMetadataAttribute("GitHash","e06231910314439545a22bad74899e40a4c2e458")>]
1313
do ()
1414

1515
module internal AssemblyVersionInformation =
1616
let [<Literal>] AssemblyTitle = "NpgsqlFSharpAnalyzer.Core"
1717
let [<Literal>] AssemblyProduct = "NpgsqlFSharpAnalyzer"
18-
let [<Literal>] AssemblyVersion = "3.18.0"
19-
let [<Literal>] AssemblyMetadata_ReleaseDate = "2020-09-15T00:00:00.0000000"
20-
let [<Literal>] AssemblyFileVersion = "3.18.0"
21-
let [<Literal>] AssemblyInformationalVersion = "3.18.0"
18+
let [<Literal>] AssemblyVersion = "3.20.0"
19+
let [<Literal>] AssemblyMetadata_ReleaseDate = "2020-12-08T00:00:00.0000000"
20+
let [<Literal>] AssemblyFileVersion = "3.20.0"
21+
let [<Literal>] AssemblyInformationalVersion = "3.20.0"
2222
let [<Literal>] AssemblyMetadata_ReleaseChannel = "release"
23-
let [<Literal>] AssemblyMetadata_GitHash = "8d5412fe3dd28abc45fb45a7d97134d09ec1ce82"
23+
let [<Literal>] AssemblyMetadata_GitHash = "e06231910314439545a22bad74899e40a4c2e458"

src/NpgsqlFSharpAnalyzer.Core/SqlAnalysis.fs

+67-1
Original file line numberDiff line numberDiff line change
@@ -343,12 +343,78 @@ module SqlAnalysis =
343343
| _ ->
344344
None
345345

346+
// When casting columns during a select statement, if the original column is non-nullable
347+
// then the computed column somehow becomes nullable when we ask the database for its type
348+
// for example
349+
// user_id int not null -> inferred non-nullable
350+
// user_id::text -> inferred nullable
351+
//
352+
// This function resolves the correct nullability and infers non-nullable columns to be returned as such
353+
let resolveColumnNullability (commandText: string) (schema: DbSchemaLookups) (columns: Column list) =
354+
match Parser.parse commandText with
355+
| Result.Ok (Expr.SelectQuery selectQuery) ->
356+
let schemaColumns =
357+
schema.Columns
358+
|> Seq.map (fun pair -> pair.Value)
359+
|> Seq.toList
360+
361+
columns
362+
|> List.map (fun column ->
363+
let originalColumnNameAndAlias =
364+
selectQuery.Columns
365+
|> List.tryPick (function
366+
// find columns expressions of the shape
367+
// {originalName}::{typeName} AS {alias}
368+
| Expr.As(Expr.TypeCast(Expr.Ident originalName, Expr.Ident typeName), Expr.Ident alias) ->
369+
Some (originalName, alias, false)
370+
// 1::{typeName} AS {alias}
371+
| Expr.As(Expr.TypeCast(Expr.Integer _, Expr.Ident typeName), Expr.Ident alias) ->
372+
Some (column.Name, column.Name, true)
373+
// {originalName}::{typeName}
374+
| Expr.TypeCast(Expr.Ident originalName, Expr.Ident typeName) ->
375+
Some (originalName, originalName, false)
376+
// 1::{typeName}
377+
| Expr.TypeCast(Expr.Integer _, Expr.Ident typeName) ->
378+
Some (column.Name, column.Name, true)
379+
// "text"::{typeName}
380+
| Expr.TypeCast(Expr.StringLiteral _, Expr.Ident typeName) ->
381+
Some (column.Name, column.Name, true)
382+
// 1 as {alias}
383+
| Expr.As(Expr.Integer _, Expr.Ident alias) ->
384+
Some (alias, alias, true)
385+
// "text" AS alias
386+
| Expr.As(Expr.StringLiteral _, Expr.Ident alias) ->
387+
Some (alias, alias, true)
388+
| _ ->
389+
None
390+
)
391+
392+
match originalColumnNameAndAlias with
393+
| None -> column
394+
| Some (name, alias, isConst) when isConst-> { column with Nullable = false }
395+
| Some (name, alias, isConst) ->
396+
schemaColumns
397+
|> List.tryFind (fun columnSchema -> columnSchema.Name = name && alias = column.Name)
398+
|> function
399+
| None -> column
400+
| Some columnSchema ->
401+
{ column with
402+
Nullable = columnSchema.Nullable
403+
DefaultConstraint = columnSchema.DefaultConstraint
404+
PartOfPrimaryKey = columnSchema.PartOfPrimaryKey
405+
BaseTableName = column.BaseTableName
406+
BaseSchemaName = column.BaseSchemaName }
407+
)
408+
| _ ->
409+
columns
410+
346411
let extractParametersAndOutputColumns(connectionString, commandText, dbSchemaLookups) =
347412
try
348413
let parameters, output, enums = InformationSchema.extractParametersAndOutputColumns(connectionString, commandText, false, dbSchemaLookups)
349414
let parametersWithNullability = determineParameterNullability parameters dbSchemaLookups commandText
350415
let potentiallyMissingColumns = missingInsertColumns dbSchemaLookups commandText
351-
Result.Ok (parametersWithNullability, output, potentiallyMissingColumns)
416+
let rewrittenColumns = resolveColumnNullability commandText dbSchemaLookups output
417+
Result.Ok (parametersWithNullability, rewrittenColumns, potentiallyMissingColumns)
352418
with
353419
| :? PostgresException as databaseError ->
354420
// errors such as syntax errors are reported here

src/NpgsqlFSharpAnalyzer/AssemblyInfo.fs

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ open System.Reflection
44

55
[<assembly: AssemblyTitleAttribute("NpgsqlFSharpAnalyzer")>]
66
[<assembly: AssemblyProductAttribute("NpgsqlFSharpAnalyzer")>]
7-
[<assembly: AssemblyVersionAttribute("3.18.0")>]
8-
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-09-15T00:00:00.0000000")>]
9-
[<assembly: AssemblyFileVersionAttribute("3.18.0")>]
10-
[<assembly: AssemblyInformationalVersionAttribute("3.18.0")>]
7+
[<assembly: AssemblyVersionAttribute("3.20.0")>]
8+
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-12-08T00:00:00.0000000")>]
9+
[<assembly: AssemblyFileVersionAttribute("3.20.0")>]
10+
[<assembly: AssemblyInformationalVersionAttribute("3.20.0")>]
1111
[<assembly: AssemblyMetadataAttribute("ReleaseChannel","release")>]
12-
[<assembly: AssemblyMetadataAttribute("GitHash","8d5412fe3dd28abc45fb45a7d97134d09ec1ce82")>]
12+
[<assembly: AssemblyMetadataAttribute("GitHash","e06231910314439545a22bad74899e40a4c2e458")>]
1313
do ()
1414

1515
module internal AssemblyVersionInformation =
1616
let [<Literal>] AssemblyTitle = "NpgsqlFSharpAnalyzer"
1717
let [<Literal>] AssemblyProduct = "NpgsqlFSharpAnalyzer"
18-
let [<Literal>] AssemblyVersion = "3.18.0"
19-
let [<Literal>] AssemblyMetadata_ReleaseDate = "2020-09-15T00:00:00.0000000"
20-
let [<Literal>] AssemblyFileVersion = "3.18.0"
21-
let [<Literal>] AssemblyInformationalVersion = "3.18.0"
18+
let [<Literal>] AssemblyVersion = "3.20.0"
19+
let [<Literal>] AssemblyMetadata_ReleaseDate = "2020-12-08T00:00:00.0000000"
20+
let [<Literal>] AssemblyFileVersion = "3.20.0"
21+
let [<Literal>] AssemblyInformationalVersion = "3.20.0"
2222
let [<Literal>] AssemblyMetadata_ReleaseChannel = "release"
23-
let [<Literal>] AssemblyMetadata_GitHash = "8d5412fe3dd28abc45fb45a7d97134d09ec1ce82"
23+
let [<Literal>] AssemblyMetadata_GitHash = "e06231910314439545a22bad74899e40a4c2e458"

src/NpgsqlFSharpParser/AssemblyInfo.fs

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ open System.Reflection
44

55
[<assembly: AssemblyTitleAttribute("NpgsqlFSharpParser")>]
66
[<assembly: AssemblyProductAttribute("NpgsqlFSharpAnalyzer")>]
7-
[<assembly: AssemblyVersionAttribute("3.18.0")>]
8-
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-09-15T00:00:00.0000000")>]
9-
[<assembly: AssemblyFileVersionAttribute("3.18.0")>]
10-
[<assembly: AssemblyInformationalVersionAttribute("3.18.0")>]
7+
[<assembly: AssemblyVersionAttribute("3.20.0")>]
8+
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-12-08T00:00:00.0000000")>]
9+
[<assembly: AssemblyFileVersionAttribute("3.20.0")>]
10+
[<assembly: AssemblyInformationalVersionAttribute("3.20.0")>]
1111
[<assembly: AssemblyMetadataAttribute("ReleaseChannel","release")>]
12-
[<assembly: AssemblyMetadataAttribute("GitHash","8d5412fe3dd28abc45fb45a7d97134d09ec1ce82")>]
12+
[<assembly: AssemblyMetadataAttribute("GitHash","e06231910314439545a22bad74899e40a4c2e458")>]
1313
do ()
1414

1515
module internal AssemblyVersionInformation =
1616
let [<Literal>] AssemblyTitle = "NpgsqlFSharpParser"
1717
let [<Literal>] AssemblyProduct = "NpgsqlFSharpAnalyzer"
18-
let [<Literal>] AssemblyVersion = "3.18.0"
19-
let [<Literal>] AssemblyMetadata_ReleaseDate = "2020-09-15T00:00:00.0000000"
20-
let [<Literal>] AssemblyFileVersion = "3.18.0"
21-
let [<Literal>] AssemblyInformationalVersion = "3.18.0"
18+
let [<Literal>] AssemblyVersion = "3.20.0"
19+
let [<Literal>] AssemblyMetadata_ReleaseDate = "2020-12-08T00:00:00.0000000"
20+
let [<Literal>] AssemblyFileVersion = "3.20.0"
21+
let [<Literal>] AssemblyInformationalVersion = "3.20.0"
2222
let [<Literal>] AssemblyMetadata_ReleaseChannel = "release"
23-
let [<Literal>] AssemblyMetadata_GitHash = "8d5412fe3dd28abc45fb45a7d97134d09ec1ce82"
23+
let [<Literal>] AssemblyMetadata_GitHash = "e06231910314439545a22bad74899e40a4c2e458"

src/NpgsqlFSharpParser/Parser.fs

+1
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ let updateQuery =
255255

256256
opp.AddOperator(InfixOperator("AND", spaces, 7, Associativity.Left, fun left right -> Expr.And(left, right)))
257257
opp.AddOperator(InfixOperator("AS", spaces, 6, Associativity.Left, fun left right -> Expr.As(left, right)))
258+
opp.AddOperator(InfixOperator("as", spaces, 6, Associativity.Left, fun left right -> Expr.As(left, right)))
258259
opp.AddOperator(InfixOperator("OR", notFollowedBy (text "DER BY"), 6, Associativity.Left, fun left right -> Expr.Or(left, right)))
259260
opp.AddOperator(InfixOperator("IN", spaces, 8, Associativity.Left, fun left right -> Expr.In(left, right)))
260261
opp.AddOperator(InfixOperator(">", spaces, 9, Associativity.Left, fun left right -> Expr.GreaterThan(left, right)))

src/NpgsqlFSharpVs/source.extension.vsixmanifest

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011"
44
xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
55
<Metadata>
6-
<Identity Id="FSharpLintVs.ef00bfc3-a899-45fc-aae8-afecf8673aaf" Version="3.18.0" Language="en-US" Publisher="Zaid Ajaj" />
6+
<Identity Id="FSharpLintVs.ef00bfc3-a899-45fc-aae8-afecf8673aaf" Version="3.20.0" Language="en-US" Publisher="Zaid Ajaj" />
77
<DisplayName>NpgsqlFSharpVs</DisplayName>
88
<Description xml:space="preserve">F# Analyzer for embedded SQL syntax analysis, type-checking for parameters and result sets and nullable column detection when writing queries using Npgsql.FSharp.</Description>
99
<MoreInfo>https://github.com/Zaid-Ajaj/Npgsql.FSharp.Analyzer</MoreInfo>

src/Ubik/AssemblyInfo.fs

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ open System.Reflection
44

55
[<assembly: AssemblyTitleAttribute("Ubik")>]
66
[<assembly: AssemblyProductAttribute("NpgsqlFSharpAnalyzer")>]
7-
[<assembly: AssemblyVersionAttribute("3.18.0")>]
8-
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-09-15T00:00:00.0000000")>]
9-
[<assembly: AssemblyFileVersionAttribute("3.18.0")>]
10-
[<assembly: AssemblyInformationalVersionAttribute("3.18.0")>]
7+
[<assembly: AssemblyVersionAttribute("3.20.0")>]
8+
[<assembly: AssemblyMetadataAttribute("ReleaseDate","2020-12-08T00:00:00.0000000")>]
9+
[<assembly: AssemblyFileVersionAttribute("3.20.0")>]
10+
[<assembly: AssemblyInformationalVersionAttribute("3.20.0")>]
1111
[<assembly: AssemblyMetadataAttribute("ReleaseChannel","release")>]
12-
[<assembly: AssemblyMetadataAttribute("GitHash","8d5412fe3dd28abc45fb45a7d97134d09ec1ce82")>]
12+
[<assembly: AssemblyMetadataAttribute("GitHash","e06231910314439545a22bad74899e40a4c2e458")>]
1313
do ()
1414

1515
module internal AssemblyVersionInformation =
1616
let [<Literal>] AssemblyTitle = "Ubik"
1717
let [<Literal>] AssemblyProduct = "NpgsqlFSharpAnalyzer"
18-
let [<Literal>] AssemblyVersion = "3.18.0"
19-
let [<Literal>] AssemblyMetadata_ReleaseDate = "2020-09-15T00:00:00.0000000"
20-
let [<Literal>] AssemblyFileVersion = "3.18.0"
21-
let [<Literal>] AssemblyInformationalVersion = "3.18.0"
18+
let [<Literal>] AssemblyVersion = "3.20.0"
19+
let [<Literal>] AssemblyMetadata_ReleaseDate = "2020-12-08T00:00:00.0000000"
20+
let [<Literal>] AssemblyFileVersion = "3.20.0"
21+
let [<Literal>] AssemblyInformationalVersion = "3.20.0"
2222
let [<Literal>] AssemblyMetadata_ReleaseChannel = "release"
23-
let [<Literal>] AssemblyMetadata_GitHash = "8d5412fe3dd28abc45fb45a7d97134d09ec1ce82"
23+
let [<Literal>] AssemblyMetadata_GitHash = "e06231910314439545a22bad74899e40a4c2e458"

0 commit comments

Comments
 (0)