fsprojects / FSharp.TypeProviders.SDK

The SDK for creating F# type providers
https://fsprojects.github.io/FSharp.TypeProviders.SDK/
MIT License
298 stars 94 forks source link

Limitation: single optional static parameter in type provider #232

Open francotiveron opened 6 years ago

francotiveron commented 6 years ago

Description

Two known limitation exists when a type provider has a single optional parameter.

  1. The optional parameter can not be omitted completely

  2. The optional parameter can not have an actual value that is identical to the default value

As a result, type provider authors should avoid type providers with a single optional parameter

Description (original)

I have a very basic type provider with one static parameter:

module Typro
open ProviderImplementation.ProvidedTypes
open FSharp.Core.CompilerServices
open System.Reflection

type Server (name : string) =
    member x.Name with get() : string = name

[<TypeProvider>]
type TypeProvider(config : TypeProviderConfig) as this = 
    inherit TypeProviderForNamespaces(config)

    let ns = "Ocnarf.TypeProviders.Pi"
    let asm = Assembly.GetExecutingAssembly()

    let provider = ProvidedTypeDefinition(asm, ns, "Provider", Some typeof<obj>, hideObjectMethods = true)
    do provider.DefineStaticParameters([ProvidedStaticParameter("Host", typeof<string>, "")], fun name args ->
        let provided = 
            let srv = args.[0] :?> string
            let prop = ProvidedProperty("Server", typeof<Server>, (fun _ -> <@@ Server(srv) @@>), isStatic = true)
            let provided = ProvidedTypeDefinition(asm, ns, name, Some typeof<obj>, hideObjectMethods = true)
            provided.AddMember prop
            provided

        provided
    )

    do this.AddNamespace(ns, [provider])

[<assembly:CompilerServices.TypeProviderAssembly()>]
do ()

And a using code in a different project

module File1
open Ocnarf.TypeProviders.Pi

type pi = Provider<"ABCD">

let name = pi.Server.Name

Repro steps

I find two different issues

1. Static parameter = "" (empty string)

module File1
open Ocnarf.TypeProviders.Pi

type pi = Provider<"">

let name = pi.Server.Name //FS0039: The field, constructor or member 'Server' is not defined

2. Static parameter unspecified

Having specified the default value for the static parameter, I expect I can call the type provider without it. To corroborate this expectancy, the intellisense tooltip (Visual Studio 2017) coming up on the < character shows

type pi = Provider<
                   {Provider<[?Host:string]>}

Nevertheless, the declaration is not accepted, as follows

module File1
open Ocnarf.TypeProviders.Pi

type pi = Provider<> //FS0010   Unexpected infix operator in member definition
dsyme commented 6 years ago

@francotiveron These are limtations with the type provider support in F# tooling. I need to dig in to it a bit more, but I've adjusted your report to now clarify that the recommendation is to avoid authoriung type providers with a single optional static parameter.