Skip to content

Commit 81b834c

Browse files
committed
Merge pull request #492 from dsyme/fix-414
Fix 414 - Problems around UseNullAsTrueValue
2 parents ce66d50 + 6425f0f commit 81b834c

File tree

4 files changed

+91
-2
lines changed

4 files changed

+91
-2
lines changed

RELEASE_NOTES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#### 2.0.0.1-beta
22
* Fix 452 - FSharpField.IsMutable = true for BCL enum cases
3-
* Include fix from 1.4.2.2 for #488 - Performance problems with project references
3+
* Fix 452 - FSharpField.IsMutable = true for BCL enum cases
4+
* Fix 414 - Add IsInstanceMemberInCompiledCode
45

56
#### 2.0.0.0-beta
67
* Feature #470, #478, #479 - Move ProjectCracker to separate nuget package and DLL, used ProjectCrackerTool.exe to run

src/fsharp/vs/Symbols.fs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,15 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
14041404
| M m -> m.IsInstance
14051405
| V v -> v.IsInstanceMember
14061406

1407+
member v.IsInstanceMemberInCompiledCode =
1408+
if isUnresolved() then false else
1409+
v.IsInstanceMember &&
1410+
match d with
1411+
| E e -> match e.ArbitraryValRef with Some vref -> ValRefIsCompiledAsInstanceMember cenv.g vref | None -> true
1412+
| P p -> match p.ArbitraryValRef with Some vref -> ValRefIsCompiledAsInstanceMember cenv.g vref | None -> true
1413+
| M m -> match m.ArbitraryValRef with Some vref -> ValRefIsCompiledAsInstanceMember cenv.g vref | None -> true
1414+
| V vref -> ValRefIsCompiledAsInstanceMember cenv.g vref
1415+
14071416
member __.IsExtensionMember =
14081417
if isUnresolved() then false else
14091418
match d with

src/fsharp/vs/Symbols.fsi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,12 @@ and [<Class>] FSharpMemberOrFunctionOrValue =
731731
/// Indicates if this is an instance member, when seen from F#?
732732
member IsInstanceMember : bool
733733

734+
/// Indicates if this is an instance member in compiled code.
735+
///
736+
/// Explanatory note: some members such as IsNone and IsSome on types with UseNullAsTrueValue appear
737+
/// as instance members in F# code but are compiled as static members.
738+
member IsInstanceMemberInCompiledCode : bool
739+
734740
/// Indicates if this is an implicit constructor?
735741
member IsImplicitConstructor : bool
736742

tests/service/ProjectAnalysisTests.fs

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ let attribsOfSymbol (s:FSharpSymbol) =
8888
if v.IsImplicitConstructor then yield "ctor"
8989
if v.IsMutable then yield "mutable"
9090
if v.IsOverrideOrExplicitInterfaceImplementation then yield "overridemem"
91+
if v.IsInstanceMember && not v.IsInstanceMemberInCompiledCode then yield "funky"
9192
if v.IsExplicitInterfaceImplementation then yield "intfmem"
9293
// if v.IsConstructorThisValue then yield "ctorthis"
9394
// if v.IsMemberThisValue then yield "this"
@@ -202,7 +203,7 @@ let ``Test project1 whole project errors`` () =
202203
wholeProjectResults.Errors.[0].EndColumn |> shouldEqual 44
203204

204205
[<Test>]
205-
let ``Test project39 should have protected FullName and TryFullName return same results`` () =
206+
let ``Test Project1 should have protected FullName and TryFullName return same results`` () =
206207
let wholeProjectResults = checker.ParseAndCheckProject(Project1.options) |> Async.RunSynchronously
207208
let rec getFullNameComparisons (entity: FSharpEntity) =
208209
seq { if not entity.IsProvided && entity.Accessibility.IsPublic then
@@ -4630,6 +4631,9 @@ let ``Test project37 typeof and arrays in attribute constructor arguments`` () =
46304631
|> Seq.map (fun a -> a.AttributeType.CompiledName)
46314632
|> Array.ofSeq |> shouldEqual [| "AttrTestAttribute"; "AttrTest2Attribute" |]
46324633

4634+
//-----------------------------------------------------------
4635+
4636+
46334637
module Project38 =
46344638
open System.IO
46354639

@@ -4724,6 +4728,8 @@ let ``Test project38 abstract slot information`` () =
47244728
|]
47254729

47264730

4731+
//--------------------------------------------
4732+
47274733
module Project39 =
47284734
open System.IO
47294735

@@ -4802,3 +4808,70 @@ let ``Test project39 all symbols`` () =
48024808
[["'a"]; ["'a0"]; ["'a"; "'a0"]]),
48034809
("return", "'b"))]
48044810

