From 73034484b6e75e43840a37933ec0011dbadd51bb Mon Sep 17 00:00:00 2001 From: nojaf Date: Wed, 14 Feb 2024 15:59:21 +0100 Subject: [PATCH] After call --- .../src/Checker/FcsCheckerService.fs | 25 +- .../src/Checker/FcsProjectProvider.fs | 2 + .../src/Settings/FSharpOptions.fs | 10 +- .../src/Shim/FileSystem/FSharpSourceCache.fs | 353 +++++++++--------- .../LanguageService/FSharpImportTypeHelper.fs | 218 +++++------ .../src/Search/FSharpSearchGuru.fs | 124 +++--- .../src/Refactorings/Rename.fs | 8 +- rider-fsharp/build.gradle.kts | 4 +- .../fsharp/llm/FSharpFileSummarizer.kt | 3 +- 9 files changed, 384 insertions(+), 363 deletions(-) diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Checker/FcsCheckerService.fs b/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Checker/FcsCheckerService.fs index 178eb0518f..f30965da17 100644 --- a/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Checker/FcsCheckerService.fs +++ b/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Checker/FcsCheckerService.fs @@ -39,6 +39,7 @@ module FcsCheckerService = type FcsProject = { OutputPath: VirtualFileSystemPath ProjectOptions: FSharpProjectOptions + ProjectSnapshot: FSharpProjectSnapshot option ParsingOptions: FSharpParsingOptions FileIndices: IDictionary ImplementationFilesWithSignatures: ISet @@ -88,25 +89,27 @@ type FcsProjectInvalidationType = type FcsCheckerService(lifetime: Lifetime, logger: ILogger, onSolutionCloseNotifier: OnSolutionCloseNotifier, settingsStore: ISettingsStore, locks: IShellLocks, configurations: RunsProducts.ProductConfigurations) = - let checker = - Environment.SetEnvironmentVariable("FCS_CheckFileInProjectCacheSize", "20") - - let settingsStoreLive = settingsStore.BindToContextLive(lifetime, ContextRange.ApplicationWide) + let settingsStoreLive = settingsStore.BindToContextLive(lifetime, ContextRange.ApplicationWide) - let getSettingProperty name = - let setting = SettingsUtil.getEntry settingsStore name - settingsStoreLive.GetValueProperty(lifetime, setting, null) + let getSettingProperty name = + let setting = SettingsUtil.getEntry settingsStore name + settingsStoreLive.GetValueProperty(lifetime, setting, null) + let useTransparentCompiler = (getSettingProperty "UseTransparentCompiler").Value + + let checker = + Environment.SetEnvironmentVariable("FCS_CheckFileInProjectCacheSize", "20") let skipImpl = getSettingProperty "SkipImplementationAnalysis" let analyzerProjectReferencesInParallel = getSettingProperty "ParallelProjectReferencesAnalysis" - + lazy let checker = FSharpChecker.Create(projectCacheSize = 200, keepAllBackgroundResolutions = false, keepAllBackgroundSymbolUses = false, enablePartialTypeChecking = skipImpl.Value, - parallelReferenceResolution = analyzerProjectReferencesInParallel.Value) + parallelReferenceResolution = analyzerProjectReferencesInParallel.Value, + useTransparentCompiler = useTransparentCompiler) checker @@ -156,11 +159,15 @@ type FcsCheckerService(lifetime: Lifetime, logger: ILogger, onSolutionCloseNotif | Some(parseResults, checkResults) -> Some({ ParseResults = parseResults; CheckResults = checkResults }) | _ -> + + ProhibitTypeCheckCookie.AssertTypeCheckIsAllowed() locks.AssertReadAccessAllowed() x.AssertFcsAccessThread() let psiModule = sourceFile.PsiModule + // check if is active ... + if useTransparentCompiler then () match x.FcsProjectProvider.GetFcsProject(psiModule) with | None -> None | Some fcsProject -> diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Checker/FcsProjectProvider.fs b/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Checker/FcsProjectProvider.fs index 7a9ac94e43..e7a7aef2b2 100644 --- a/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Checker/FcsProjectProvider.fs +++ b/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Checker/FcsProjectProvider.fs @@ -285,6 +285,8 @@ type FcsProjectProvider(lifetime: Lifetime, solution: ISolution, changeManager: match scriptFcsProjectProvider.GetScriptOptions(sourceFile) with | None -> None | Some projectOptions -> + + // let snapshot = FSharpProjectSnapshot.FromOptions projectOptions let parsingOptions = { FSharpParsingOptions.Default with diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Settings/FSharpOptions.fs b/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Settings/FSharpOptions.fs index f180cba49b..bdbe336a1e 100644 --- a/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Settings/FSharpOptions.fs +++ b/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Settings/FSharpOptions.fs @@ -29,6 +29,7 @@ module FSharpOptions = let [] nonFSharpProjectInMemoryReferences = "Analyze C# and VB.NET project references in-memory" let [] outOfScopeCompletion = "Enable out of scope items completion" let [] topLevelOpenCompletion = "Add 'open' declarations to top level module or namespace" + let [] useTransparentCompilerDescription = "Use TransparentCompiler" [, "FSharpOptions")>] @@ -46,7 +47,10 @@ type FSharpOptions = mutable EnableOutOfScopeCompletion: bool [] - mutable TopLevelOpenCompletion: bool } + mutable TopLevelOpenCompletion: bool + + [] + mutable UseTransparentCompiler: bool } type FantomasLocationSettings = | AutoDetected = 0 @@ -154,6 +158,9 @@ type FSharpOptionsProvider(lifetime, solution, settings, settingsSchema) = member val NonFSharpProjectInMemoryReferences = base.GetValueProperty("NonFSharpProjectInMemoryReferences").Value with get, set + + member val UseTransparentCompiler = + base.GetValueProperty("UseTransparentCompiler").Value member this.UpdateAssemblyReaderSetting() = this.NonFSharpProjectInMemoryReferences <- @@ -210,6 +217,7 @@ type FSharpOptionsPage(lifetime: Lifetime, optionsPageContext, settings, this.AddBoolOptionWithComment((fun key -> key.SkipImplementationAnalysis), skipImplementationAnalysis, "Requires restart") |> ignore this.AddBoolOptionWithComment((fun key -> key.ParallelProjectReferencesAnalysis), parallelProjectReferencesAnalysis, "Requires restart") |> ignore this.AddBoolOptionWithComment((fun key -> key.OutOfProcessTypeProviders), FSharpExperimentalFeatures.outOfProcessTypeProviders, "Requires restart") |> ignore + this.AddBoolOptionWithComment((fun key -> key.UseTransparentCompiler), useTransparentCompilerDescription, "Requires restart") |> ignore do use indent = this.Indent() diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Shim/FileSystem/FSharpSourceCache.fs b/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Shim/FileSystem/FSharpSourceCache.fs index 60158687a7..1a7450ce8d 100644 --- a/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Shim/FileSystem/FSharpSourceCache.fs +++ b/ReSharper.FSharp/src/FSharp/FSharp.Common/src/Shim/FileSystem/FSharpSourceCache.fs @@ -1,175 +1,178 @@ -namespace JetBrains.ReSharper.Plugins.FSharp.Shim.FileSystem - -open System -open System.IO -open System.Collections.Concurrent -open System.Runtime.InteropServices -open System.Text -open JetBrains.Application.changes -open JetBrains.DataFlow -open JetBrains.Diagnostics -open JetBrains.DocumentManagers -open JetBrains.DocumentManagers.impl -open JetBrains.DocumentModel -open JetBrains.Lifetimes -open JetBrains.ProjectModel -open JetBrains.ReSharper.Plugins.FSharp -open JetBrains.ReSharper.Resources.Shell - -type FSharpSource = - | Exists of Source: byte[] * Timestamp: DateTime - | NotExists - - member x.ToRdFSharpSource() = - match x with - | Exists(source, timestamp) -> RdFSharpSource(Encoding.UTF8.GetString(source), timestamp) - | _ -> RdFSharpSource("NotExists", DateTime.MinValue) - -[] -type FSharpSourceCache(lifetime: Lifetime, solution: ISolution, changeManager, documentManager: DocumentManager, - solutionDocumentChangeProvider: SolutionDocumentChangeProvider, fileExtensions: IProjectFileExtensions, - logger: ILogger) = - inherit FileSystemShimChangeProvider(Lifetime.Define(lifetime).Lifetime, changeManager) - - let fileUpdated = new Signal("FSharpSourceCache.fileUpdated") - - let [] RemoveFileChangeType = - ProjectModelChangeType.REMOVED ||| ProjectModelChangeType.MOVED_OUT - - let [] UpdateFileChangeType = - ProjectModelChangeType.EXTERNAL_CHANGE ||| ProjectModelChangeType.ADDED ||| ProjectModelChangeType.MOVED_IN - - let files = ConcurrentDictionary() - - let getText (document: IDocument) = - Encoding.UTF8.GetBytes(document.GetText()) - - let tryAddSource (path: VirtualFileSystemPath) = - let mutable source = None - ReadLockCookie.TryExecute(fun _ -> - match files.TryGetValue(path) with - | true, value -> source <- Some value - | _ -> - - let document = documentManager.GetOrCreateDocument(path) - if isNull document then () else - - logger.Trace("Add: tryAddSource: {0}", path) - source <- - if path.ExistsFile then - Some(Exists(getText document, File.GetLastWriteTimeUtc(path.FullPath))) - else - Some(NotExists) - - files[path] <- source.Value - ) |> ignore - - source - - let isApplicable (path: VirtualFileSystemPath) = - // todo: support FCS fake paths like `startup`, prevent going to FS to check existence, etc. - not path.IsEmpty && path.IsAbsolute && fileExtensions.GetFileType(path).Is() - - let applyChange (projectFile: IProjectFile) (document: IDocument) changeSource = - let path = projectFile.Location - if not (isApplicable path) then () else - - let text = getText document - - let mutable fsSource = Unchecked.defaultof<_> - match files.TryGetValue(path, &fsSource), fsSource with - | true, Exists(source, _) when source = text -> () - | _ -> - - logger.Trace("Add: {0} change: {1}", changeSource, path) - files[path] <- Exists(text, DateTime.UtcNow) - fileUpdated.Fire(path) - - member x.FileUpdated = fileUpdated - - member x.TryGetSource(path: VirtualFileSystemPath, [] source: byref) = - match files.TryGetValue(path) with - | true, value -> source <- value; true - | _ -> - - match tryAddSource path with - | Some v -> source <- v; true - | _ -> false - - override this.ReadFile(path, useMemoryMappedFile, shouldShadowCopy) = - if not (isApplicable path) then base.ReadFile(path, useMemoryMappedFile, shouldShadowCopy) else - - match this.TryGetSource(path) with - | true, Exists(source, _) -> new MemoryStream(source) :> _ - | true, NotExists -> failwithf $"Reading not existing file: {path}" - | _ -> - - logger.Trace("Miss: FileStreamReadShim miss: {0}", path) - base.ReadFile(path, useMemoryMappedFile, shouldShadowCopy) - - override x.GetLastWriteTime(path) = - if not (isApplicable path) then base.GetLastWriteTime(path) else - - match x.TryGetSource(path) with - | true, Exists(_, timestamp) -> timestamp - | true, NotExists -> FileNotFoundException($"GetLastWriteTime: NotExists: {path}") |> raise - | _ -> - - logger.Trace("GetLastWriteTime: miss: {0}", path) - base.GetLastWriteTime(path) - - override x.ExistsFile(path) = - if not (isApplicable path) then base.ExistsFile(path) else - - match files.TryGetValue(path) with - | true, Exists _ -> true - | true, NotExists -> false - | _ -> - - match tryAddSource path with - | Some (Exists _) -> true - | Some NotExists -> false - | _ -> - - logger.Trace("Miss: Exists: {0}", path) - base.ExistsFile(path) - - member x.ProcessDocumentChange(change: DocumentChange) = - let projectFile = - match change with - | :? ProjectFileDocumentChange as change -> change.ProjectFile - | :? ProjectFileDocumentCopyChange as change -> change.ProjectFile - | _ -> null - - if isNotNull projectFile && projectFile.LanguageType.Is() then - applyChange projectFile change.Document "Document" - - member x.ProcessProjectModelChange(change: ProjectModelChange) = - if isNull change then () else - - let visitor = - { new RecursiveProjectModelChangeDeltaVisitor() with - override v.VisitItemDelta(change) = - base.VisitItemDelta(change) - - if change.ContainsChangeType(RemoveFileChangeType) then - files.TryRemove(change.OldLocation) |> ignore - - if change.ContainsChangeType(UpdateFileChangeType) then - let projectFile = change.ProjectItem.As() - if isValid projectFile && projectFile.LanguageType.Is() then - let document = projectFile.GetDocument() - if isNotNull document then - applyChange projectFile document "Project model" } - - visitor.VisitDelta(change) - - override x.Execute(changeEventArgs: ChangeEventArgs) = - let changeMap = changeEventArgs.ChangeMap - x.ProcessDocumentChange(changeMap.GetChange(solutionDocumentChangeProvider)) - x.ProcessProjectModelChange(changeMap.GetChange(solution)) - - member x.GetRdFSharpSource(fileName: string): RdFSharpSource = - let path = VirtualFileSystemPath.TryParse(fileName, InteractionContext.SolutionContext) - let mutable fsSource = Unchecked.defaultof - if x.TryGetSource(path, &fsSource) then fsSource.ToRdFSharpSource() else null +namespace JetBrains.ReSharper.Plugins.FSharp.Shim.FileSystem + +open System +open System.IO +open System.Collections.Concurrent +open System.Runtime.InteropServices +open System.Text +open JetBrains.Application.changes +open JetBrains.DataFlow +open JetBrains.Diagnostics +open JetBrains.DocumentManagers +open JetBrains.DocumentManagers.impl +open JetBrains.DocumentModel +open JetBrains.Lifetimes +open JetBrains.ProjectModel +open JetBrains.ReSharper.Plugins.FSharp +open JetBrains.ReSharper.Resources.Shell + +type FSharpSource = + | Exists of Source: byte[] * Timestamp: DateTime + | NotExists + + member x.ToRdFSharpSource() = + match x with + | Exists(source, timestamp) -> RdFSharpSource(Encoding.UTF8.GetString(source), timestamp) + | _ -> RdFSharpSource("NotExists", DateTime.MinValue) + +// Potentially drop this cache if transparent compiler is used? +// Might not be used if transparent compiler + +[] +type FSharpSourceCache(lifetime: Lifetime, solution: ISolution, changeManager, documentManager: DocumentManager, + solutionDocumentChangeProvider: SolutionDocumentChangeProvider, fileExtensions: IProjectFileExtensions, + logger: ILogger) = + inherit FileSystemShimChangeProvider(Lifetime.Define(lifetime).Lifetime, changeManager) + + let fileUpdated = new Signal("FSharpSourceCache.fileUpdated") + + let [] RemoveFileChangeType = + ProjectModelChangeType.REMOVED ||| ProjectModelChangeType.MOVED_OUT + + let [] UpdateFileChangeType = + ProjectModelChangeType.EXTERNAL_CHANGE ||| ProjectModelChangeType.ADDED ||| ProjectModelChangeType.MOVED_IN + + let files = ConcurrentDictionary() + + let getText (document: IDocument) = + Encoding.UTF8.GetBytes(document.GetText()) + + let tryAddSource (path: VirtualFileSystemPath) = + let mutable source = None + ReadLockCookie.TryExecute(fun _ -> + match files.TryGetValue(path) with + | true, value -> source <- Some value + | _ -> + + let document = documentManager.GetOrCreateDocument(path) + if isNull document then () else + + logger.Trace("Add: tryAddSource: {0}", path) + source <- + if path.ExistsFile then + Some(Exists(getText document, File.GetLastWriteTimeUtc(path.FullPath))) + else + Some(NotExists) + + files[path] <- source.Value + ) |> ignore + + source + + let isApplicable (path: VirtualFileSystemPath) = + // todo: support FCS fake paths like `startup`, prevent going to FS to check existence, etc. + not path.IsEmpty && path.IsAbsolute && fileExtensions.GetFileType(path).Is() + + let applyChange (projectFile: IProjectFile) (document: IDocument) changeSource = + let path = projectFile.Location + if not (isApplicable path) then () else + + let text = getText document + + let mutable fsSource = Unchecked.defaultof<_> + match files.TryGetValue(path, &fsSource), fsSource with + | true, Exists(source, _) when source = text -> () + | _ -> + + logger.Trace("Add: {0} change: {1}", changeSource, path) + files[path] <- Exists(text, DateTime.UtcNow) + fileUpdated.Fire(path) + + member x.FileUpdated = fileUpdated + + member x.TryGetSource(path: VirtualFileSystemPath, [] source: byref) = + match files.TryGetValue(path) with + | true, value -> source <- value; true + | _ -> + + match tryAddSource path with + | Some v -> source <- v; true + | _ -> false + + override this.ReadFile(path, useMemoryMappedFile, shouldShadowCopy) = + if not (isApplicable path) then base.ReadFile(path, useMemoryMappedFile, shouldShadowCopy) else + + match this.TryGetSource(path) with + | true, Exists(source, _) -> new MemoryStream(source) :> _ + | true, NotExists -> failwithf $"Reading not existing file: {path}" + | _ -> + + logger.Trace("Miss: FileStreamReadShim miss: {0}", path) + base.ReadFile(path, useMemoryMappedFile, shouldShadowCopy) + + override x.GetLastWriteTime(path) = + if not (isApplicable path) then base.GetLastWriteTime(path) else + + match x.TryGetSource(path) with + | true, Exists(_, timestamp) -> timestamp + | true, NotExists -> FileNotFoundException($"GetLastWriteTime: NotExists: {path}") |> raise + | _ -> + + logger.Trace("GetLastWriteTime: miss: {0}", path) + base.GetLastWriteTime(path) + + override x.ExistsFile(path) = + if not (isApplicable path) then base.ExistsFile(path) else + + match files.TryGetValue(path) with + | true, Exists _ -> true + | true, NotExists -> false + | _ -> + + match tryAddSource path with + | Some (Exists _) -> true + | Some NotExists -> false + | _ -> + + logger.Trace("Miss: Exists: {0}", path) + base.ExistsFile(path) + + member x.ProcessDocumentChange(change: DocumentChange) = + let projectFile = + match change with + | :? ProjectFileDocumentChange as change -> change.ProjectFile + | :? ProjectFileDocumentCopyChange as change -> change.ProjectFile + | _ -> null + + if isNotNull projectFile && projectFile.LanguageType.Is() then + applyChange projectFile change.Document "Document" + + member x.ProcessProjectModelChange(change: ProjectModelChange) = + if isNull change then () else + + let visitor = + { new RecursiveProjectModelChangeDeltaVisitor() with + override v.VisitItemDelta(change) = + base.VisitItemDelta(change) + + if change.ContainsChangeType(RemoveFileChangeType) then + files.TryRemove(change.OldLocation) |> ignore + + if change.ContainsChangeType(UpdateFileChangeType) then + let projectFile = change.ProjectItem.As() + if isValid projectFile && projectFile.LanguageType.Is() then + let document = projectFile.GetDocument() + if isNotNull document then + applyChange projectFile document "Project model" } + + visitor.VisitDelta(change) + + override x.Execute(changeEventArgs: ChangeEventArgs) = + let changeMap = changeEventArgs.ChangeMap + x.ProcessDocumentChange(changeMap.GetChange(solutionDocumentChangeProvider)) + x.ProcessProjectModelChange(changeMap.GetChange(solution)) + + member x.GetRdFSharpSource(fileName: string): RdFSharpSource = + let path = VirtualFileSystemPath.TryParse(fileName, InteractionContext.SolutionContext) + let mutable fsSource = Unchecked.defaultof + if x.TryGetSource(path, &fsSource) then fsSource.ToRdFSharpSource() else null diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/LanguageService/FSharpImportTypeHelper.fs b/ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/LanguageService/FSharpImportTypeHelper.fs index 6735bd3b7e..41c9dfa7dd 100644 --- a/ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/LanguageService/FSharpImportTypeHelper.fs +++ b/ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/LanguageService/FSharpImportTypeHelper.fs @@ -1,109 +1,109 @@ -namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.LanguageService - -open JetBrains.ProjectModel -open JetBrains.ReSharper.Intentions.QuickFixes -open JetBrains.ReSharper.Plugins.FSharp.Psi -open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Search -open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl -open JetBrains.ReSharper.Plugins.FSharp.Psi.Metadata -open JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve -open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree -open JetBrains.ReSharper.Plugins.FSharp.Psi.Util -open JetBrains.ReSharper.Psi -open JetBrains.ReSharper.Psi.ExtensionsAPI.Finder -open JetBrains.ReSharper.Psi.Modules -open JetBrains.ReSharper.Psi.Tree - -[)>] -type FSharpImportTypeHelper() = - let [] opName = "FSharpImportTypeHelper.FindTypeCandidates" - - let isApplicable (context: IFSharpReferenceOwner) = - let referenceName = context.As() - not (isNotNull (OpenStatementNavigator.GetByReferenceName(referenceName))) - - interface IImportTypeHelper with - member x.FindTypeCandidates(reference, importTypeCacheFactory) = - let reference = reference.As() - if isNull reference || reference.IsQualified then Seq.empty else - - let context = reference.GetElement() - if not (isApplicable context) then Seq.empty else - - let sourceFile = context.GetSourceFile() - let psiModule = context.GetPsiModule() - let containingModules = getContainingModules context - let referenceStartOffset = context.GetDocumentStartOffset() - - let fsFile = sourceFile.FSharpFile - let settings = fsFile.GetSettingsStoreWithEditorConfig() - - let names = reference.GetAllNames().ResultingList() - let factory = importTypeCacheFactory.Invoke(context) - - let canReferenceInsideProject typeElement = - let searchGuru = psiModule.GetSolution().GetComponent() :> ISearchGuru - let elementId = searchGuru.GetElementId(typeElement) - searchGuru.CanContainReferences(sourceFile, elementId) - - let fsAssemblyAutoOpenCache = psiModule.GetSolution().GetComponent() - - let mutable candidates: ITypeElement seq = - names - |> Seq.collect factory.Invoke - |> Seq.filter (fun clrDeclaredElement -> - let typeElement = clrDeclaredElement.As() - if isNull typeElement then false else - - // todo: enable when singleton property cases are supported - if typeElement.IsUnionCase() then false else - - if typeElement.Module == psiModule && - not (canReferenceInsideProject typeElement) then false else - - let moduleToOpen = getModuleToOpen typeElement - if containingModules.Contains(moduleToOpen) then false else - - if typeElement.Module != psiModule && - not (psiModule.References(typeElement.Module)) then - true else - - let moduleToImport = ModuleToImport.DeclaredElement(moduleToOpen) - let moduleDecl, _ = findModuleToInsertTo fsFile referenceStartOffset settings moduleToImport - let qualifiedElementList = moduleToImport.GetQualifiedElementList(moduleDecl, true) - let names = qualifiedElementList |> List.map (fun el -> el.GetSourceName()) - - let autoOpenedModules = fsAssemblyAutoOpenCache.GetAutoOpenedModules(typeElement.Module) - if autoOpenedModules.Count > 0 && autoOpenedModules.Contains(String.concat "." names) then false else - - let symbolUse = fsFile.CheckerService.ResolveNameAtLocation(context, names, false, opName) - Option.isSome symbolUse) - |> Seq.cast - - - let referenceName = context.As() - if isNotNull referenceName then - let typeArgumentList = referenceName.TypeArgumentList - if isNull typeArgumentList || typeArgumentList.TypeUsages.Count = 0 then () else - - let typesCount = typeArgumentList.TypeUsages.Count - candidates <- candidates |> Seq.filter (fun c -> c.TypeParameters.Count = typesCount) - - let typeReferenceName = context.As() - if isNotNull (AttributeNavigator.GetByReferenceName(typeReferenceName)) then - let attributeTypeElement = context.GetPredefinedType().Attribute.GetTypeElement() - candidates <- candidates |> Seq.filter (fun c -> c.IsDescendantOf(attributeTypeElement)) - - if isNotNull (InheritMemberNavigator.GetByTypeName(typeReferenceName)) then - candidates <- candidates |> Seq.filter (fun c -> c :? IInterface || c :? IClass || c :? IStruct) - - candidates - - member x.ReferenceTargetCanBeType _ = true - member x.ReferenceTargetIsUnlikelyBeType _ = false - - - - - -// todo: ExtensionMethodImportUtilBase +namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.LanguageService + +open JetBrains.ProjectModel +open JetBrains.ReSharper.Intentions.QuickFixes +open JetBrains.ReSharper.Plugins.FSharp.Psi +open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Search +open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl +open JetBrains.ReSharper.Plugins.FSharp.Psi.Metadata +open JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve +open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree +open JetBrains.ReSharper.Plugins.FSharp.Psi.Util +open JetBrains.ReSharper.Psi +open JetBrains.ReSharper.Psi.ExtensionsAPI.Finder +open JetBrains.ReSharper.Psi.Modules +open JetBrains.ReSharper.Psi.Tree + +[)>] +type FSharpImportTypeHelper() = + let [] opName = "FSharpImportTypeHelper.FindTypeCandidates" + + let isApplicable (context: IFSharpReferenceOwner) = + let referenceName = context.As() + not (isNotNull (OpenStatementNavigator.GetByReferenceName(referenceName))) + + interface IImportTypeHelper with + member x.FindTypeCandidates(reference, importTypeCacheFactory) = + let reference = reference.As() + if isNull reference || reference.IsQualified then Seq.empty else + + let context = reference.GetElement() + if not (isApplicable context) then Seq.empty else + + let sourceFile = context.GetSourceFile() + let psiModule = context.GetPsiModule() + let containingModules = getContainingModules context + let referenceStartOffset = context.GetDocumentStartOffset() + + let fsFile = sourceFile.FSharpFile + let settings = fsFile.GetSettingsStoreWithEditorConfig() + + let names = reference.GetAllNames().ResultingList() + let factory = importTypeCacheFactory.Invoke(context) + + let canReferenceInsideProject typeElement = true + // let searchGuru = psiModule.GetSolution().GetComponent() :> ISearchGuru + // let elementId = searchGuru.GetElementId(typeElement) + // searchGuru.CanContainReferences(sourceFile, elementId) + + let fsAssemblyAutoOpenCache = psiModule.GetSolution().GetComponent() + + let mutable candidates: ITypeElement seq = + names + |> Seq.collect factory.Invoke + |> Seq.filter (fun clrDeclaredElement -> + let typeElement = clrDeclaredElement.As() + if isNull typeElement then false else + + // todo: enable when singleton property cases are supported + if typeElement.IsUnionCase() then false else + + if typeElement.Module == psiModule && + not (canReferenceInsideProject typeElement) then false else + + let moduleToOpen = getModuleToOpen typeElement + if containingModules.Contains(moduleToOpen) then false else + + if typeElement.Module != psiModule && + not (psiModule.References(typeElement.Module)) then + true else + + let moduleToImport = ModuleToImport.DeclaredElement(moduleToOpen) + let moduleDecl, _ = findModuleToInsertTo fsFile referenceStartOffset settings moduleToImport + let qualifiedElementList = moduleToImport.GetQualifiedElementList(moduleDecl, true) + let names = qualifiedElementList |> List.map (fun el -> el.GetSourceName()) + + let autoOpenedModules = fsAssemblyAutoOpenCache.GetAutoOpenedModules(typeElement.Module) + if autoOpenedModules.Count > 0 && autoOpenedModules.Contains(String.concat "." names) then false else + + let symbolUse = fsFile.CheckerService.ResolveNameAtLocation(context, names, false, opName) + Option.isSome symbolUse) + |> Seq.cast + + + let referenceName = context.As() + if isNotNull referenceName then + let typeArgumentList = referenceName.TypeArgumentList + if isNull typeArgumentList || typeArgumentList.TypeUsages.Count = 0 then () else + + let typesCount = typeArgumentList.TypeUsages.Count + candidates <- candidates |> Seq.filter (fun c -> c.TypeParameters.Count = typesCount) + + let typeReferenceName = context.As() + if isNotNull (AttributeNavigator.GetByReferenceName(typeReferenceName)) then + let attributeTypeElement = context.GetPredefinedType().Attribute.GetTypeElement() + candidates <- candidates |> Seq.filter (fun c -> c.IsDescendantOf(attributeTypeElement)) + + if isNotNull (InheritMemberNavigator.GetByTypeName(typeReferenceName)) then + candidates <- candidates |> Seq.filter (fun c -> c :? IInterface || c :? IClass || c :? IStruct) + + candidates + + member x.ReferenceTargetCanBeType _ = true + member x.ReferenceTargetIsUnlikelyBeType _ = false + + + + + +// todo: ExtensionMethodImportUtilBase diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/Search/FSharpSearchGuru.fs b/ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/Search/FSharpSearchGuru.fs index 88bbcd8fb9..5a84fd4e24 100644 --- a/ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/Search/FSharpSearchGuru.fs +++ b/ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/Search/FSharpSearchGuru.fs @@ -1,62 +1,62 @@ -namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Search - -open JetBrains.ProjectModel -open JetBrains.ReSharper.Plugins.FSharp -open JetBrains.ReSharper.Plugins.FSharp.Checker -open JetBrains.ReSharper.Plugins.FSharp.Psi -open JetBrains.ReSharper.Psi -open JetBrains.ReSharper.Psi.ExtensionsAPI.Finder -open JetBrains.ReSharper.Psi.Modules - -type FSharpSearchGuruElementId = - { DeclaredElement: IDeclaredElement - PsiModule: IPsiModule - FileIndex: int } - - -[] -type FSharpSearchGuru(fsProjectOptionsProvider: IFcsProjectProvider) = - let getTypeElement (fsElement: IFSharpDeclaredElement) = - match fsElement with - | :? ITypeElement as typeElement -> typeElement - | fsElement -> fsElement.GetContainingType() - - interface ISearchGuru with - member x.IsAvailable _ = true - member x.BuzzWordFilter(_, words) = words - - member x.GetElementId(element) = - let fsDeclaredElement = element.As() - if isNull fsDeclaredElement then null else - - let typeElement = getTypeElement fsDeclaredElement - if isNull typeElement then null else - - let sourceFiles = typeElement.GetSourceFiles() - if sourceFiles.IsEmpty then null else - - let declarationFileIndex = - sourceFiles.ReadOnlyList() - |> Seq.map fsProjectOptionsProvider.GetFileIndex - |> Seq.min - - if declarationFileIndex = -1 then null else - - { DeclaredElement = element - PsiModule = fsDeclaredElement.Module - FileIndex = declarationFileIndex } :> _ - - - member x.CanContainReferences(sourceFile, elementId) = - if not (sourceFile.LanguageType.Is()) then true else - - let fsElementId = elementId :?> FSharpSearchGuruElementId - - let typePrivateMember = fsElementId.DeclaredElement.As() - if isNotNull typePrivateMember then - typePrivateMember.GetSourceFiles().Contains(sourceFile) else - - if sourceFile.PsiModule != fsElementId.PsiModule then true else - - let sourceFileIndex = fsProjectOptionsProvider.GetFileIndex(sourceFile) - sourceFileIndex >= fsElementId.FileIndex +namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Search + +open JetBrains.ProjectModel +open JetBrains.ReSharper.Plugins.FSharp +open JetBrains.ReSharper.Plugins.FSharp.Checker +open JetBrains.ReSharper.Plugins.FSharp.Psi +open JetBrains.ReSharper.Psi +open JetBrains.ReSharper.Psi.ExtensionsAPI.Finder +open JetBrains.ReSharper.Psi.Modules + +type FSharpSearchGuruElementId = + { DeclaredElement: IDeclaredElement + PsiModule: IPsiModule + FileIndex: int } + + +// [] +// type FSharpSearchGuru(fsProjectOptionsProvider: IFcsProjectProvider) = +// let getTypeElement (fsElement: IFSharpDeclaredElement) = +// match fsElement with +// | :? ITypeElement as typeElement -> typeElement +// | fsElement -> fsElement.GetContainingType() +// +// interface ISearchGuru with +// member x.IsAvailable _ = true +// member x.BuzzWordFilter(_, words) = words +// +// member x.GetElementId(element) = +// let fsDeclaredElement = element.As() +// if isNull fsDeclaredElement then null else +// +// let typeElement = getTypeElement fsDeclaredElement +// if isNull typeElement then null else +// +// let sourceFiles = typeElement.GetSourceFiles() +// if sourceFiles.IsEmpty then null else +// +// let declarationFileIndex = +// sourceFiles.ReadOnlyList() +// |> Seq.map fsProjectOptionsProvider.GetFileIndex +// |> Seq.min +// +// if declarationFileIndex = -1 then null else +// +// { DeclaredElement = element +// PsiModule = fsDeclaredElement.Module +// FileIndex = declarationFileIndex } :> _ +// +// +// member x.CanContainReferences(sourceFile, elementId) = +// if not (sourceFile.LanguageType.Is()) then true else +// +// let fsElementId = elementId :?> FSharpSearchGuruElementId +// +// let typePrivateMember = fsElementId.DeclaredElement.As() +// if isNotNull typePrivateMember then +// typePrivateMember.GetSourceFiles().Contains(sourceFile) else +// +// if sourceFile.PsiModule != fsElementId.PsiModule then true else +// +// let sourceFileIndex = fsProjectOptionsProvider.GetFileIndex(sourceFile) +// sourceFileIndex >= fsElementId.FileIndex diff --git a/ReSharper.FSharp/src/FSharp/FSharp.Psi.Services/src/Refactorings/Rename.fs b/ReSharper.FSharp/src/FSharp/FSharp.Psi.Services/src/Refactorings/Rename.fs index cceba9eb70..07ff5dba22 100644 --- a/ReSharper.FSharp/src/FSharp/FSharp.Psi.Services/src/Refactorings/Rename.fs +++ b/ReSharper.FSharp/src/FSharp/FSharp.Psi.Services/src/Refactorings/Rename.fs @@ -237,9 +237,9 @@ type FSharpDeclaredElementForRenameProvider() = type SingleUnionCaseRenameEvaluator() = interface IDerivedRenamesEvaluator with member x.SuggestedElementsHaveDerivedName = false - member x.CreateFromReference(_, _) = EmptyList.Instance :> _ + member x.CreateFromReference(_, _, _) = EmptyList.Instance :> _ - member x.CreateFromElement(initialElement, _) = + member x.CreateFromElement(initialElement, _, _) = let isApplicable (typeElement: ITypeElement) = typeElement.IsUnion() && @@ -265,9 +265,9 @@ type SingleUnionCaseRenameEvaluator() = type AssociatedTypeRenameEvaluator() = interface IDerivedRenamesEvaluator with member x.SuggestedElementsHaveDerivedName = false - member x.CreateFromReference(_, _) = EmptyList.Instance :> _ + member x.CreateFromReference(_, _, _) = EmptyList.Instance :> _ - member x.CreateFromElement(initialElement, _) = + member x.CreateFromElement(initialElement, _, _) = match initialElement.FirstOrDefault() with | :? IFSharpModule as fsModule -> let associatedTypeElement = fsModule.AssociatedTypeElement diff --git a/rider-fsharp/build.gradle.kts b/rider-fsharp/build.gradle.kts index 14eec8d613..a5301e20c3 100644 --- a/rider-fsharp/build.gradle.kts +++ b/rider-fsharp/build.gradle.kts @@ -75,8 +75,8 @@ intellij { "org.intellij.intelliLang", "DatabaseTools", "css-impl", - "javascript-impl", - "com.intellij.ml.llm" + "javascript-impl" + // "com.intellij.ml.llm" ) ) } diff --git a/rider-fsharp/src/main/java/com/jetbrains/rider/plugins/fsharp/llm/FSharpFileSummarizer.kt b/rider-fsharp/src/main/java/com/jetbrains/rider/plugins/fsharp/llm/FSharpFileSummarizer.kt index a44ce217e1..a7c2247cad 100644 --- a/rider-fsharp/src/main/java/com/jetbrains/rider/plugins/fsharp/llm/FSharpFileSummarizer.kt +++ b/rider-fsharp/src/main/java/com/jetbrains/rider/plugins/fsharp/llm/FSharpFileSummarizer.kt @@ -1,5 +1,6 @@ package com.jetbrains.rider.plugins.fsharp.llm +/* import com.intellij.ml.llm.smartChat.psiSummarization.LanguageSummaryProvider import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement @@ -27,4 +28,4 @@ class FSharpFileSummarizer: LanguageSummaryProvider { return null } } - +*/ \ No newline at end of file