Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/fsharp/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1307,3 +1307,5 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS
3201,tcModuleAbbrevFirstInMutRec,"In a recursive declaration group, module abbreviations must come after all 'open' declarations and before other declarations"
3202,tcUnsupportedMutRecDecl,"This declaration is not supported in recursive declaration groups"
3203,parsInvalidUseOfRec,"Invalid use of 'rec' keyword"
3204,expressionHasNoName,"This expression does not have a name."
3205,nameofNotPermitted,"The nameof operator is not allowed in this position."
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
<None Include="FSharp.Core\Microsoft.FSharp.Core\IntConversionsTestGenerator.fsx" />
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\OptionModule.fs" />
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\PrintfTests.fs" />
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\NameOfTests.fs" />
<Compile Include="FSharp.Core\Microsoft.FSharp.Control\Cancellation.fs" />
<Compile Include="FSharp.Core\Microsoft.FSharp.Control\AsyncType.fs" />
<Compile Include="FSharp.Core\Microsoft.FSharp.Control\LazyType.fs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace FSharp.Core.Unittests
open System
open NUnit.Framework

[<TestFixture>]
type BasicNameOfTests() =
let localConstant = 23
member this.MemberMethod() = 0
member this.MemberProperty = this.MemberMethod()
static member StaticMethod() = 0
static member StaticProperty = BasicNameOfTests.StaticMethod()

[<Test>]
member this.``local variable name lookup`` () =
let a = 0
let result = nameof a
Assert.AreEqual("a",result)
Assert.AreEqual("result",nameof result)

[<Test>]
member this.``local int function name`` () =
let myFunction x = 0 * x
let b = nameof myFunction
Assert.AreEqual("myFunction",b)

[<Test>]
member this.``local curried function name`` () =
let curriedFunction x y = x * y
let b = nameof curriedFunction
Assert.AreEqual("curriedFunction",b)

[<Test>]
member this.``local tupled function name`` () =
let tupledFunction(x,y) = x * y
let b = nameof tupledFunction
Assert.AreEqual("tupledFunction",b)

[<Test>]
member this.``local unit function name`` () =
let myFunction() = 1
let b = nameof(myFunction)
Assert.AreEqual("myFunction",b)

[<Test>]
member this.``local function parameter name`` () =
let myFunction parameter1 = nameof parameter1

Assert.AreEqual("parameter1",myFunction "x")

[<Test>]
member this.``can get name from inside a local function (needs to be let rec)`` () =
let rec myLocalFunction x =
let z = 2 * x
nameof myLocalFunction + " " + z.ToString()

Assert.AreEqual("myLocalFunction 46",myLocalFunction 23)
Assert.AreEqual("myLocalFunction 50",myLocalFunction 25)

[<Test>]
member this.CanGetNameFromInsideAMember () =
let b = nameof(this.CanGetNameFromInsideAMember)
Assert.AreEqual("CanGetNameFromInsideAMember",b)

[<Test>]
member this.``member function name`` () =
let b = nameof(this.MemberMethod)
Assert.AreEqual("MemberMethod",b)

[<Test>]
member this.``member function which is defined below`` () =
let b = nameof(this.MemberMethodDefinedBelow)
Assert.AreEqual("MemberMethodDefinedBelow",b)

member this.MemberMethodDefinedBelow(x,y) = x * y

[<Test>]
member this.``static member function name`` () =
let b = nameof(BasicNameOfTests.StaticMethod)
Assert.AreEqual("StaticMethod",b)

[<Test>]
member this.``class member lookup`` () =
let b = nameof(localConstant)
Assert.AreEqual("localConstant",b)

[<Test>]
member this.``member property name`` () =
let b = nameof(this.MemberProperty)
Assert.AreEqual("MemberProperty",b)

[<Test>]
member this.``static property name`` () =
let b = nameof(BasicNameOfTests.StaticProperty)
Assert.AreEqual("StaticProperty",b)

member this.get_XYZ() = 1

