Skip to content

Commit a90304d

Browse files
authored
Merge branch 'main' into repo-assist/fix-issue-1632-dtd-processing-parameter-b6794c39a31ef477
2 parents 81fa7d7 + 483317f commit a90304d

18 files changed

Lines changed: 495 additions & 186 deletions

File tree

.github/aw/actions-lock.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@
2929
"repo": "github/gh-aw/actions/setup",
3030
"version": "v0.49.7",
3131
"sha": "0ea0cf123dda697de607a0cd6e3315746680eb86"
32+
},
33+
"github/gh-aw/actions/setup@v0.50.0": {
34+
"repo": "github/gh-aw/actions/setup",
35+
"version": "v0.50.0",
36+
"sha": "8624e99d3979177875f082b4959b14da951d9ffe"
37+
},
38+
"github/gh-aw/actions/setup@v0.50.1": {
39+
"repo": "github/gh-aw/actions/setup",
40+
"version": "v0.50.1",
41+
"sha": "fad43e3c91a4e1d43e458f68e96574127934e7d1"
3242
}
3343
}
3444
}

.github/workflows/repo-assist.lock.yml

Lines changed: 150 additions & 138 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/repo-assist.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ tools:
7474
bash: true
7575
repo-memory: true
7676

77-
source: githubnext/agentics/workflows/repo-assist.md@b0e9cfd3a20372ce7fe0462bb7bbca2272df4a88
77+
source: githubnext/agentics/workflows/repo-assist.md@b87234850bf9664d198f28a02df0f937d0447295
7878
---
7979

8080
# Repo Assist

docs/library/CsvProvider.fsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,9 +475,21 @@ transformed the dataset to be smaller.
475475
*)
476476

