Skip to content
Merged
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
6 changes: 3 additions & 3 deletions src/Compiler/Service/ItemKey.fs
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,9 @@ and [<Sealed>] ItemKeyStoreBuilder() =
| TType_forall (_, ty) -> writeType false ty

| TType_app (tcref, _, _) ->
match tcref.TypeAbbrev with
| Some ty -> writeType isStandalone ty
| None -> writeEntityRef tcref
match isStandalone, tcref.TypeAbbrev with
| false, Some ty -> writeType false ty
| _ -> writeEntityRef tcref

| TType_tuple (_, tinst) ->
writeString ItemKeyTags.typeTuple
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
open Xunit
open FSharp.Compiler.CodeAnalysis
open FSharp.Test.ProjectGeneration
open FSharp.Test.ProjectGeneration.Helpers

type Occurence = Definition | InType | Use

Expand Down Expand Up @@ -198,7 +199,7 @@ let foo x = 5""" })
}

[<Fact>]
let ``We find a type that has been aliased`` () =
let ``We find values of a type that has been aliased`` () =

let project = SyntheticProject.Create("TypeAliasTest",
{ sourceFile "First" [] with
Expand All @@ -218,3 +219,24 @@ let ``We find a type that has been aliased`` () =
"FileSecond.fs", 6, 12, 29
])
}

[<Fact>]
let ``We don't find type aliases for a type`` () =

let source = """
type MyType =
member _.foo = "boo"
member x.this : mytype = x
and mytype = MyType
"""

let fileName, options, checker = singleFileChecker source

let symbolUse = getSymbolUse fileName source "MyType" options checker |> Async.RunSynchronously

checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol, fastCheck = true)
|> Async.RunSynchronously
|> expectToFind [
fileName, 2, 5, 11
fileName, 5, 13, 19
]
89 changes: 67 additions & 22 deletions tests/FSharp.Test.Utilities/ProjectGeneration.fs
Original file line number Diff line number Diff line change
Expand Up @@ -370,10 +370,10 @@ module ProjectOperations =
let actual =
foundRanges
|> Seq.map (fun r -> Path.GetFileName(r.FileName), r.StartLine, r.StartColumn, r.EndColumn)
|> Seq.sortBy (fun (file, _, _, _) -> file)
|> Seq.sort
|> Seq.toArray

Assert.Equal<(string * int * int * int)[]>(expected |> Seq.toArray, actual)
Assert.Equal<(string * int * int * int)[]>(expected |> Seq.sort |> Seq.toArray, actual)

let rec saveProject (p: SyntheticProject) generateSignatureFiles checker =
async {
Expand Down Expand Up @@ -401,6 +401,65 @@ module ProjectOperations =
}


module Helpers =

let getSymbolUse fileName (source: string) (symbolName: string) options (checker: FSharpChecker) =
async {
let index = source.IndexOf symbolName
let line = source |> Seq.take index |> Seq.where ((=) '\n') |> Seq.length
let fullLine = source.Split '\n' |> Array.item line
let colAtEndOfNames = fullLine.IndexOf symbolName + symbolName.Length

let! results = checker.ParseAndCheckFileInProject(
fileName, 0, SourceText.ofString source, options)

let typeCheckResults = getTypeCheckResult results

let symbolUse =
typeCheckResults.GetSymbolUseAtLocation(line + 1, colAtEndOfNames, fullLine, [symbolName])

return symbolUse |> Option.defaultWith (fun () ->
failwith $"No symbol found in {fileName} at {line}:{colAtEndOfNames}\nFile contents:\n\n{source}\n")
}

let singleFileChecker source =

let fileName = "test.fs"

let getSource _ = source |> SourceText.ofString |> Some

let checker = FSharpChecker.Create(
keepAllBackgroundSymbolUses = false,
enableBackgroundItemKeyStoreAndSemanticClassification = true,
enablePartialTypeChecking = true,
captureIdentifiersWhenParsing = true,
documentSource = DocumentSource.Custom getSource)

let options =
let baseOptions, _ =
checker.GetProjectOptionsFromScript(
fileName,
SourceText.ofString "",
assumeDotNetFramework = false
)
|> Async.RunSynchronously

{ baseOptions with
ProjectFileName = "project"
ProjectId = None
SourceFiles = [|fileName|]
IsIncompleteTypeCheckEnvironment = false
UseScriptResolutionRules = false
LoadTime = DateTime()
UnresolvedReferences = None
OriginalLoadReferences = []
Stamp = None }

fileName, options, checker

open Helpers


type WorkflowContext =
{ Project: SyntheticProject
Signatures: Map<string, string>
Expand Down Expand Up @@ -601,26 +660,12 @@ type ProjectWorkflowBuilder
member this.PlaceCursor(workflow: Async<WorkflowContext>, fileId, symbolName: string) =
async {
let! ctx = workflow

let source = renderSourceFile ctx.Project (ctx.Project.Find fileId)
let index = source.IndexOf symbolName
let line = source |> Seq.take index |> Seq.where ((=) '\n') |> Seq.length
let fullLine = source.Split '\n' |> Array.item line
let colAtEndOfNames = fullLine.IndexOf symbolName + symbolName.Length

let! results = checkFile fileId ctx.Project checker
let typeCheckResults = getTypeCheckResult results

let su =
typeCheckResults.GetSymbolUseAtLocation(line + 1, colAtEndOfNames, fullLine, [symbolName])

if su.IsNone then
let file = ctx.Project.Find fileId

failwith
$"No symbol found in {file.FileName} at {line}:{colAtEndOfNames}\nFile contents:\n\n{source}\n"

return { ctx with Cursor = su }
let file = ctx.Project.Find fileId
let fileName = ctx.Project.ProjectDir ++ file.FileName
let source = renderSourceFile ctx.Project file
let options= ctx.Project.GetProjectOptions checker
let! su = getSymbolUse fileName source symbolName options checker
return { ctx with Cursor = Some su }
}

/// Find all references within a single file, results are provided to the 'processResults' function
Expand Down