Skip to content

Fix finding internal symbols in internals-visible-to projects #15902

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

Merged
merged 5 commits into from
Sep 6, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,36 @@ let ``Finding references in project`` (fastCheck, captureIdentifiersWhenParsing)
findAllReferencesToModuleFromFile "File000" fastCheck (expectNumberOfResults 5)
}

[<Fact>]
let ``Find references to internal symbols in other projects`` () =
let library = {
SyntheticProject.Create("Library",
{ sourceFile "Library" [] with Source = """
namespace Lib

module internal Library =
let foo x = x + 5

[<assembly: System.Runtime.CompilerServices.InternalsVisibleTo("FileFirst")>]
do () """ })
with AutoAddModules = false }

let project =
{ SyntheticProject.Create("App",
{ sourceFile "First" [] with Source = """
open Lib
let bar x = Library.foo x""" })
with DependsOn = [library] }

project.Workflow {
placeCursor "Library" "foo"
findAllReferences (expectToFind [
"FileFirst.fs", 4, 12, 23
"FileLibrary.fs", 5, 8, 11
])
}


[<Fact>]
let ``We find back-ticked identifiers`` () =
SyntheticProject.Create(
Expand Down
18 changes: 11 additions & 7 deletions tests/FSharp.Test.Utilities/ProjectGeneration.fs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,9 @@ let private renderFsProj (p: SyntheticProject) =
let version = reference.Version |> Option.map (fun v -> $" Version=\"{v}\"") |> Option.defaultValue ""
$"<PackageReference Include=\"{reference.Name}\"{version}/>"

for project in p.DependsOn do
$"<ProjectReference Include=\"{project.ProjectFileName}\" />"

for f in p.SourceFiles do
if f.HasSignatureFile then
$"<Compile Include=\"{f.SignatureFileName}\" />"
Expand Down Expand Up @@ -1019,10 +1022,10 @@ type ProjectWorkflowBuilder

member this.FindSymbolUse(ctx: WorkflowContext, fileId, symbolName: string) =
async {
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 project, file = ctx.Project.FindInAllProjects fileId
let fileName = project.ProjectDir ++ file.FileName
let source = renderSourceFile project file
let options= project.GetProjectOptions checker
return! getSymbolUse fileName source symbolName options checker
}

Expand Down Expand Up @@ -1072,16 +1075,17 @@ type ProjectWorkflowBuilder
member this.FindAllReferences(workflow: Async<WorkflowContext>, processResults) =
async {
let! ctx = workflow
let options = ctx.Project.GetProjectOptions checker

let symbolUse =
ctx.Cursor
|> Option.defaultWith (fun () ->
failwith $"Please place cursor at a valid location via placeCursor first")

let! results =
[ for f in options.SourceFiles do
checker.FindBackgroundReferencesInFile(f, options, symbolUse.Symbol, fastCheck = true) ]
[ for p, f in ctx.Project.GetAllFiles() do
let options = p.GetProjectOptions checker
for fileName in [getFilePath p f; if f.SignatureFile <> No then getSignatureFilePath p f] do
checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol, fastCheck = true) ]
|> Async.Parallel

results |> Seq.collect id |> Seq.toList |> processResults
Expand Down
10 changes: 6 additions & 4 deletions vsintegration/src/FSharp.Editor/LanguageService/Symbols.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ type SymbolUse =
type FSharpSymbol with

member this.IsInternalToProject =
let publicOrInternal = this.Accessibility.IsPublic || this.Accessibility.IsInternal

match this with
| :? FSharpParameter -> true
| :? FSharpMemberOrFunctionOrValue as m -> not m.IsModuleValueOrMember || not m.Accessibility.IsPublic
| :? FSharpEntity as m -> not m.Accessibility.IsPublic
| :? FSharpMemberOrFunctionOrValue as m -> not m.IsModuleValueOrMember || not publicOrInternal
| :? FSharpEntity -> not publicOrInternal
| :? FSharpGenericParameter -> true
| :? FSharpUnionCase as m -> not m.Accessibility.IsPublic
| :? FSharpField as m -> not m.Accessibility.IsPublic
| :? FSharpUnionCase -> not publicOrInternal
| :? FSharpField -> not publicOrInternal
| _ -> false

type FSharpSymbolUse with
Expand Down