477477
(**
478+
## Using CSV provider in a library
479+
480+
When using `CsvProvider` in a library that others will reference, the sample file must be
481+
embedded in the compiled assembly. See the step-by-step guide in
482+
[Using JSON provider in a library](JsonProvider.html#jsonlib) — the same `EmbeddedResource`
483+
parameter and naming convention applies to `CsvProvider`.
484+
485+
In brief, for a file `data/sample.csv` in a library `MyLib`:
486+
1. Mark the file as `<EmbeddedResource>` in the `.fsproj`
487+
2. Use `EmbeddedResource="MyLib, MyLib.data.sample.csv"` in the type provider declaration
488+
478489
## Related articles
479490
480-
* [Using JSON provider in a library](JsonProvider.html#jsonlib) also applies to CSV type provider
491+
* [Using JSON provider in a library](JsonProvider.html#jsonlib) — includes step-by-step
492+
`EmbeddedResource` guide that applies to all type providers
481493
* [CSV Parser](CsvFile.html) - provides more information about
482494
working with CSV documents dynamically.
483495
* [API Reference: CsvProvider type provider](../reference/fsharp-data-csvprovider.html)

docs/library/JsonProvider.fsx

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,26 @@ access the sample JSON. This works fine when the sample is specified inline, but
462462
the sample is specified as a local file (unless you distribute the samples with your library).
463463
464464
For this reason, the JSON provider lets you specify samples as embedded resources using the
465-
static parameter `EmbeddedResource` (don't forget then to [include the file](https://docs.microsoft.com/en-us/visualstudio/ide/build-actions) as EmbeddedResource in the
466-
project file). If you are building a library `MyLib.dll`, you can write:
465+
static parameter `EmbeddedResource`. When this parameter is set, the type provider at design time
466+
reads the sample from the local path, but at runtime (when the library is loaded by a consumer)
467+
it reads the sample from the embedded resource in the compiled assembly.
468+
469+
### Step-by-step guide
470+
471+
**Step 1**: Mark your sample file as an embedded resource in the `.fsproj` file:
472+
473+
```xml
474+
<ItemGroup>
475+
<EmbeddedResource Include="data/worldbank.json" />
476+
</ItemGroup>
477+
```
478+
479+
**Step 2**: Use the `EmbeddedResource` static parameter. The value must be
480+
`"AssemblyName, AssemblyName.dotted.path.to.file.json"` where:
481+
- `AssemblyName` is the name of your library assembly (without `.dll`)
482+
- The file path uses **dots** (not slashes) as separators, prefixed with `AssemblyName`
483+
484+
So for a file `data/worldbank.json` in a library `MyLib`, the value is:
467485
468486
*)
469487
type WB =
@@ -480,6 +498,14 @@ to load `MyLib.dll` and locate the sample `worldbank.json` as a resource of the
480498
this succeeds, it does not attempt to find the local file and so your library can be used
481499
without providing a local copy of the sample JSON files.
482500
501+
> **Common pitfall**: If you get a cryptic error where the type provider interprets the file path
502+
> as the CSV/JSON content itself (resulting in a single-column type named after the path), you
503+
> have likely forgotten to add the `EmbeddedResource` parameter, or the assembly name or resource
504+
> path in the parameter value is incorrect.
505+
>
506+
> To verify the embedded resource name, you can inspect the compiled `.dll` using a tool such as
507+
> `ildasm`, `dotnet-ildasm`, or ILSpy and look at the `.mresource` entries.
508+
483509
## Related articles
484510
485511
* [JSON Parser](JsonValue.html) - provides more information about

src/FSharp.Data.DesignTime/Csv/CsvGenerator.fs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,19 @@ module internal CsvTypeBuilder =
2727
ProvidedParameter: ProvidedParameter
2828
}
2929

30-
let generateTypes asm ns typeName (missingValuesStr, cultureStr) inferredFields =
30+
let generateTypes asm ns typeName (missingValuesStr, cultureStr) useOriginalNames inferredFields =
3131

3232
let fields =
3333
inferredFields
3434
|> List.mapi (fun index field ->
3535
let typ, typWithoutMeasure, conv, convBack =
3636
ConversionsGenerator.convertStringValue missingValuesStr cultureStr field
3737

38-
let propertyName = NameUtils.capitalizeFirstLetter field.Name
38+
let propertyName =
39+
if useOriginalNames then
40+
field.Name
41+
else
42+
NameUtils.capitalizeFirstLetter field.Name
3943

4044
let prop =
4145
ProvidedProperty(
@@ -58,11 +62,17 @@ module internal CsvTypeBuilder =
5862
| _ -> Expr.TupleGet(rowVarExpr, index)
5963
)
6064

65+
let paramName =
66+
if useOriginalNames then
67+
field.Name
68+
else
69+
NameUtils.niceCamelName propertyName
70+
6171
{ TypeForTuple = typWithoutMeasure
6272
ProvidedProperty = prop
6373
Convert = convert
6474
ConvertBack = convertBack
65-
ProvidedParameter = ProvidedParameter(NameUtils.niceCamelName propertyName, typ) })
75+
ProvidedParameter = ProvidedParameter(paramName, typ) })
6676

6777
// The erased row type will be a tuple of all the field types (without the units of measure). If there is a single column then it is just the column type.
6878
let rowErasedType =

src/FSharp.Data.DesignTime/Csv/CsvProvider.fs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type public CsvProvider(cfg: TypeProviderConfig) as this =
5757
let resource = args.[15] :?> string
5858
let preferDateOnly = args.[16] :?> bool
5959
let strictBooleans = args.[17] :?> bool
60+
let useOriginalNames = args.[18] :?> bool
6061

6162
// This provider already has a schema mechanism, so let's disable inline schemas.
6263
let inferenceMode = InferenceMode'.ValuesOnly
@@ -130,7 +131,7 @@ type public CsvProvider(cfg: TypeProviderConfig) as this =
130131

131132
let csvType, csvErasedType, rowType, stringArrayToRow, rowToStringArray =
132133
inferredFields
133-
|> CsvTypeBuilder.generateTypes asm ns typeName (missingValuesStr, cultureStr)
134+
|> CsvTypeBuilder.generateTypes asm ns typeName (missingValuesStr, cultureStr) useOriginalNames
134135

135136
let stringArrayToRowVar = Var("stringArrayToRow", stringArrayToRow.Type)
136137
let rowToStringArrayVar = Var("rowToStringArray", rowToStringArray.Type)
@@ -239,7 +240,8 @@ type public CsvProvider(cfg: TypeProviderConfig) as this =
239240
ProvidedStaticParameter("ResolutionFolder", typeof<string>, parameterDefaultValue = "")
240241
ProvidedStaticParameter("EmbeddedResource", typeof<string>, parameterDefaultValue = "")
241242
ProvidedStaticParameter("PreferDateOnly", typeof<bool>, parameterDefaultValue = false)
242-
ProvidedStaticParameter("StrictBooleans", typeof<bool>, parameterDefaultValue = false) ]
243+
ProvidedStaticParameter("StrictBooleans", typeof<bool>, parameterDefaultValue = false)
244+
ProvidedStaticParameter("UseOriginalNames", typeof<bool>, parameterDefaultValue = false) ]
243245

