-
Notifications
You must be signed in to change notification settings - Fork 830
[WIP] F# RFC-1003 - Implementing nameof operator #908
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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> | ||
| 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>] | ||
|
||
| // 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 |
|---|---|---|
|
|
@@ -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) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's needed for surfaceareas of other profiles too?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably. will see in test results.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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() | ||
|
|
||
There was a problem hiding this comment.
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
typenameofplease? Thanks! https://github.com/fsharp/FSharpLangDesign/blob/master/RFCs/FS-1003-nameof-operator.mdThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll do it
There was a problem hiding this comment.
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 ;-)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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:
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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:
There was a problem hiding this comment.
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)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because I don't know how to do that. see https://github.com/Microsoft/visualfsharp/pull/908/files#diff-e56f7c54b96af89dbcb25c1abd8b072dR2313
There was a problem hiding this comment.
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>). Thenameofoperator can than look at the expression provided. By this evennameof(typedefof<IList<_>>)would work.