[<Test>]
member this.``member method starting with get_`` () =
let b = nameof(this.get_XYZ)
Assert.AreEqual("get_XYZ",b)

static member get_SXYZ() = 1

[<Test>]
member this.``static method starting with get_`` () =
let b = nameof(BasicNameOfTests.get_SXYZ)
Assert.AreEqual("get_SXYZ",b)

[<Test>]
member this.``nameof local property with encapsulated name`` () =
let ``local property with encapsulated name and %.f`` = 0
let b = nameof(``local property with encapsulated name and %.f``)
Assert.AreEqual("local property with encapsulated name and %.f",b)

[<TestFixture>]
type MethodGroupTests() =
member this.MethodGroup() = ()
member this.MethodGroup(i:int) = ()

[<Test>]
member this.``method group name lookup`` () =
let b = nameof(this.MethodGroup)
Assert.AreEqual("MethodGroup",b)

[<TestFixture>]
type FrameworkMethodTests() =
[<Test>]
member this.``library function name`` () =
let b = nameof(List.map)
Assert.AreEqual("Map",b)

[<Test>]
member this.``static class function name`` () =
let b = nameof(Tuple.Create)
Assert.AreEqual("Create",b)

type CustomUnionType =
| OptionA of string
| OptionB of int * string

[<TestFixture>]
type NameOfOperatorForTypes() =
[<Test>]
member this.``use typenameof on Int32`` () =
let b = typenameof<System.Int32>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you update the RFC to include details of typenameof please? Thanks! https://github.com/fsharp/FSharpLangDesign/blob/master/RFCs/FS-1003-nameof-operator.md

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good then I leave it for you ;-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious, why do we need a separate construct for types? What are the advantages?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tbh: it's because I couldn't fix syntax ambiguity if we have nameof
On Feb 5, 2016 12:43, "Max Malook" [email protected] wrote:

In
src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Core/NameOfTests.fs
#908 (comment):

  •    Assert.AreEqual("Map",b)
    
  • []
  • member this.static class function name () =
  •    let b = nameof(Tuple.Create)
    
  •    Assert.AreEqual("Create",b)
    
    +type CustomUnionType =
    +| OptionA of string
    +| OptionB of int * string
    +
    +[]
    +type NameOfOperatorForTypes() =
  • []
  • member this.use typenameof on Int32 () =
  •    let b = typenameof<System.Int32>
    

I'm curious, why do we need a separate construct for types? What are the
advantages?


Reply to this email directly or view it on GitHub
https://github.com/Microsoft/visualfsharp/pull/908/files#r52006423.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate more on the problem, maybe with a concrete example?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just take a look at the signatures.

nameof:: 'a -> string

typenameof<'a>:: string (is that how we write that?)
On Feb 5, 2016 12:49, "Max Malook" [email protected] wrote:

In
src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Core/NameOfTests.fs
#908 (comment):

  •    Assert.AreEqual("Map",b)
    
  • []
  • member this.static class function name () =
  •    let b = nameof(Tuple.Create)
    
  •    Assert.AreEqual("Create",b)
    
    +type CustomUnionType =
    +| OptionA of string
    +| OptionB of int * string
    +
    +[]
    +type NameOfOperatorForTypes() =
  • []
  • member this.use typenameof on Int32 () =
  •    let b = typenameof<System.Int32>
    

Can you elaborate more on the problem, maybe with a concrete example?


Reply to this email directly or view it on GitHub
https://github.com/Microsoft/visualfsharp/pull/908/files#r52006913.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for my understanding this functionality is only a compile time construct, it don't need to have any signature at all. It's more like a macro to me. Why not simply write nameof(System.Int32)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also write nameof(typeof<System.Int32>). The nameof operator can than look at the expression provided. By this even nameof(typedefof<IList<_>>) would work.

Assert.AreEqual("System.Int32",b)

[<Test>]
member this.``use typenameof on a custom type`` () =
let b = typenameof<NameOfOperatorForTypes>
Assert.AreEqual("FSharp.Core.Unittests.NameOfOperatorForTypes",b)

