<commit_before>﻿namespace FSharpVSPowerTools.Navigation

open System
open System.IO
open System.Windows
open Microsoft.VisualStudio.Text
open Microsoft.VisualStudio.Text.Editor
open Microsoft.VisualStudio.Text.Operations
open Microsoft.VisualStudio
open Microsoft.VisualStudio.OLE.Interop
open Microsoft.VisualStudio.Shell.Interop
open Microsoft.FSharp.Compiler.SourceCodeServices
open Microsoft.FSharp.Compiler.Range
open FSharpVSPowerTools
open FSharpVSPowerTools.ProjectSystem
open FSharp.CompilerBinding

[<RequireQualifiedAccess>]
module PkgCmdConst =
    let cmdidFindReferences = uint32 VSConstants.VSStd97CmdID.FindReferences
    let guidBuiltinCmdSet = VSConstants.GUID_VSStandardCommandSet97
    let guidSymbolLibrary = Guid("2ad4e2a2-b89f-48b6-98e8-363bd1a35450")

[<NoEquality; NoComparison>]
type DocumentState =
    { Word: (SnapshotSpan * Symbol) option
      File: string
      Project: IProjectProvider }

type FindReferencesFilter(view: IWpfTextView, vsLanguageService: VSLanguageService, serviceProvider: System.IServiceProvider) =
    let findReferences() =
        let state =
            maybe {
                let! caretPos = view.TextBuffer.GetSnapshotPoint view.Caret.Position
                let dte = serviceProvider.GetService<EnvDTE.DTE, SDTE>()
                let! doc = dte.GetActiveDocument()
                let! project = ProjectProvider.createForDocument doc
                return { Word = vsLanguageService.GetSymbol(caretPos, project); File = doc.FullName; Project = project }
            }
        match state with
        | Some { Word = Some (cw, sym); File = file; Project = project } ->
            let references =
                vsLanguageService.FindUsages (cw, file, project, [project]) 
                |> Async.RunSynchronously   
                |> Option.map (fun (_, _, refs) -> 
                    refs 
                    |> Seq.map (fun symbolUse -> (symbolUse.FileName, symbolUse))<commit_msg>FindReferencesFilter searches solution-wide<commit_after>﻿namespace FSharpVSPowerTools.Navigation

open System
open System.IO
open System.Windows
open Microsoft.VisualStudio.Text
open Microsoft.VisualStudio.Text.Editor
open Microsoft.VisualStudio.Text.Operations
open Microsoft.VisualStudio
open Microsoft.VisualStudio.OLE.Interop
open Microsoft.VisualStudio.Shell.Interop
open Microsoft.FSharp.Compiler.SourceCodeServices
open Microsoft.FSharp.Compiler.Range
open FSharpVSPowerTools
open FSharpVSPowerTools.ProjectSystem
open FSharp.CompilerBinding

[<RequireQualifiedAccess>]
module PkgCmdConst =
    let cmdidFindReferences = uint32 VSConstants.VSStd97CmdID.FindReferences
    let guidBuiltinCmdSet = VSConstants.GUID_VSStandardCommandSet97
    let guidSymbolLibrary = Guid("2ad4e2a2-b89f-48b6-98e8-363bd1a35450")

[<NoEquality; NoComparison>]
type DocumentState =
    { Word: SnapshotSpan * Symbol
      File: string
      Project: IProjectProvider
      SymbolDeclLocation: SymbolDeclarationLocation }

type FindReferencesFilter(view: IWpfTextView, vsLanguageService: VSLanguageService, serviceProvider: System.IServiceProvider) =
    let findReferences() =
        let dte = serviceProvider.GetService<EnvDTE.DTE, SDTE>()

        let state =
            maybe {
                let! caretPos = view.TextBuffer.GetSnapshotPoint view.Caret.Position
                let! doc = dte.GetActiveDocument()
                let! project = ProjectProvider.createForDocument doc
                let! word, sym = vsLanguageService.GetSymbol(caretPos, project)
                let! symbolUse, _ = 
                    vsLanguageService.GetFSharpSymbolUse(word, sym, doc.FullName, project, AllowStaleResults.No)
                    |> Async.RunSynchronously
                let! symbolDeclarationLocation = ProjectProvider.getSymbolUsageScope symbolUse.Symbol dte doc.FullName
                return { Word = word, sym; File = doc.FullName; Project = project
                         SymbolDeclLocation = symbolDeclarationLocation }
            }

        match state with
        | Some { Word = cw, sym; File = file; Project = project; SymbolDeclLocation = symbolDeclLocation } ->
            let dependentProjects = 
                let declarationProject = 
                    match symbolDeclLocation with
                    | SymbolDeclarationLocation.File -> project
                    | SymbolDeclarationLocation.Project p -> p

                let dependentProjects = ProjectProvider.getDependentProjects dte declarationProject
                if dependentProjects |> List.exists (fun x -> x.ProjectFileName = declarationProject.ProjectFileName)
                then dependentProjects
                else declarationProject :: dependentProjects

            let references =
                vsLanguageService.FindUsages (cw, file, project, dependentProjects) 
                |> Async.RunSynchronously
                |> Option.map (fun (_, _, refs) -> 
                    refs 
                    |> Seq.map (fun symbolUse -> (symbolUse.FileName, symbolUse))
{'fraction_non_alphanumeric': 0.07231075697211155, 'fraction_numerical': 0.010756972111553785, 'mean_word_length': 2.829900839054157, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3133970', 'n_tokens_mistral': 1381, 'n_tokens_neox': 1264, 'n_words': 291}