4811+
4812+
//--------------------------------------------
4813+
4814+
module Project40 =
4815+
open System.IO
4816+
4817+
let fileName1 = Path.ChangeExtension(Path.GetTempFileName(), ".fs")
4818+
let base2 = Path.GetTempFileName()
4819+
let dllName = Path.ChangeExtension(base2, ".dll")
4820+
let projFileName = Path.ChangeExtension(base2, ".fsproj")
4821+
let fileSource1 = """
4822+
module M
4823+
4824+
let f (x: option<_>) = x.IsSome, x.IsNone
4825+
4826+
[<CompilationRepresentation(CompilationRepresentationFlags.UseNullAsTrueValue)>]
4827+
type C =
4828+
| A
4829+
| B of string
4830+
member x.IsItAnA = match x with A -> true | B _ -> false
4831+
member x.IsItAnAMethod() = match x with A -> true | B _ -> false
4832+
4833+
let g (x: C) = x.IsItAnA,x.IsItAnAMethod()
4834+
"""
4835+
4836+
File.WriteAllText(fileName1, fileSource1)
4837+
let fileNames = [fileName1]
4838+
let args = mkProjectCommandLineArgs (dllName, fileNames)
4839+
let options = checker.GetProjectOptionsFromCommandLineArgs (projFileName, args)
4840+
let cleanFileName a = if a = fileName1 then "file1" else "??"
4841+
4842+
[<Test>]
4843+
let ``Test Project40 all symbols`` () =
4844+
4845+
let wholeProjectResults = checker.ParseAndCheckProject(Project40.options) |> Async.RunSynchronously
4846+
let allSymbolUses = wholeProjectResults.GetAllUsesOfAllSymbols() |> Async.RunSynchronously
4847+
let allSymbolUsesInfo = [ for s in allSymbolUses -> s.Symbol.DisplayName, tups s.RangeAlternate, attribsOfSymbol s.Symbol ]
4848+
allSymbolUsesInfo |> shouldEqual
4849+
[("option", ((4, 10), (4, 16)), ["abbrev"]); ("x", ((4, 7), (4, 8)), []);
4850+
("x", ((4, 23), (4, 24)), []);
4851+
("IsSome", ((4, 23), (4, 31)), ["member"; "prop"; "funky"]);
4852+
("x", ((4, 33), (4, 34)), []);
4853+
("IsNone", ((4, 33), (4, 41)), ["member"; "prop"; "funky"]);
4854+
("f", ((4, 4), (4, 5)), ["val"]);
4855+
("CompilationRepresentationAttribute", ((6, 2), (6, 27)), ["class"]);
4856+
("CompilationRepresentationAttribute", ((6, 2), (6, 27)), ["class"]);
4857+
("CompilationRepresentationAttribute", ((6, 2), (6, 27)), ["member"]);
4858+
("CompilationRepresentationFlags", ((6, 28), (6, 58)),
4859+
["enum"; "valuetype"]);
4860+
("UseNullAsTrueValue", ((6, 28), (6, 77)), ["field"; "static"; "8"]);
4861+
("string", ((9, 11), (9, 17)), ["abbrev"]);
4862+
("string", ((9, 11), (9, 17)), ["abbrev"]); ("A", ((8, 6), (8, 7)), []);
4863+
("B", ((9, 6), (9, 7)), []); ("C", ((7, 5), (7, 6)), ["union"]);
4864+
("IsItAnA", ((10, 13), (10, 20)), ["member"; "getter"; "funky"]);
4865+
("IsItAnAMethod", ((11, 13), (11, 26)), ["member"; "funky"]);
4866+
("x", ((10, 11), (10, 12)), []); ("x", ((10, 29), (10, 30)), []);
4867+
("A", ((10, 36), (10, 37)), []); ("B", ((10, 48), (10, 49)), []);
4868+
("x", ((11, 11), (11, 12)), []); ("x", ((11, 37), (11, 38)), []);
4869+
("A", ((11, 44), (11, 45)), []); ("B", ((11, 56), (11, 57)), []);
4870+
("C", ((13, 10), (13, 11)), ["union"]); ("x", ((13, 7), (13, 8)), []);
4871+
("x", ((13, 15), (13, 16)), []);
4872+
("IsItAnA", ((13, 15), (13, 24)), ["member"; "prop"; "funky"]);
4873+
("x", ((13, 25), (13, 26)), []);
4874+
("IsItAnAMethod", ((13, 25), (13, 40)), ["member"; "funky"]);
4875+
("g", ((13, 4), (13, 5)), ["val"]); ("M", ((2, 7), (2, 8)), ["module"])]
4876+
4877+

0 commit comments

Comments
 (0)