[<Test>]
member this.``use typenameof on a custom union type`` () =
let b = typenameof<CustomUnionType>
Assert.AreEqual("FSharp.Core.Unittests.CustomUnionType",b)
//
// [<Test>]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test for typenameof on a generic type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// member this.``use typenameof on a custom union case`` () =
// let b = typenameof<CustomUnionType.OptionB>
// Assert.AreEqual("FSharp.Core.Unittests.CustomUnionType.OptionB",b)

[<Test>]
member this.``use typenameof on List<string>`` () =
let b = typenameof<System.Collections.Generic.List<string>>
Assert.AreEqual("System.Collections.Generic.List`1",b)

[<Test>]
member this.``use typenameof on generic List`` () =
let b = typenameof<System.Collections.Generic.List<_>>
Assert.AreEqual("System.Collections.Generic.List`1",b)



[<TestFixture>]
type OperatorNameTests() =

[<Test>]
member this.``lookup name of typeof operator`` () =
let b = nameof(typeof<int>)
Assert.AreEqual("TypeOf",b)

[<Test>]
member this.``lookup name of + operator`` () =
let b = nameof(+)
Assert.AreEqual("op_Addition",b)

[<Test>]
member this.``lookup name of |> operator`` () =
let a = nameof(|>)
Assert.AreEqual("op_PipeRight",a)
let b = nameof(op_PipeRight)
Assert.AreEqual("op_PipeRight",b)

[<Test>]
member this.``lookup name of nameof operator`` () =
let b = nameof(nameof)
Assert.AreEqual("NameOf",b)

[<TestFixture>]
type PatternMatchingOfOperatorNameTests() =
member this.Method1(i:int) = ()

[<Test>]
member this.``use it as a match case guard`` () =
match "Method1" with
| x when x = nameof(this.Method1) -> ()
| _ -> Assert.Fail("not expected")

[<TestFixture>]
type NameOfOperatorInQuotations() =
[<Test>]
member this.``use it in a quotation`` () =
let q =
<@
let f(x:int) = nameof x
f 20
@>
()

[<TestFixture>]
type NameOfOperatorForGenerics() =
[<Test>]
member this.``use it in a generic function`` () =
let fullyGeneric x = x
let b = nameof(fullyGeneric)
Assert.AreEqual("fullyGeneric",b)

[<TestFixture>]
type UserDefinedNameOfTests() =
[<Test>]
member this.``userdefined nameof should shadow the operator`` () =
let nameof x = "test" + x.ToString()

let y = nameof 1
Assert.AreEqual("test1",y)

type Person =
{ Name : string
Age : int }
member __.Update(fld : string, value : obj) =
match fld with
| x when x = nameof __.Name -> { __ with Name = string value }
| x when x = nameof __.Age -> { __ with Age = value :?> int }
| _ -> __
Original file line number Diff line number Diff line change
Expand Up @@ -2197,8 +2197,10 @@ Microsoft.FSharp.Core.Operators: System.IO.TextReader ConsoleIn[T]()
Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleError[T]()
Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleOut[T]()
Microsoft.FSharp.Core.Operators: System.Object Box[T](T)
Microsoft.FSharp.Core.Operators: System.String NameOf[T](T)
Microsoft.FSharp.Core.Operators: System.String ToString()
Microsoft.FSharp.Core.Operators: System.String ToString[T](T)
Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]()
Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String)
Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue])
Microsoft.FSharp.Core.Operators: System.Type GetType()
Expand Down
2 changes: 2 additions & 0 deletions src/fsharp/FSharp.Core.Unittests/SurfaceArea.net20.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2438,8 +2438,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" +
Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" +
#endif
@"
Microsoft.FSharp.Core.Operators: System.String NameOf[T](T)
Microsoft.FSharp.Core.Operators: System.String ToString()
Microsoft.FSharp.Core.Operators: System.String ToString[T](T)
Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]()
Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String)
Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue])
Microsoft.FSharp.Core.Operators: System.Type GetType()
Expand Down
2 changes: 2 additions & 0 deletions src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2602,8 +2602,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" +
Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" +
#endif
@"
Microsoft.FSharp.Core.Operators: System.String NameOf[T](T)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's needed for surfaceareas of other profiles too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably. will see in test results.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added all SurfaceAreas