244246
let helpText =
245247
"""<summary>Typed representation of a CSV file.</summary>
@@ -264,7 +266,8 @@ type public CsvProvider(cfg: TypeProviderConfig) as this =
264266
<param name='EmbeddedResource'>When specified, the type provider first attempts to load the sample from the specified resource
265267
(e.g. 'MyCompany.MyAssembly, resource_name.csv'). This is useful when exposing types generated by the type provider.</param>
266268
<param name='PreferDateOnly'>When true on .NET 6+, date-only strings are inferred as DateOnly and time-only strings as TimeOnly. Defaults to false for backward compatibility.</param>
267-
<param name='StrictBooleans'>When true, only <c>true</c> and <c>false</c> (case-insensitive) are inferred as boolean. Values such as <c>0</c>, <c>1</c>, <c>yes</c>, and <c>no</c> are treated as integers or strings respectively. Defaults to false.</param>"""
269+
<param name='StrictBooleans'>When true, only <c>true</c> and <c>false</c> (case-insensitive) are inferred as boolean. Values such as <c>0</c>, <c>1</c>, <c>yes</c>, and <c>no</c> are treated as integers or strings respectively. Defaults to false.</param>
270+
<param name='UseOriginalNames'>When true, CSV column header names are used as-is for generated property names instead of being normalized (e.g. capitalizing the first letter). Defaults to false.</param>"""
268271

269272
do csvProvTy.AddXmlDoc helpText
270273
do csvProvTy.DefineStaticParameters(parameters, buildTypes)

src/FSharp.Data.DesignTime/Json/JsonGenerator.fs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,26 @@ type internal JsonGenerationContext =
3030
PreferDictionaries: bool
3131
GenerateConstructors: bool
3232
InferenceMode: InferenceMode'
33-
UnitsOfMeasureProvider: IUnitsOfMeasureProvider }
33+
UnitsOfMeasureProvider: IUnitsOfMeasureProvider
34+
UseOriginalNames: bool }
3435

3536
static member Create
36-
(cultureStr, tpType, unitsOfMeasureProvider, inferenceMode, ?uniqueNiceName, ?typeCache, ?preferDictionaries)
37-
=
37+
(
38+
cultureStr,
39+
tpType,
40+
unitsOfMeasureProvider,
41+
inferenceMode,
42+
?uniqueNiceName,
43+
?typeCache,
44+
?preferDictionaries,
45+
?useOriginalNames
46+
) =
47+
let useOriginalNames = defaultArg useOriginalNames false
48+
3849
let uniqueNiceName =
39-
defaultArg uniqueNiceName (NameUtils.uniqueGenerator NameUtils.nicePascalName)
50+
defaultArg
51+
uniqueNiceName
52+
(NameUtils.uniqueGenerator (if useOriginalNames then id else NameUtils.nicePascalName))
4053

4154
let typeCache = defaultArg typeCache (Dictionary())
4255
let preferDictionaries = defaultArg preferDictionaries false
@@ -49,7 +62,8 @@ type internal JsonGenerationContext =
4962
preferDictionaries,
5063
true,
5164
inferenceMode,
52-
unitsOfMeasureProvider
65+
unitsOfMeasureProvider,
66+
useOriginalNames
5367
)
5468

5569
static member Create
@@ -61,7 +75,8 @@ type internal JsonGenerationContext =
6175
preferDictionaries,
6276
generateConstructors,
6377
inferenceMode,
64-
unitsOfMeasureProvider
78+
unitsOfMeasureProvider,
79+
useOriginalNames
6580
) =
6681
{ CultureStr = cultureStr
6782
TypeProviderType = tpType
@@ -73,7 +88,8 @@ type internal JsonGenerationContext =
7388
PreferDictionaries = preferDictionaries
7489
GenerateConstructors = generateConstructors
7590
InferenceMode = inferenceMode
76-
UnitsOfMeasureProvider = unitsOfMeasureProvider }
91+
UnitsOfMeasureProvider = unitsOfMeasureProvider
92+
UseOriginalNames = useOriginalNames }
7793

7894
member x.MakeOptionType(typ: Type) =
7995
typedefof<option<_>>.MakeGenericType typ
@@ -376,7 +392,13 @@ module JsonTypeBuilder =
376392
ctx.TypeProviderType.AddMember(objectTy)
377393

378394
// to nameclash property names
379-
let makeUnique = NameUtils.uniqueGenerator NameUtils.nicePascalName
395+
let nicePropertyName =
396+
if ctx.UseOriginalNames then
397+
id
398+
else
399+
NameUtils.nicePascalName
400+
401+
let makeUnique = NameUtils.uniqueGenerator nicePropertyName
380402
makeUnique "JsonValue" |> ignore
381403

382404
let inferedKeyValueType =
@@ -600,7 +622,13 @@ module JsonTypeBuilder =
600622

601623
prop.Name,
602624
[ ProvidedProperty(name, convertedType, getterCode = getter) ],
603-
ProvidedParameter(NameUtils.niceCamelName name, replaceJDocWithJValue ctx convertedType) ]
625+
ProvidedParameter(
626+
(if ctx.UseOriginalNames then
627+
name
628+
else
629+
NameUtils.niceCamelName name),
630+
replaceJDocWithJValue ctx convertedType
631+
) ]
604632

605633
let names, properties, parameters = List.unzip3 members
606634
let properties = properties |> List.concat

src/FSharp.Data.DesignTime/Json/JsonProvider.fs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
5858
let inferenceMode = args.[9] :?> InferenceMode
5959
let schema = args.[10] :?> string
6060
let preferDateOnly = args.[11] :?> bool
61+
let useOriginalNames = args.[12] :?> bool
6162

6263
let inferenceMode =
6364
InferenceMode'.FromPublicApi(inferenceMode, inferTypesFromValues)
@@ -117,7 +118,8 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
117118
tpType,
118119
unitsOfMeasureProvider,
119120
inferenceMode,
120-
?preferDictionaries = Some preferDictionaries
121+
?preferDictionaries = Some preferDictionaries,
122+
?useOriginalNames = Some useOriginalNames
121123
)
122124

123125
let result = JsonTypeBuilder.generateJsonType ctx false false rootName inferedType
@@ -164,7 +166,8 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
164166
parameterDefaultValue = InferenceMode.BackwardCompatible
165167
)
166168
ProvidedStaticParameter("Schema", typeof<string>, parameterDefaultValue = "")
167-
ProvidedStaticParameter("PreferDateOnly", typeof<bool>, parameterDefaultValue = false) ]
169+
ProvidedStaticParameter("PreferDateOnly", typeof<bool>, parameterDefaultValue = false)
170+
ProvidedStaticParameter("UseOriginalNames", typeof<bool>, parameterDefaultValue = false) ]
168171

169172
let helpText =
170173
"""<summary>Typed representation of a JSON document.</summary>
@@ -188,7 +191,8 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
188191
| ValuesAndInlineSchemasOverrides -> Same as ValuesAndInlineSchemasHints, but value inferred types are ignored when an inline schema is present.
189192
</param>
190193
<param name='Schema'>Location of a JSON Schema file or a string containing a JSON Schema document. When specified, Sample and SampleIsList must not be used.</param>
191-
<param name='PreferDateOnly'>When true on .NET 6+, date-only strings (e.g. "2023-01-15") are inferred as DateOnly and time-only strings as TimeOnly. Defaults to false for backward compatibility.</param>"""
194+
<param name='PreferDateOnly'>When true on .NET 6+, date-only strings (e.g. "2023-01-15") are inferred as DateOnly and time-only strings as TimeOnly. Defaults to false for backward compatibility.</param>
195+
<param name='UseOriginalNames'>When true, JSON property names are used as-is for generated property names instead of being normalized to PascalCase. Defaults to false.</param>"""
192196

193197
do jsonProvTy.AddXmlDoc helpText
194198
do jsonProvTy.DefineStaticParameters(parameters, buildTypes)

0 commit comments

Comments
 (0)