Microsoft.FSharp.Core.Operators: System.String ToString()
Microsoft.FSharp.Core.Operators: System.String ToString[T](T)
Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]()
Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String)
Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue])
Microsoft.FSharp.Core.Operators: System.Type GetType()
Expand Down
2 changes: 2 additions & 0 deletions src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2574,8 +2574,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" +
Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" +
#endif
@"
Microsoft.FSharp.Core.Operators: System.String NameOf[T](T)
Microsoft.FSharp.Core.Operators: System.String ToString()
Microsoft.FSharp.Core.Operators: System.String ToString[T](T)
Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]()
Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String)
Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue])
Microsoft.FSharp.Core.Operators: System.Type GetType()
Expand Down
2 changes: 2 additions & 0 deletions src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2576,8 +2576,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" +
Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" +
#endif
@"
Microsoft.FSharp.Core.Operators: System.String NameOf[T](T)
Microsoft.FSharp.Core.Operators: System.String ToString()
Microsoft.FSharp.Core.Operators: System.String ToString[T](T)
Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]()
Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String)
Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue])
Microsoft.FSharp.Core.Operators: System.Type GetType()
Expand Down
2 changes: 2 additions & 0 deletions src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2587,8 +2587,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" +
Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" +
#endif
@"
Microsoft.FSharp.Core.Operators: System.String NameOf[T](T)
Microsoft.FSharp.Core.Operators: System.String ToString()
Microsoft.FSharp.Core.Operators: System.String ToString[T](T)
Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]()
Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String)
Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue])
Microsoft.FSharp.Core.Operators: System.Type GetType()
Expand Down
2 changes: 2 additions & 0 deletions src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2574,8 +2574,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" +
Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" +
#endif
@"
Microsoft.FSharp.Core.Operators: System.String NameOf[T](T)
Microsoft.FSharp.Core.Operators: System.String ToString()
Microsoft.FSharp.Core.Operators: System.String ToString[T](T)
Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]()
Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String)
Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue])
Microsoft.FSharp.Core.Operators: System.Type GetType()
Expand Down
6 changes: 6 additions & 0 deletions src/fsharp/FSharp.Core/prim-types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4753,6 +4753,12 @@ namespace Microsoft.FSharp.Core
[<CompiledName("TypeOf")>]
let inline typeof<'T> = BasicInlinedOperations.typeof<'T>

[<CompiledName("TypeNameOf")>]
let inline typenameof<'T> : string = raise (Exception "may not call directly, should always be optimized away")

[<CompiledName("NameOf")>]
let inline nameof (_: 'T) : string = raise (Exception "may not call directly, should always be optimized away")

[<CompiledName("MethodHandleOf")>]
let methodhandleof (_call: ('T -> 'TResult)) : System.RuntimeMethodHandle = raise (Exception "may not call directly, should always be optimized away")

Expand Down
9 changes: 9 additions & 0 deletions src/fsharp/FSharp.Core/prim-types.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -2306,6 +2306,15 @@ namespace Microsoft.FSharp.Core
[<CompiledName("TypeOf")>]
val inline typeof<'T> : System.Type

/// <summary>Returns the name of the given static type.</summary>
[<RequiresExplicitTypeArguments>]
[<CompiledName("TypeNameOf")>]
val inline typenameof<'T> : string

/// <summary>Returns the name of the given symbol.</summary>
[<CompiledName("NameOf")>]
val inline nameof : 'T -> string

/// <summary>An internal, library-only compiler intrinsic for compile-time
/// generation of a RuntimeMethodHandle.</summary>
[<CompiledName("MethodHandleOf")>]
Expand Down
Loading