diff --git a/ReSharper.FSharp/Directory.Build.props b/ReSharper.FSharp/Directory.Build.props
index 0a015a1a00..4d27e3bb5a 100644
--- a/ReSharper.FSharp/Directory.Build.props
+++ b/ReSharper.FSharp/Directory.Build.props
@@ -9,7 +9,7 @@
2020.1.4
- 2020.1.12
+ 2020.2.0
4.7.0
4.5.0
diff --git a/ReSharper.FSharp/ReSharper.FSharp.sln.DotSettings b/ReSharper.FSharp/ReSharper.FSharp.sln.DotSettings
index a2611e7655..303ea0b910 100644
--- a/ReSharper.FSharp/ReSharper.FSharp.sln.DotSettings
+++ b/ReSharper.FSharp/ReSharper.FSharp.sln.DotSettings
@@ -8,9 +8,18 @@
True
True
True
+ True
True
True
True
True
True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
diff --git a/ReSharper.FSharp/src/Daemon.FSharp/src/FSharpSymbolHighlightingUtil.cs b/ReSharper.FSharp/src/Daemon.FSharp/src/FSharpSymbolHighlightingUtil.cs
index 337bf118b2..787d8926e5 100644
--- a/ReSharper.FSharp/src/Daemon.FSharp/src/FSharpSymbolHighlightingUtil.cs
+++ b/ReSharper.FSharp/src/Daemon.FSharp/src/FSharpSymbolHighlightingUtil.cs
@@ -13,65 +13,65 @@ public static class FSharpSymbolHighlightingUtil
public static string GetEntityHighlightingAttributeId([NotNull] this FSharpEntity entity)
{
if (entity.IsNamespace)
- return FSharpHighlightingAttributeIds.Namespace;
+ return FSharpHighlightingAttributeIdsModule.Namespace;
if (entity.IsEnum)
- return FSharpHighlightingAttributeIds.Enum;
+ return FSharpHighlightingAttributeIdsModule.Enum;
if (entity.IsValueType)
- return FSharpHighlightingAttributeIds.Struct;
+ return FSharpHighlightingAttributeIdsModule.Struct;
if (entity.IsDelegate)
- return FSharpHighlightingAttributeIds.Delegate;
+ return FSharpHighlightingAttributeIdsModule.Delegate;
if (entity.IsFSharpModule)
- return FSharpHighlightingAttributeIds.Module;
+ return FSharpHighlightingAttributeIdsModule.Module;
if (entity.IsFSharpUnion)
- return FSharpHighlightingAttributeIds.Union;
+ return FSharpHighlightingAttributeIdsModule.Union;
if (entity.IsFSharpRecord)
- return FSharpHighlightingAttributeIds.Record;
+ return FSharpHighlightingAttributeIdsModule.Record;
return entity.IsInterface
- ? FSharpHighlightingAttributeIds.Interface
- : FSharpHighlightingAttributeIds.Class;
+ ? FSharpHighlightingAttributeIdsModule.Interface
+ : FSharpHighlightingAttributeIdsModule.Class;
}
[NotNull]
public static string GetMfvHighlightingAttributeId([NotNull] this FSharpMemberOrFunctionOrValue mfv)
{
if (mfv.IsEvent || mfv.IsEventAddMethod || mfv.IsEventRemoveMethod || mfv.EventForFSharpProperty != null)
- return FSharpHighlightingAttributeIds.Event;
+ return FSharpHighlightingAttributeIdsModule.Event;
if (mfv.IsImplicitConstructor || mfv.IsConstructor)
return mfv.DeclaringEntity?.Value is FSharpEntity declEntity && declEntity.IsValueType
- ? FSharpHighlightingAttributeIds.Struct
- : FSharpHighlightingAttributeIds.Class;
+ ? FSharpHighlightingAttributeIdsModule.Struct
+ : FSharpHighlightingAttributeIdsModule.Class;
var entity = mfv.DeclaringEntity;
if (mfv.IsModuleValueOrMember && (entity != null && !entity.Value.IsFSharpModule || mfv.IsExtensionMember))
return mfv.IsProperty || mfv.IsPropertyGetterMethod || mfv.IsPropertySetterMethod
- ? FSharpHighlightingAttributeIds.Property
- : FSharpHighlightingAttributeIds.Method;
+ ? FSharpHighlightingAttributeIdsModule.Property
+ : FSharpHighlightingAttributeIdsModule.Method;
if (mfv.LiteralValue != null)
- return FSharpHighlightingAttributeIds.Literal;
+ return FSharpHighlightingAttributeIdsModule.Literal;
if (mfv.IsActivePattern)
- return FSharpHighlightingAttributeIds.ActivePatternCase;
+ return FSharpHighlightingAttributeIdsModule.ActivePatternCase;
if (mfv.IsMutable || mfv.IsRefCell())
- return FSharpHighlightingAttributeIds.MutableValue;
+ return FSharpHighlightingAttributeIdsModule.MutableValue;
if (IsMangledOpName(mfv.LogicalName))
- return FSharpHighlightingAttributeIds.Operator;
+ return FSharpHighlightingAttributeIdsModule.Operator;
var fsType = mfv.FullType;
if (fsType.HasTypeDefinition && fsType.TypeDefinition is var mfvTypeEntity && mfvTypeEntity.IsByRef)
- return FSharpHighlightingAttributeIds.MutableValue;
+ return FSharpHighlightingAttributeIdsModule.MutableValue;
- return FSharpHighlightingAttributeIds.Value;
+ return FSharpHighlightingAttributeIdsModule.Value;
}
[NotNull]
@@ -87,21 +87,21 @@ public static string GetHighlightingAttributeId([NotNull] this FSharpSymbol symb
case FSharpField field:
return field.IsLiteral
- ? FSharpHighlightingAttributeIds.Literal
- : FSharpHighlightingAttributeIds.Field;
+ ? FSharpHighlightingAttributeIdsModule.Literal
+ : FSharpHighlightingAttributeIdsModule.Field;
case FSharpUnionCase _:
- return FSharpHighlightingAttributeIds.UnionCase;
+ return FSharpHighlightingAttributeIdsModule.UnionCase;
case FSharpGenericParameter _:
- return FSharpHighlightingAttributeIds.TypeParameter;
+ return FSharpHighlightingAttributeIdsModule.TypeParameter;
case FSharpActivePatternCase _:
- return FSharpHighlightingAttributeIds.ActivePatternCase;
+ return FSharpHighlightingAttributeIdsModule.ActivePatternCase;
}
// some highlighting is needed for tooltip provider
- return FSharpHighlightingAttributeIds.Value;
+ return FSharpHighlightingAttributeIdsModule.Value;
}
}
}
diff --git a/ReSharper.FSharp/src/Daemon.FSharp/src/Highlightings/IdentifierHighlighting.cs b/ReSharper.FSharp/src/Daemon.FSharp/src/Highlightings/IdentifierHighlighting.cs
index d4797c3225..03c05cf03d 100644
--- a/ReSharper.FSharp/src/Daemon.FSharp/src/Highlightings/IdentifierHighlighting.cs
+++ b/ReSharper.FSharp/src/Daemon.FSharp/src/Highlightings/IdentifierHighlighting.cs
@@ -9,7 +9,7 @@ public interface IFSharpIdentifierTooltipProvider
}
[DaemonTooltipProvider(typeof(IFSharpIdentifierTooltipProvider))]
- [StaticSeverityHighlighting(Severity.INFO, HighlightingGroupIds.IdentifierHighlightingsGroup,
+ [StaticSeverityHighlighting(Severity.INFO, typeof(HighlightingGroupIds.IdentifierHighlightings),
OverlapResolve = OverlapResolveKind.NONE, ShowToolTipInStatusBar = false)]
public class FSharpIdentifierHighlighting : ICustomAttributeIdHighlighting
{
diff --git a/ReSharper.FSharp/src/Daemon.FSharp/src/Stages/HighlightIdentifiersStage.cs b/ReSharper.FSharp/src/Daemon.FSharp/src/Stages/HighlightIdentifiersStage.cs
index f8db2d214d..1099207ee3 100644
--- a/ReSharper.FSharp/src/Daemon.FSharp/src/Stages/HighlightIdentifiersStage.cs
+++ b/ReSharper.FSharp/src/Daemon.FSharp/src/Stages/HighlightIdentifiersStage.cs
@@ -45,7 +45,7 @@ private void AddHighlightings(IEnumerable symbolsUses,
var highlightingId =
symbolUse.IsFromComputationExpression
- ? FSharpHighlightingAttributeIds.Keyword
+ ? FSharpHighlightingAttributeIdsModule.Keyword
: symbol.GetHighlightingAttributeId();
if (symbolUse.IsFromDefinition && symbol is FSharpMemberOrFunctionOrValue mfv)
diff --git a/ReSharper.FSharp/src/FSharp.Common/FSharp.Common.fsproj b/ReSharper.FSharp/src/FSharp.Common/FSharp.Common.fsproj
index edbfd7b433..0495757d1f 100644
--- a/ReSharper.FSharp/src/FSharp.Common/FSharp.Common.fsproj
+++ b/ReSharper.FSharp/src/FSharp.Common/FSharp.Common.fsproj
@@ -39,8 +39,10 @@
-
-
+
+
+
+
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Checker/FSharpCheckerService.fs b/ReSharper.FSharp/src/FSharp.Common/src/Checker/FSharpCheckerService.fs
index aa99275328..3db42a5e1a 100644
--- a/ReSharper.FSharp/src/FSharp.Common/src/Checker/FSharpCheckerService.fs
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Checker/FSharpCheckerService.fs
@@ -1,7 +1,6 @@
namespace rec JetBrains.ReSharper.Plugins.FSharp.Checker
open System
-open System.Collections.Generic
open System.Runtime.InteropServices
open FSharp.Compiler.SourceCodeServices
open FSharp.Compiler.Text
@@ -11,6 +10,7 @@ open JetBrains.Application
open JetBrains.Application.Settings
open JetBrains.DataFlow
open JetBrains.DocumentModel
+open JetBrains.Lifetimes
open JetBrains.ProjectModel
open JetBrains.ReSharper.Feature.Services
open JetBrains.ReSharper.Plugins.FSharp
@@ -21,10 +21,15 @@ open JetBrains.ReSharper.Psi.Modules
open JetBrains.ReSharper.Psi.Tree
open JetBrains.Util
+module FSharpCheckerService =
+ let getSourceText (document: IDocument) =
+ SourceText.ofString(document.GetText())
+
+
[]
type FSharpCheckerService
- (lifetime, logger: ILogger, onSolutionCloseNotifier: OnSolutionCloseNotifier, settingsStore: ISettingsStore,
- settingsSchema: SettingsSchema) =
+ (lifetime: Lifetime, logger: ILogger, onSolutionCloseNotifier: OnSolutionCloseNotifier,
+ settingsStore: ISettingsStore, settingsSchema: SettingsSchema) =
let checker =
Environment.SetEnvironmentVariable("FCS_CheckFileInProjectCacheSize", "20")
@@ -55,13 +60,23 @@ type FSharpCheckerService
if checker.IsValueCreated then
checker.Value.InvalidateAll())
- member val OptionsProvider = Unchecked.defaultof with get, set
+ member val FcsReactorMonitor = Unchecked.defaultof with get, set
+ member val FcsProjectProvider = Unchecked.defaultof with get, set
+
member x.Checker = checker.Value
- member x.ParseFile(path: FileSystemPath, document: IDocument, parsingOptions: FSharpParsingOptions) =
- let source = SourceText.ofString (document.GetText())
+ member x.ParseFile(path, document, parsingOptions, [] noCache: bool) =
try
- let parseResults = x.Checker.ParseFile(path.FullPath, source, parsingOptions).RunAsTask()
+ let source = FSharpCheckerService.getSourceText document
+ let fullPath = getFullPath path
+
+ let parseAsync =
+ if noCache then
+ x.Checker.ParseFileNoCache(fullPath, source, parsingOptions)
+ else
+ x.Checker.ParseFile(fullPath, source, parsingOptions)
+
+ let parseResults = parseAsync.RunAsTask()
Some parseResults
with
| OperationCanceled -> reraise()
@@ -71,21 +86,23 @@ type FSharpCheckerService
None
member x.ParseFile([] sourceFile: IPsiSourceFile) =
- let parsingOptions = x.OptionsProvider.GetParsingOptions(sourceFile)
+ let parsingOptions = x.FcsProjectProvider.GetParsingOptions(sourceFile)
x.ParseFile(sourceFile.GetLocation(), sourceFile.Document, parsingOptions)
member x.ParseAndCheckFile([] file: IPsiSourceFile, opName,
[] allowStaleResults) =
- match x.OptionsProvider.GetProjectOptions(file) with
+ match x.FcsProjectProvider.GetProjectOptions(file) with
| None -> None
| Some options ->
let path = file.GetLocation().FullPath
- let source = SourceText.ofString (file.Document.GetText())
+ let source = FSharpCheckerService.getSourceText file.Document
logger.Trace("ParseAndCheckFile: start {0}, {1}", path, opName)
+ use op = x.FcsReactorMonitor.MonitorOperation opName
+
// todo: don't cancel the computation when file didn't change
- match x.Checker.ParseAndCheckDocument(path, source, options, allowStaleResults, opName).RunAsTask() with
+ match x.Checker.ParseAndCheckDocument(path, source, options, allowStaleResults, op.OperationName).RunAsTask() with
| Some (parseResults, checkResults) when parseResults.ParseTree.IsSome ->
logger.Trace("ParseAndCheckFile: finish {0}, {1}", path, opName)
Some { ParseResults = parseResults; CheckResults = checkResults }
@@ -95,7 +112,7 @@ type FSharpCheckerService
None
member x.TryGetStaleCheckResults([] file: IPsiSourceFile, opName) =
- match x.OptionsProvider.GetProjectOptions(file) with
+ match x.FcsProjectProvider.GetProjectOptions(file) with
| None -> None
| Some options ->
@@ -111,9 +128,9 @@ type FSharpCheckerService
logger.Trace("TryGetStaleCheckResults: fail {0}, {1}", path, opName)
None
- member x.InvalidateFSharpProject(fsProject: FSharpProject) =
+ member x.InvalidateFcsProject(fcsProjectOptions: FSharpProjectOptions) =
if checker.IsValueCreated then
- checker.Value.InvalidateConfiguration(fsProject.ProjectOptions, false)
+ checker.Value.InvalidateConfiguration(fcsProjectOptions, false)
/// Use with care: returns wrong symbol inside its non-recursive declaration, see dotnet/fsharp#7694.
member x.ResolveNameAtLocation(sourceFile: IPsiSourceFile, names, coords, opName) =
@@ -123,7 +140,9 @@ type FSharpCheckerService
let checkResults = results.CheckResults
let fcsPos = getPosFromCoords coords
let lineText = sourceFile.Document.GetLineText(coords.Line)
- checkResults.GetSymbolUseAtLocation(fcsPos.Line, fcsPos.Column, lineText, names, opName).RunAsTask())
+
+ use op = x.FcsReactorMonitor.MonitorOperation opName
+ checkResults.GetSymbolUseAtLocation(fcsPos.Line, fcsPos.Column, lineText, names, op.OperationName).RunAsTask())
/// Use with care: returns wrong symbol inside its non-recursive declaration, see dotnet/fsharp#7694.
member x.ResolveNameAtLocation(sourceFile: IPsiSourceFile, name, coords, opName) =
@@ -137,31 +156,37 @@ type FSharpCheckerService
x.ResolveNameAtLocation(sourceFile, names, coords, opName)
-type FSharpProject =
- { ProjectOptions: FSharpProjectOptions
- ParsingOptions: FSharpParsingOptions
- FileIndices: IDictionary
- ImplFilesWithSigs: ISet }
-
- member x.ContainsFile(file: IPsiSourceFile) =
- x.FileIndices.ContainsKey(file.GetLocation())
-
-
type FSharpParseAndCheckResults =
{ ParseResults: FSharpParseFileResults
CheckResults: FSharpCheckFileResults }
-type IFSharpProjectOptionsProvider =
+type IFcsProjectProvider =
abstract GetProjectOptions: IPsiSourceFile -> FSharpProjectOptions option
abstract GetParsingOptions: IPsiSourceFile -> FSharpParsingOptions
abstract GetFileIndex: IPsiSourceFile -> int
+
+ // Indicates if implementation file has an associated signature file.
abstract HasPairFile: IPsiSourceFile -> bool
- abstract Invalidate: IProject -> bool
+
+ /// Returns True when the project has been invalidated.
+ abstract InvalidateReferencesToProject: IProject -> bool
+
abstract ModuleInvalidated: ISignal
- abstract HasFSharpProjects: bool
+
+ /// True when any F# projects are currently known to project options provider after requesting info from FCS.
+ abstract HasFcsProjects: bool
-type IFSharpScriptProjectOptionsProvider =
+type IScriptFcsProjectProvider =
abstract GetScriptOptions: IPsiSourceFile -> FSharpProjectOptions option
abstract GetScriptOptions: FileSystemPath * string -> FSharpProjectOptions option
+
+
+type IMonitoredReactorOperation =
+ inherit IDisposable
+ abstract OperationName : string
+
+
+type IFcsReactorMonitor =
+ abstract MonitorOperation : opName: string -> IMonitoredReactorOperation
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Checker/FSharpProjectOptionsBuilder.fs b/ReSharper.FSharp/src/FSharp.Common/src/Checker/FSharpProjectOptionsBuilder.fs
deleted file mode 100644
index 47c9ea349d..0000000000
--- a/ReSharper.FSharp/src/FSharp.Common/src/Checker/FSharpProjectOptionsBuilder.fs
+++ /dev/null
@@ -1,252 +0,0 @@
-namespace JetBrains.ReSharper.Plugins.FSharp.Checker
-
-open System
-open System.Collections.Generic
-open FSharp.Compiler.SourceCodeServices
-open JetBrains.Application
-open JetBrains.Diagnostics
-open JetBrains.ProjectModel
-open JetBrains.ProjectModel.ProjectsHost
-open JetBrains.ProjectModel.ProjectsHost.MsBuild.Strategies
-open JetBrains.ProjectModel.Properties
-open JetBrains.ProjectModel.Properties.Managed
-open JetBrains.ReSharper.Plugins.FSharp.ProjectModel
-open JetBrains.ReSharper.Plugins.FSharp.ProjectModel.ProjectProperties
-open JetBrains.ReSharper.Plugins.FSharp.ProjectModel.ProjectItems.ItemsContainer
-open JetBrains.ReSharper.Plugins.FSharp.Util
-open JetBrains.ReSharper.Psi.Modules
-open JetBrains.Util
-open JetBrains.Util.Dotnet.TargetFrameworkIds
-
-module FSharpProperties =
- let [] TargetProfile = "TargetProfile"
- let [] BaseAddress = "BaseAddress"
- let [] OtherFlags = "OtherFlags"
- let [] NoWarn = "NoWarn"
- let [] WarnAsError = "WarnAsError"
- let [] FscToolPath = "FscToolPath"
- let [] LangVersion = "LangVersion"
-
-
-[]
-type FSharpProjectPropertiesRequest() =
- let properties =
- [| FSharpProperties.TargetProfile
- FSharpProperties.BaseAddress
- FSharpProperties.OtherFlags
- FSharpProperties.NoWarn
- FSharpProperties.WarnAsError
- FSharpProperties.FscToolPath
- FSharpProperties.LangVersion |]
-
- interface IProjectPropertiesRequest with
- member x.RequestedProperties = properties :> _
-
-
-[]
-type FSharpTargetsProjectLoadModificator() =
- let fsTargets =
- [| "GenerateCode"
- "GenerateFSharpInternalsVisibleToFile"
- "GenerateAssemblyFileVersionTask"
- "ImplicitlyExpandNETStandardFacades" |]
-
- interface MsBuildLegacyLoadStrategy.IModificator with
- member x.IsApplicable(mark) =
- match mark with
- | FSharpProjectMark -> true
- | _ -> false
-
- member x.Modify(targets) =
- targets.AddRange(fsTargets)
-
-[]
-module ProjectOptions =
- let sandboxParsingOptions =
- { FSharpParsingOptions.Default with SourceFiles = [| "Sandbox.fs" |] }
-
- []
- module ImplicitDefines =
- let sourceDefines = [ "EDITING"; "COMPILED" ]
- let scriptDefines = [ "EDITING"; "INTERACTIVE" ]
-
- let getImplicitDefines isScript =
- if isScript then scriptDefines else sourceDefines
-
-
-
-type IFSharpProjectOptionsBuilder =
- abstract BuildSingleFSharpProject: IProject * IPsiModule -> FSharpProject
-
-
-[]
-type FSharpProjectOptionsBuilder
- (checkerService: FSharpCheckerService, logger: ILogger, itemsContainer: IFSharpItemsContainer) =
-
- let defaultDelimiters = [| ';'; ','; ' ' |]
-
- let defaultOptions =
- [| "--noframework"
- "--debug:full"
- "--debug+"
- "--optimize-"
- "--tailcalls-"
- "--fullpaths"
- "--flaterrors"
- "--highentropyva+"
- "--noconditionalerasure" |]
-
- let unusedValuesWarns =
- [| "--warnon:1182" |]
-
- let splitAndTrim (delimiters: char[]) = function
- | null -> EmptyArray.Instance
- | (s: string) -> s.Split(delimiters, StringSplitOptions.RemoveEmptyEntries)
-
- let getReferences psiModule =
- getReferencePaths (fun _ -> true) psiModule
- |> Seq.map (fun r -> "-r:" + r)
-
- let getOutputType outputType =
- match outputType with
- | ProjectOutputType.CONSOLE_EXE -> "exe"
- | ProjectOutputType.WIN_EXE -> "winexe"
- | ProjectOutputType.MODULE -> "module"
- | _ -> "library"
-
- abstract GetProjectItemsPaths:
- project: IProject * targetFrameworkId: TargetFrameworkId -> (FileSystemPath * BuildAction)[]
-
- default x.GetProjectItemsPaths(project, targetFrameworkId) =
- let projectMark = project.GetProjectMark().NotNull()
- itemsContainer.GetProjectItemsPaths(projectMark, targetFrameworkId)
-
- member x.GetProjectFilesAndResources(project: IProject, targetFrameworkId) =
- let sourceFiles = List()
- let resources = List()
-
- let sigFiles = HashSet()
- let implsWithSigs = HashSet()
-
- let projectItems = x.GetProjectItemsPaths(project, targetFrameworkId)
-
- for path, buildAction in projectItems do
- match buildAction with
- | SourceFile ->
- sourceFiles.Add(path) |> ignore
- let fileName = path.NameWithoutExtension
- match path.ExtensionNoDot with
- | SigExtension -> sigFiles.Add(fileName) |> ignore
- | ImplExtension when sigFiles.Contains(fileName) -> implsWithSigs.add(path)
- | _ -> ()
-
- | Resource -> resources.Add(path) |> ignore
- | _ -> ()
-
- let resources: IList<_> = if resources.IsEmpty() then EmptyList.InstanceList else resources :> _
- let implsWithSigs: ISet<_> = if implsWithSigs.IsEmpty() then EmptySet.Instance :> _ else implsWithSigs :> _
-
- sourceFiles.ToArray(), implsWithSigs, resources
-
- interface IFSharpProjectOptionsBuilder with
- member x.BuildSingleFSharpProject(project: IProject, psiModule: IPsiModule) =
- let targetFrameworkId = psiModule.TargetFrameworkId
- let properties = project.ProjectProperties
-
- let options = List()
-
- let outPath = project.GetOutputFilePath(targetFrameworkId)
- if not outPath.IsEmpty then
- options.Add("--out:" + outPath.FullPath)
-
- options.AddRange(defaultOptions)
- options.AddRange(unusedValuesWarns)
- options.AddRange(getReferences psiModule)
-
- match properties.ActiveConfigurations.TryGetConfiguration(targetFrameworkId) with
- | :? IManagedProjectConfiguration as cfg ->
- let definedConstants = splitAndTrim defaultDelimiters cfg.DefineConstants
- options.AddRange(definedConstants |> Seq.map (fun c -> "--define:" + c))
-
- options.Add("--target:" + getOutputType cfg.OutputType)
-
- options.Add(sprintf "--warn:%d" cfg.WarningLevel)
-
- if cfg.TreatWarningsAsErrors then
- options.Add("--warnaserror")
-
- let doc = cfg.DocumentationFile
- if not (doc.IsNullOrWhitespace()) then options.Add("--doc:" + doc)
-
- let props = cfg.PropertiesCollection
-
- let getOption f p =
- match props.TryGetValue(p) with
- | true, v when not (v.IsNullOrWhitespace()) -> Some ("--" + p.ToLower() + ":" + f v)
- | _ -> None
-
- [ FSharpProperties.TargetProfile; FSharpProperties.BaseAddress; FSharpProperties.LangVersion ]
- |> List.choose (getOption id)
- |> options.AddRange
-
- [ FSharpProperties.NoWarn; FSharpProperties.WarnAsError ]
- |> List.choose (getOption (fun v -> (splitAndTrim defaultDelimiters v).Join(",")))
- |> options.AddRange
-
- match props.TryGetValue(FSharpProperties.OtherFlags) with
- | true, otherFlags when not (otherFlags.IsNullOrWhitespace()) -> splitAndTrim [| ' ' |] otherFlags
- | _ -> EmptyArray.Instance
- |> options.AddRange
- | _ -> ()
-
- let filePaths, implsWithSig, resources = x.GetProjectFilesAndResources(project, targetFrameworkId)
-
- options.AddRange(resources |> Seq.map (fun (r: FileSystemPath) -> "--resource:" + r.FullPath))
- let fileIndices = Dictionary()
- Array.iteri (fun i p -> fileIndices.[p] <- i) filePaths
-
- let projectOptions =
- { ProjectFileName = sprintf "%O.%O.fsproj" project.ProjectFileLocation targetFrameworkId
- ProjectId = None
- SourceFiles = Array.map (fun (p: FileSystemPath ) -> p.FullPath) filePaths
- OtherOptions = options.ToArray()
- ReferencedProjects = Array.empty
- IsIncompleteTypeCheckEnvironment = false
- UseScriptResolutionRules = false
- LoadTime = DateTime.Now
- OriginalLoadReferences = List.empty
- UnresolvedReferences = None
- ExtraProjectInfo = None
- Stamp = None }
-
- let hasFSharpCoreReference options =
- options.OtherOptions
- |> Seq.exists (fun s ->
- s.StartsWith("-r:", StringComparison.Ordinal) &&
- s.EndsWith("FSharp.Core.dll", StringComparison.Ordinal))
-
- let shouldAddFSharpCore options =
- not (hasFSharpCoreReference options || options.OtherOptions |> Array.contains "--compiling-fslib")
-
- let options =
- if shouldAddFSharpCore projectOptions then
- { projectOptions with
- OtherOptions = FSharpCoreFix.ensureCorrectFSharpCore projectOptions.OtherOptions }
- else projectOptions
-
- let parsingOptions, errors =
- checkerService.Checker.GetParsingOptionsFromCommandLineArgs(List.ofArray options.OtherOptions)
-
- let defines = ImplicitDefines.sourceDefines @ parsingOptions.ConditionalCompilationDefines
-
- let parsingOptions = { parsingOptions with
- SourceFiles = options.SourceFiles
- ConditionalCompilationDefines = defines }
-
- if not errors.IsEmpty then
- logger.Warn("Getting parsing options: {0}", concatErrors errors)
-
- { ProjectOptions = projectOptions
- ParsingOptions = parsingOptions
- FileIndices = fileIndices
- ImplFilesWithSigs = implsWithSig }
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Checker/FSharpProjectOptionsProvider.fs b/ReSharper.FSharp/src/FSharp.Common/src/Checker/FSharpProjectOptionsProvider.fs
deleted file mode 100644
index 6c1a318d81..0000000000
--- a/ReSharper.FSharp/src/FSharp.Common/src/Checker/FSharpProjectOptionsProvider.fs
+++ /dev/null
@@ -1,311 +0,0 @@
-namespace rec JetBrains.ReSharper.Plugins.FSharp.Checker
-
-open System.Collections.Generic
-open FSharp.Compiler.SourceCodeServices
-open FSharp.Compiler.Text
-open JetBrains.Annotations
-open JetBrains.Application.changes
-open JetBrains.DataFlow
-open JetBrains.ProjectModel
-open JetBrains.ProjectModel.Assemblies.Impl
-open JetBrains.ProjectModel.Build
-open JetBrains.ReSharper.Feature.Services.Daemon
-open JetBrains.ReSharper.Plugins.FSharp.ProjectModel.Scripts
-open JetBrains.ReSharper.Plugins.FSharp
-open JetBrains.ReSharper.Plugins.FSharp.Checker
-open JetBrains.ReSharper.Plugins.FSharp.ProjectModel
-open JetBrains.ReSharper.Plugins.FSharp.ProjectModel.ProjectItems.ItemsContainer
-open JetBrains.ReSharper.Plugins.FSharp.ProjectModel.ProjectProperties
-open JetBrains.ReSharper.Plugins.FSharp.Settings
-open JetBrains.ReSharper.Plugins.FSharp.Util
-open JetBrains.ReSharper.Psi
-open JetBrains.ReSharper.Psi.Files
-open JetBrains.ReSharper.Psi.Modules
-open JetBrains.Threading
-open JetBrains.Util
-
-[]
-type FSharpProjectOptionsProvider
- (lifetime, solution: ISolution, changeManager: ChangeManager, checkerService: FSharpCheckerService,
- optionsBuilder: IFSharpProjectOptionsBuilder, scriptOptionsProvider: IFSharpScriptProjectOptionsProvider,
- fsFileService: IFSharpFileService, moduleReferenceResolveStore: ModuleReferencesResolveStore, logger: ILogger,
- psiModules: IPsiModules, resolveContextManager: PsiModuleResolveContextManager) as this =
- inherit RecursiveProjectModelChangeDeltaVisitor()
-
- let [] invalidatingProjectChangeType =
- ProjectModelChangeType.PROPERTIES ||| ProjectModelChangeType.TARGET_FRAMEWORK |||
- ProjectModelChangeType.REFERENCE_TARGET
-
- let [] invalidatingChildChangeType =
- ProjectModelChangeType.ADDED ||| ProjectModelChangeType.REMOVED |||
- ProjectModelChangeType.MOVED_IN ||| ProjectModelChangeType.MOVED_OUT |||
- ProjectModelChangeType.REFERENCE_TARGET
-
- let projects = Dictionary>()
- let psiModulesToFsProjects = Dictionary()
-
- let locker = JetFastSemiReenterableRWLock()
- do
- changeManager.Changed2.Advise(lifetime, this.ProcessChange)
- checkerService.OptionsProvider <- this
- lifetime.OnTermination(fun _ -> checkerService.OptionsProvider <- Unchecked.defaultof<_>) |> ignore
-
- let moduleInvalidated = new Signal(lifetime, "FSharpPsiModuleInvalidated")
-
- let tryGetFSharpProject (psiModule: IPsiModule) =
- use lock = locker.UsingReadLock()
- tryGetValue psiModule psiModulesToFsProjects
-
- let rec createFSharpProject (project: IProject) (psiModule: IPsiModule) =
- let mutable fsProject = Unchecked.defaultof<_>
- match psiModulesToFsProjects.TryGetValue(psiModule, &fsProject) with
- | true -> fsProject
- | _ ->
-
- logger.Info("Creating options for {0} {1}", project, psiModule)
- let fsProject = optionsBuilder.BuildSingleFSharpProject(project, psiModule)
-
- let referencedProjectsOptions = seq {
- let resolveContext =
- resolveContextManager.GetOrCreateModuleResolveContext(project, psiModule, psiModule.TargetFrameworkId)
-
- let referencedProjectsPsiModules =
- psiModules.GetModuleReferences(psiModule, resolveContext)
- |> Seq.choose (fun reference ->
- match reference.Module.ContainingProjectModule with
- | FSharpProject referencedProject when
- referencedProject.IsOpened && (referencedProject != project) ->
- Some reference.Module
- | _ -> None)
-
- for referencedPsiModule in referencedProjectsPsiModules do
- let project = referencedPsiModule.ContainingProjectModule :?> IProject
- let outPath = project.GetOutputFilePath(referencedPsiModule.TargetFrameworkId).FullPath
- let fsProject = createFSharpProject project referencedPsiModule
- yield outPath, fsProject.ProjectOptions }
-
- let options = { fsProject.ProjectOptions with ReferencedProjects = Array.ofSeq referencedProjectsOptions }
- let fsProject = { fsProject with ProjectOptions = options }
-
- psiModulesToFsProjects.[psiModule] <- fsProject
- projects.GetOrCreateValue(project, fun () -> Dictionary()).[psiModule] <- fsProject
-
- fsProject
-
- let getOrCreateFSharpProject (file: IPsiSourceFile) =
- match tryGetFSharpProject file.PsiModule with
- | Some _ as result -> result
- | _ ->
-
- match file.GetProject() with
- | FSharpProject project ->
- use lock = locker.UsingWriteLock()
- let fsProject = createFSharpProject project file.PsiModule
- Some fsProject
-
- | _ -> None
-
- let invalidateProject project =
- let invalidatedProjects = HashSet()
- let mutable invalidated = false
-
- let rec invalidate (project: IProject) =
- logger.Info("Invalidating {0}", project)
- match tryGetValue project projects with
- | None -> ()
- | Some fsProjectsForProject ->
- for KeyValue (psiModule, fsProject) in fsProjectsForProject do
- checkerService.InvalidateFSharpProject(fsProject)
- moduleInvalidated.Fire(psiModule)
- psiModulesToFsProjects.Remove(psiModule) |> ignore
- invalidated <- true
-
- fsProjectsForProject.Clear()
-
- invalidatedProjects.Add(project) |> ignore
- // todo: keep referencing projects for invalidating removed projects
- let referencesToProject = moduleReferenceResolveStore.GetReferencesToProject(project)
- if not (referencesToProject.IsEmpty()) then
- logger.Info("Invalidating projects reverencing {0}", project)
- for reference in referencesToProject do
- match reference.GetProject() with
- | FSharpProject referencingProject when
- not (invalidatedProjects.Contains(referencingProject)) ->
- invalidate referencingProject
- | _ -> ()
- logger.Info("Done invalidating {0}", project)
- invalidate project
- invalidated
-
-
- let isScriptLike file =
- fsFileService.IsScriptLike(file) || file.PsiModule.IsMiscFilesProjectModule() || isNull (file.GetProject())
-
- let getParsingOptionsForSingleFile ([] sourceFile: IPsiSourceFile) isScript =
- { FSharpParsingOptions.Default with
- SourceFiles = [| sourceFile.GetLocation().FullPath |]
- ConditionalCompilationDefines = ImplicitDefines.scriptDefines
- IsExe = isScript }
-
- member x.ModuleInvalidated = moduleInvalidated
-
- member private x.ProcessChange(obj: ChangeEventArgs) =
- match obj.ChangeMap.GetChange(solution) with
- | null -> ()
-
- | :? ProjectReferenceChange as referenceChange ->
- use lock = locker.UsingWriteLock()
- let referenceProject = referenceChange.ProjectToModuleReference.OwnerModule
- if referenceProject.IsFSharp then
- invalidateProject referenceProject |> ignore
-
- | change ->
- if not change.IsClosingSolution then
- use lock = locker.UsingWriteLock()
- x.VisitDelta(change)
-
- override x.VisitDelta(change: ProjectModelChange) =
- match change.ProjectModelElement with
- | :? IProject as project ->
- if project.IsFSharp then
- if change.ContainsChangeType(invalidatingProjectChangeType) then
- invalidateProject project |> ignore
-
- else if change.IsSubtreeChanged then
- let mutable shouldInvalidate = false
- let changeVisitor =
- { new RecursiveProjectModelChangeDeltaVisitor() with
- member x.VisitDelta(change) =
- if change.ContainsChangeType(invalidatingChildChangeType) then
- shouldInvalidate <- true
-
- if not shouldInvalidate then
- base.VisitDelta(change) }
-
- change.Accept(changeVisitor)
- if shouldInvalidate then
- invalidateProject project |> ignore
-
- if change.IsRemoved then
- solution.GetComponent().RemoveProject(project)
-
- let mutable fsProjects = Unchecked.defaultof<_>
- match projects.TryGetValue(project, &fsProjects) with
- | false -> ()
- | _ ->
-
- logger.Info("Removing {0}", project)
-
- for KeyValue (psiModule, fsProject) in fsProjects do
- checkerService.InvalidateFSharpProject(fsProject)
- psiModulesToFsProjects.Remove(psiModule) |> ignore
-
- projects.Remove(project) |> ignore
-
- else if project.ProjectProperties.ProjectKind = ProjectKind.SOLUTION_FOLDER then
- base.VisitDelta(change)
-
- | :? ISolution -> base.VisitDelta(change)
- | _ -> ()
-
- interface IFSharpProjectOptionsProvider with
- member x.GetProjectOptions(file) =
- if fsFileService.IsScriptLike(file) then scriptOptionsProvider.GetScriptOptions(file) else
- if file.PsiModule.IsMiscFilesProjectModule() then None else
-
- getOrCreateFSharpProject file
- |> Option.map (fun fsProject -> fsProject.ProjectOptions)
-
- member x.HasPairFile(file) =
- if isScriptLike file then false else
-
- match getOrCreateFSharpProject file with
- | Some fsProject -> fsProject.ImplFilesWithSigs.Contains(file.GetLocation())
- | _ -> false
-
- member x.GetParsingOptions(sourceFile) =
- if isNull sourceFile then sandboxParsingOptions else
- if isScriptLike sourceFile then getParsingOptionsForSingleFile sourceFile true else
-
- match getOrCreateFSharpProject sourceFile with
- | Some fsProject -> fsProject.ParsingOptions
- | _ -> getParsingOptionsForSingleFile sourceFile false
-
- member x.GetFileIndex(sourceFile) =
- if isScriptLike sourceFile then 0 else
-
- getOrCreateFSharpProject sourceFile
- |> Option.bind (fun fsProject ->
- let path = sourceFile.GetLocation()
- tryGetValue path fsProject.FileIndices)
- |> Option.defaultWith (fun _ -> -1)
-
- member x.ModuleInvalidated = x.ModuleInvalidated :> _
-
- member x.Invalidate(project: IProject) =
- invalidateProject project
-
- member x.HasFSharpProjects = not (projects.IsEmpty())
-
-[]
-type FSharpScriptProjectOptionsProvider
- (lifetime, logger: ILogger, checkerService: FSharpCheckerService, scriptOptions: FSharpScriptOptionsProvider) =
-
- let getScriptOptionsLock = obj()
- let defaultFlags = [| "--warnon:1182" |]
-
- let getOtherFlags languageVersion =
- if languageVersion = FSharpLanguageVersion.Default then defaultFlags else
-
- let languageVersionOptionArg = FSharpLanguageVersion.toCompilerArg languageVersion
- Array.append defaultFlags [| languageVersionOptionArg |]
-
- let otherFlags =
- lazy
- let languageVersion = scriptOptions.LanguageVersion
- let flags = new Property<_>("FSharpScriptOtherFlags", getOtherFlags languageVersion.Value)
- IPropertyEx.FlowInto(languageVersion, lifetime, flags, fun version -> getOtherFlags version)
- flags
-
- let fixScriptOptions options =
- { options with OtherOptions = FSharpCoreFix.ensureCorrectFSharpCore options.OtherOptions }
-
- let getOptions (path: FileSystemPath) source =
- let path = path.FullPath
- let source = SourceText.ofString source
- lock getScriptOptionsLock (fun _ ->
- let getScriptOptionsAsync =
- checkerService.Checker.GetProjectOptionsFromScript(path, source, otherFlags = otherFlags.Value.Value)
- try
- let options, errors = getScriptOptionsAsync.RunAsTask()
- if not errors.IsEmpty then
- logger.Warn("Script options for {0}: {1}", path, concatErrors errors)
- let options = fixScriptOptions options
- Some options
- with
- | OperationCanceled -> reraise()
- | exn ->
- logger.Warn("Error while getting script options for {0}: {1}", path, exn.Message)
- logger.LogExceptionSilently(exn)
- None)
-
- interface IFSharpScriptProjectOptionsProvider with
- member x.GetScriptOptions(path: FileSystemPath, source) =
- getOptions path source
-
- member x.GetScriptOptions(file: IPsiSourceFile) =
- let path = file.GetLocation()
- let source = file.Document.GetText()
- getOptions path source
-
-
-[]
-type OutputAssemblyChangeInvalidator(lifetime, outputAssemblies: OutputAssemblies, daemon: IDaemon, psiFiles: IPsiFiles,
- provider: IFSharpProjectOptionsProvider) =
- do
- outputAssemblies.ProjectOutputAssembliesChanged.Advise(lifetime, fun (project: IProject) ->
- if not provider.HasFSharpProjects || project.IsFSharp then () else
-
- if provider.Invalidate(project) then
- psiFiles.IncrementModificationTimestamp(null)
- daemon.Invalidate())
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Checker/FcsProjectBuilder.fs b/ReSharper.FSharp/src/FSharp.Common/src/Checker/FcsProjectBuilder.fs
new file mode 100644
index 0000000000..4251f86f10
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Checker/FcsProjectBuilder.fs
@@ -0,0 +1,270 @@
+namespace JetBrains.ReSharper.Plugins.FSharp.Checker
+
+open System
+open System.Collections.Generic
+open FSharp.Compiler.SourceCodeServices
+open JetBrains.Application
+open JetBrains.Diagnostics
+open JetBrains.ProjectModel
+open JetBrains.ProjectModel.ProjectsHost
+open JetBrains.ProjectModel.ProjectsHost.MsBuild.Strategies
+open JetBrains.ProjectModel.Properties
+open JetBrains.ProjectModel.Properties.Managed
+open JetBrains.ReSharper.Plugins.FSharp.ProjectModel
+open JetBrains.ReSharper.Plugins.FSharp.ProjectModel.ProjectProperties
+open JetBrains.ReSharper.Plugins.FSharp.ProjectModel.ProjectItems.ItemsContainer
+open JetBrains.ReSharper.Plugins.FSharp.Util
+open JetBrains.ReSharper.Psi
+open JetBrains.ReSharper.Psi.Modules
+open JetBrains.Util
+open JetBrains.Util.Dotnet.TargetFrameworkIds
+
+type FcsProject =
+ { OutputPath: FileSystemPath
+ FileIndices: Dictionary
+ ProjectOptions: FSharpProjectOptions
+ ParsingOptions: FSharpParsingOptions
+ ImplementationFilesWithSignatures: ISet }
+
+ member x.IsKnownFile(sourceFile: IPsiSourceFile) =
+ x.FileIndices.ContainsKey(sourceFile.GetLocation())
+
+
+type ReferencedModule =
+ { ReferencedPath: FileSystemPath
+ ReferencingModules: HashSet }
+
+ static member Create(psiModule: IPsiModule) =
+ { ReferencedPath = getOutputPath psiModule
+ ReferencingModules = HashSet() }
+
+
+module FSharpProperties =
+ let [] TargetProfile = "TargetProfile"
+ let [] BaseAddress = "BaseAddress"
+ let [] OtherFlags = "OtherFlags"
+ let [] NoWarn = "NoWarn"
+ let [] WarnAsError = "WarnAsError"
+ let [] FscToolPath = "FscToolPath"
+ let [] LangVersion = "LangVersion"
+
+
+[]
+type FSharpProjectPropertiesRequest() =
+ let properties =
+ [| FSharpProperties.TargetProfile
+ FSharpProperties.BaseAddress
+ FSharpProperties.OtherFlags
+ FSharpProperties.NoWarn
+ FSharpProperties.WarnAsError
+ FSharpProperties.FscToolPath
+ FSharpProperties.LangVersion |]
+
+ interface IProjectPropertiesRequest with
+ member x.RequestedProperties = properties :> _
+
+
+[]
+type FSharpTargetsProjectLoadModificator() =
+ let fsTargets =
+ [| "GenerateCode"
+ "GenerateFSharpInternalsVisibleToFile"
+ "GenerateAssemblyFileVersionTask"
+ "ImplicitlyExpandNETStandardFacades" |]
+
+ interface MsBuildLegacyLoadStrategy.IModificator with
+ member x.IsApplicable(mark) =
+ match mark with
+ | FSharpProjectMark -> true
+ | _ -> false
+
+ member x.Modify(targets) =
+ targets.AddRange(fsTargets)
+
+[]
+module ProjectOptions =
+ let sandboxParsingOptions =
+ { FSharpParsingOptions.Default with SourceFiles = [| "Sandbox.fs" |] }
+
+ []
+ module ImplicitDefines =
+ let sourceDefines = [ "EDITING"; "COMPILED" ]
+ let scriptDefines = [ "EDITING"; "INTERACTIVE" ]
+
+ let getImplicitDefines isScript =
+ if isScript then scriptDefines else sourceDefines
+
+
+[]
+type FcsProjectBuilder(checkerService: FSharpCheckerService, itemsContainer: IFSharpItemsContainer, logger: ILogger) =
+
+ let itemsDelimiters = [| ';'; ','; ' ' |]
+
+ let defaultOptions =
+ [| "--noframework"
+ "--debug:full"
+ "--debug+"
+ "--optimize-"
+ "--tailcalls-"
+ "--fullpaths"
+ "--flaterrors"
+ "--highentropyva+"
+ "--noconditionalerasure" |]
+
+ let unusedValuesWarns =
+ [| "--warnon:1182" |]
+
+ let splitAndTrim (delimiters: char[]) (s: string) =
+ if isNull s then EmptyArray.Instance else
+ s.Split(delimiters, StringSplitOptions.RemoveEmptyEntries)
+
+ let getReferences psiModule =
+ getReferencedModules psiModule
+ |> Seq.map getModuleFullPath
+ |> Seq.map (fun r -> "-r:" + r)
+
+ let getOutputType (outputType: ProjectOutputType) =
+ match outputType with
+ | ProjectOutputType.CONSOLE_EXE -> "exe"
+ | ProjectOutputType.WIN_EXE -> "winexe"
+ | ProjectOutputType.MODULE -> "module"
+ | _ -> "library"
+
+ abstract GetProjectItemsPaths:
+ project: IProject * targetFrameworkId: TargetFrameworkId -> (FileSystemPath * BuildAction)[]
+
+ default x.GetProjectItemsPaths(project, targetFrameworkId) =
+ let projectMark = project.GetProjectMark().NotNull()
+ itemsContainer.GetProjectItemsPaths(projectMark, targetFrameworkId)
+
+ member x.GetProjectFilesAndResources(project: IProject, targetFrameworkId) =
+ let sourceFiles = List()
+ let resources = List()
+
+ let sigFiles = HashSet()
+ let implsWithSigs = HashSet()
+
+ let projectItems = x.GetProjectItemsPaths(project, targetFrameworkId)
+
+ for path, buildAction in projectItems do
+ match buildAction with
+ | SourceFile ->
+ sourceFiles.Add(path) |> ignore
+ let fileName = path.NameWithoutExtension
+ match path.ExtensionNoDot with
+ | SigExtension -> sigFiles.Add(fileName) |> ignore
+ | ImplExtension when sigFiles.Contains(fileName) -> implsWithSigs.add(path)
+ | _ -> ()
+
+ | Resource -> resources.Add(path) |> ignore
+ | _ -> ()
+
+ let resources: IList<_> = if resources.IsEmpty() then EmptyList.InstanceList else resources :> _
+ let implsWithSigs: ISet<_> = if implsWithSigs.IsEmpty() then EmptySet.Instance :> _ else implsWithSigs :> _
+
+ sourceFiles.ToArray(), implsWithSigs, resources
+
+ member x.BuildFcsProject(psiModule: IPsiModule, project: IProject): FcsProject =
+ logger.Verbose("Creating FcsProject: {0}", psiModule)
+
+ let targetFrameworkId = psiModule.TargetFrameworkId
+ let projectProperties = project.ProjectProperties
+
+ let otherOptions = List()
+
+ let outPath = project.GetOutputFilePath(targetFrameworkId)
+ if not outPath.IsEmpty then
+ otherOptions.Add("--out:" + outPath.FullPath)
+
+ otherOptions.AddRange(defaultOptions)
+ otherOptions.AddRange(unusedValuesWarns)
+ otherOptions.AddRange(getReferences psiModule)
+
+ match projectProperties.ActiveConfigurations.TryGetConfiguration(targetFrameworkId) with
+ | :? IManagedProjectConfiguration as cfg ->
+ let definedConstants = splitAndTrim itemsDelimiters cfg.DefineConstants
+ otherOptions.AddRange(definedConstants |> Seq.map (fun c -> "--define:" + c))
+
+ otherOptions.Add("--target:" + getOutputType cfg.OutputType)
+
+ otherOptions.Add(sprintf "--warn:%d" cfg.WarningLevel)
+
+ if cfg.TreatWarningsAsErrors then
+ otherOptions.Add("--warnaserror")
+
+ let doc = cfg.DocumentationFile
+ if not (doc.IsNullOrWhitespace()) then otherOptions.Add("--doc:" + doc)
+
+ let props = cfg.PropertiesCollection
+
+ let getOption f p =
+ match props.TryGetValue(p) with
+ | true, v when not (v.IsNullOrWhitespace()) -> Some ("--" + p.ToLower() + ":" + f v)
+ | _ -> None
+
+ [ FSharpProperties.TargetProfile; FSharpProperties.BaseAddress; FSharpProperties.LangVersion ]
+ |> List.choose (getOption id)
+ |> otherOptions.AddRange
+
+ [ FSharpProperties.NoWarn; FSharpProperties.WarnAsError ]
+ |> List.choose (getOption (fun v -> (splitAndTrim itemsDelimiters v).Join(",")))
+ |> otherOptions.AddRange
+
+ match props.TryGetValue(FSharpProperties.OtherFlags) with
+ | true, otherFlags when not (otherFlags.IsNullOrWhitespace()) -> splitAndTrim [| ' ' |] otherFlags
+ | _ -> EmptyArray.Instance
+ |> otherOptions.AddRange
+ | _ -> ()
+
+ let filePaths, implsWithSig, resources = x.GetProjectFilesAndResources(project, targetFrameworkId)
+
+ otherOptions.AddRange(resources |> Seq.map (fun (r: FileSystemPath) -> "--resource:" + r.FullPath))
+ let fileIndices = Dictionary()
+ Array.iteri (fun i p -> fileIndices.[p] <- i) filePaths
+
+ let projectOptions =
+ { ProjectFileName = sprintf "%O.%O.fsproj" project.ProjectFileLocation targetFrameworkId
+ ProjectId = None
+ SourceFiles = Array.map (fun (p: FileSystemPath ) -> p.FullPath) filePaths
+ OtherOptions = otherOptions.ToArray()
+ ReferencedProjects = Array.empty
+ IsIncompleteTypeCheckEnvironment = false
+ UseScriptResolutionRules = false
+ LoadTime = DateTime.Now
+ OriginalLoadReferences = List.empty
+ UnresolvedReferences = None
+ ExtraProjectInfo = None
+ Stamp = None }
+
+ let hasFSharpCoreReference options =
+ options.OtherOptions
+ |> Seq.exists (fun s ->
+ s.StartsWith("-r:", StringComparison.Ordinal) &&
+ s.EndsWith("FSharp.Core.dll", StringComparison.Ordinal))
+
+ let shouldAddFSharpCore options =
+ not (hasFSharpCoreReference options || options.OtherOptions |> Array.contains "--compiling-fslib")
+
+ let options =
+ if shouldAddFSharpCore projectOptions then
+ { projectOptions with
+ OtherOptions = FSharpCoreFix.ensureCorrectFSharpCore projectOptions.OtherOptions }
+ else projectOptions
+
+ let parsingOptions, errors =
+ checkerService.Checker.GetParsingOptionsFromCommandLineArgs(List.ofArray options.OtherOptions)
+
+ let defines = ImplicitDefines.sourceDefines @ parsingOptions.ConditionalCompilationDefines
+
+ let parsingOptions = { parsingOptions with
+ SourceFiles = options.SourceFiles
+ ConditionalCompilationDefines = defines }
+
+ if not errors.IsEmpty then
+ logger.Warn("Getting parsing options: {0}", concatErrors errors)
+
+ { OutputPath = outPath
+ ProjectOptions = projectOptions
+ ParsingOptions = parsingOptions
+ FileIndices = fileIndices
+ ImplementationFilesWithSignatures = implsWithSig }
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Checker/FcsProjectProvider.fs b/ReSharper.FSharp/src/FSharp.Common/src/Checker/FcsProjectProvider.fs
new file mode 100644
index 0000000000..5af5a67dd3
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Checker/FcsProjectProvider.fs
@@ -0,0 +1,278 @@
+namespace JetBrains.ReSharper.Plugins.FSharp.Checker
+
+open System.Collections.Generic
+open FSharp.Compiler.SourceCodeServices
+open JetBrains.Annotations
+open JetBrains.Application.Threading
+open JetBrains.Application.changes
+open JetBrains.DataFlow
+open JetBrains.Lifetimes
+open JetBrains.ProjectModel
+open JetBrains.ProjectModel.Build
+open JetBrains.ProjectModel.Tasks
+open JetBrains.ReSharper.Feature.Services.Daemon
+open JetBrains.ReSharper.Plugins.FSharp.ProjectModel.Scripts
+open JetBrains.ReSharper.Plugins.FSharp.Checker
+open JetBrains.ReSharper.Plugins.FSharp.ProjectModel
+open JetBrains.ReSharper.Plugins.FSharp.ProjectModel.ProjectProperties
+open JetBrains.ReSharper.Plugins.FSharp.Util
+open JetBrains.ReSharper.Psi
+open JetBrains.ReSharper.Psi.Files
+open JetBrains.ReSharper.Psi.Modules
+open JetBrains.Threading
+open JetBrains.Util
+
+
+[]
+module FcsProjectProvider =
+ let isProjectModule (psiModule: IPsiModule) =
+ psiModule :? IProjectPsiModule
+
+ let getModuleProject (psiModule: IPsiModule) =
+ psiModule.ContainingProjectModule.As()
+
+ let isFSharpProject (projectModelModule: IModule) =
+ match projectModelModule with
+ | :? IProject as project -> project.IsFSharp // todo: check `isOpened`?
+ | _ -> false
+
+ let isFSharpProjectModule (psiModule: IPsiModule) =
+ psiModule.IsValid() && isFSharpProject psiModule.ContainingProjectModule
+
+
+[]
+type FcsProjectProvider
+ (lifetime: Lifetime, solution: ISolution, changeManager: ChangeManager, checkerService: FSharpCheckerService,
+ fcsProjectBuilder: FcsProjectBuilder, scriptFcsProjectProvider: IScriptFcsProjectProvider,
+ scheduler: ISolutionLoadTasksScheduler, fsFileService: IFSharpFileService, psiModules: IPsiModules,
+ locks: IShellLocks, logger: ILogger) as this =
+ inherit RecursiveProjectModelChangeDeltaVisitor()
+
+ let locker = JetFastSemiReenterableRWLock()
+
+ let fcsProjects = Dictionary()
+ let referencedModules = Dictionary()
+
+ // todo: keep standalone projects
+// let fcsStandaloneProjects = Dictionary() // todo
+
+ let dirtyModules = HashSet()
+ let fcsProjectInvalidated = new Signal(lifetime, "FcsProjectInvalidated")
+
+ let getReferencingModules (psiModule: IPsiModule) =
+ match tryGetValue psiModule referencedModules with
+ | None -> Seq.empty
+ | Some referencedModule -> referencedModule.ReferencingModules :> _
+
+ let rec invalidateFcsProject (psiModule: IPsiModule) =
+ match tryGetValue psiModule fcsProjects with
+ | None -> ()
+ | Some fcsProject ->
+
+ logger.Trace("Start invalidating project: {0}", psiModule)
+ fcsProjectInvalidated.Fire(psiModule)
+
+ // Invalidate FCS projects for the old project options, before creating new ones.
+ // todo: try to not invalidate FCS project if a project is not changed actually?
+ checkerService.InvalidateFcsProject(fcsProject.ProjectOptions)
+ getReferencingModules psiModule |> Seq.iter invalidateFcsProject
+
+ referencedModules.Remove(psiModule) |> ignore
+ fcsProjects.Remove(psiModule) |> ignore
+ dirtyModules.Remove(psiModule) |> ignore
+
+// if not (psiModule.IsValid()) then // todo: keep change type in dirtyModules?
+// solution.GetComponent().RemoveProject(project)
+
+ // todo: remove removed psiModules? (don't we remove them anyway?) (standalone projects only?)
+ // todo: invalidate resolved symbol cache
+ // todo: invalidate fcsProjects on request from resolved symbols cache
+ logger.Trace("Done invalidating project: {0}", psiModule)
+
+ let processDirtyFcsProjects () =
+ use lock = locker.UsingWriteLock()
+ if dirtyModules.IsEmpty() then () else
+
+ logger.Verbose("Start invalidating dirty projects")
+ let modulesToInvalidate = List(dirtyModules)
+ for psiModule in modulesToInvalidate do
+ invalidateFcsProject psiModule
+ logger.Verbose("Done invalidating dirty projects")
+
+ do
+ // Start listening for the changes after project model is updated.
+ scheduler.EnqueueTask(SolutionLoadTask("FSharpProjectOptionsProvider", SolutionLoadTaskKinds.StartPsi, fun _ ->
+ changeManager.Changed2.Advise(lifetime, this.ProcessChange)))
+
+ checkerService.FcsProjectProvider <- this
+ lifetime.OnTermination(fun _ -> checkerService.FcsProjectProvider <- Unchecked.defaultof<_>) |> ignore
+
+ let tryGetFcsProject (psiModule: IPsiModule): FcsProject option =
+ use lock = locker.UsingReadLock()
+ tryGetValue psiModule fcsProjects
+
+ let rec createFcsProject (project: IProject) (psiModule: IPsiModule): FcsProject =
+ match tryGetValue psiModule fcsProjects with
+ | Some fcsProject -> fcsProject
+ | _ ->
+
+ let fcsProject = fcsProjectBuilder.BuildFcsProject(psiModule, project)
+
+ let referencedProjectPsiModules =
+ getReferencedModules psiModule
+ |> Seq.filter (fun psiModule ->
+ psiModule.IsValid() && isProjectModule psiModule && psiModule.ContainingProjectModule != project)
+ |> List
+
+ let referencedFcsProjects =
+ referencedProjectPsiModules
+ |> Seq.filter isFSharpProjectModule
+ |> Seq.map (fun referencedPsiModule ->
+ let referencedProject = referencedPsiModule.ContainingProjectModule :?> _
+ let referencedFcsProject = createFcsProject referencedProject referencedPsiModule
+ referencedFcsProject.OutputPath.FullPath, referencedFcsProject.ProjectOptions)
+ |> Seq.toArray
+
+ let fcsProjectOptions = { fcsProject.ProjectOptions with ReferencedProjects = referencedFcsProjects }
+ let fcsProject = { fcsProject with ProjectOptions = fcsProjectOptions }
+
+ fcsProjects.[psiModule] <- fcsProject
+
+ for referencedPsiModule in referencedProjectPsiModules do
+ let referencedModule = referencedModules.GetOrCreateValue(referencedPsiModule, ReferencedModule.Create)
+ referencedModule.ReferencingModules.Add(psiModule) |> ignore
+
+ fcsProject
+
+ let getOrCreateFcsProject (psiModule: IPsiModule): FcsProject option =
+ match tryGetFcsProject psiModule with
+ | Some _ as fcsProject -> fcsProject
+ | _ ->
+
+ match getModuleProject psiModule with
+ | FSharpProject project ->
+ use lock = locker.UsingWriteLock()
+ let fcsProject = createFcsProject project psiModule
+ Some fcsProject
+
+ | _ -> None
+
+ let getOrCreateFcsProjectForFile (sourceFile: IPsiSourceFile) =
+ getOrCreateFcsProject sourceFile.PsiModule
+
+ let isScriptLike file =
+ fsFileService.IsScriptLike(file) || file.PsiModule.IsMiscFilesProjectModule() || isNull (file.GetProject())
+
+ let getParsingOptionsForSingleFile ([] sourceFile: IPsiSourceFile) isScript =
+ { FSharpParsingOptions.Default with
+ SourceFiles = [| sourceFile.GetLocation().FullPath |]
+ ConditionalCompilationDefines = ImplicitDefines.scriptDefines
+ IsExe = isScript }
+
+ let getProjectOptions (sourceFile: IPsiSourceFile) =
+ let psiModule = sourceFile.PsiModule
+
+ // Scripts belong to separate psi modules even when are in projects, project/misc module check is enough.
+ if isProjectModule psiModule && not (psiModule.IsMiscFilesProjectModule()) then
+ match getOrCreateFcsProject psiModule with
+ | Some fcsProject when fcsProject.IsKnownFile(sourceFile) -> Some fcsProject.ProjectOptions
+ | _ -> None
+
+ elif psiModule :? FSharpScriptPsiModule then
+ scriptFcsProjectProvider.GetScriptOptions(sourceFile)
+
+ else
+ None
+
+ member x.FcsProjectInvalidated = fcsProjectInvalidated
+
+ member private x.ProcessChange(obj: ChangeEventArgs) =
+ if not (solution.IsValid()) then () else
+
+ match obj.ChangeMap.GetChange(psiModules) with
+ | null -> ()
+ | change ->
+
+ // todo: check if there's a change for a project module when referenced assembly module is changed?
+ use lock = locker.UsingWriteLock()
+
+ for moduleChange in change.ModuleChanges do
+ // todo: ignore `PsiModuleChange.ChangeType.Invalidated`?
+ if moduleChange.Type <> PsiModuleChange.ChangeType.Added then
+ dirtyModules.Add(moduleChange.Item) |> ignore
+
+ for fileChange in change.FileChanges do
+ let changeType = fileChange.Type
+ if changeType = PsiModuleChange.ChangeType.Added || changeType = PsiModuleChange.ChangeType.Removed then
+ let psiModule = fileChange.Item.PsiModule
+ dirtyModules.Add(psiModule) |> ignore
+
+ interface IFcsProjectProvider with
+ member x.GetProjectOptions(sourceFile) =
+ locks.AssertReadAccessAllowed()
+ processDirtyFcsProjects ()
+
+ getProjectOptions sourceFile
+
+ member x.HasPairFile(sourceFile) =
+ locks.AssertReadAccessAllowed()
+ processDirtyFcsProjects ()
+
+ if isScriptLike sourceFile then false else
+
+ match getOrCreateFcsProjectForFile sourceFile with
+ | Some fsProject -> fsProject.ImplementationFilesWithSignatures.Contains(sourceFile.GetLocation())
+ | _ -> false
+
+ member x.GetParsingOptions(sourceFile) =
+ locks.AssertReadAccessAllowed()
+ processDirtyFcsProjects ()
+
+ if isNull sourceFile then sandboxParsingOptions else
+ if isScriptLike sourceFile then getParsingOptionsForSingleFile sourceFile true else
+
+ match getOrCreateFcsProjectForFile sourceFile with
+ | Some fsProject -> fsProject.ParsingOptions
+ | _ -> getParsingOptionsForSingleFile sourceFile false
+
+ member x.GetFileIndex(sourceFile) =
+ locks.AssertReadAccessAllowed()
+ processDirtyFcsProjects ()
+
+ if isScriptLike sourceFile then 0 else
+
+ getOrCreateFcsProjectForFile sourceFile
+ |> Option.bind (fun fsProject ->
+ let path = sourceFile.GetLocation()
+ tryGetValue path fsProject.FileIndices)
+ |> Option.defaultWith (fun _ -> -1)
+
+ member x.ModuleInvalidated = x.FcsProjectInvalidated :> _
+
+ member x.InvalidateReferencesToProject(project: IProject) =
+ (false, project.GetPsiModules()) ||> Seq.fold (fun invalidated psiModule ->
+ tryGetValue psiModule referencedModules
+ |> Option.map (fun referencedModule ->
+ (invalidated, referencedModule.ReferencingModules)
+ ||> Seq.fold (fun invalidated psiModule -> dirtyModules.Add(psiModule) || invalidated))
+ |> Option.defaultValue invalidated)
+
+ member x.HasFcsProjects = not (fcsProjects.IsEmpty())
+
+
+/// Invalidates psi caches when a non-F# project is built and FCS cached resolve results become stale
+[]
+type OutputAssemblyChangeInvalidator
+ (lifetime: Lifetime, outputAssemblies: OutputAssemblies, daemon: IDaemon, psiFiles: IPsiFiles,
+ fcsProjectProvider: IFcsProjectProvider, scheduler: ISolutionLoadTasksScheduler) =
+ do
+ scheduler.EnqueueTask(SolutionLoadTask("FSharpProjectOptionsProvider", SolutionLoadTaskKinds.StartPsi, fun _ ->
+ // todo: track file system changes instead? This currently may be triggered on a project model change too.
+ outputAssemblies.ProjectOutputAssembliesChanged.Advise(lifetime, fun (project: IProject) ->
+ if not fcsProjectProvider.HasFcsProjects || project.IsFSharp then () else
+
+ if fcsProjectProvider.InvalidateReferencesToProject(project) then
+ psiFiles.IncrementModificationTimestamp(null) // Drop cached values.
+ daemon.Invalidate() // Request files re-highlighting.
+ )
+ ))
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Checker/ScriptFcsProjectProvider.fs b/ReSharper.FSharp/src/FSharp.Common/src/Checker/ScriptFcsProjectProvider.fs
new file mode 100644
index 0000000000..6dfb3bfe43
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Checker/ScriptFcsProjectProvider.fs
@@ -0,0 +1,72 @@
+namespace JetBrains.ReSharper.Plugins.FSharp.Checker
+
+open FSharp.Compiler.SourceCodeServices
+open FSharp.Compiler.Text
+open JetBrains.DataFlow
+open JetBrains.ProjectModel
+open JetBrains.ReSharper.Plugins.FSharp
+open JetBrains.ReSharper.Plugins.FSharp.ProjectModel
+open JetBrains.ReSharper.Plugins.FSharp.Settings
+open JetBrains.ReSharper.Plugins.FSharp.Util
+open JetBrains.ReSharper.Psi
+open JetBrains.Util
+
+[]
+type ScriptFcsProjectProvider
+ (lifetime, logger: ILogger, checkerService: FSharpCheckerService, scriptSettings: FSharpScriptSettingsProvider) =
+
+ let getScriptOptionsLock = obj()
+
+ let defaultFlags =
+ [| "--warnon:1182"
+
+ if PlatformUtil.IsRunningOnCore then
+ "--targetprofile:netcore"
+ "--simpleresolution" |]
+
+ let getOtherFlags languageVersion =
+ if languageVersion = FSharpLanguageVersion.Default then defaultFlags else
+
+ let languageVersionOptionArg = FSharpLanguageVersion.toCompilerArg languageVersion
+ Array.append defaultFlags [| languageVersionOptionArg |]
+
+ let otherFlags =
+ lazy
+ let languageVersion = scriptSettings.LanguageVersion
+ let flags = new Property<_>("FSharpScriptOtherFlags", getOtherFlags languageVersion.Value)
+ IPropertyEx.FlowInto(languageVersion, lifetime, flags, fun version -> getOtherFlags version)
+ flags
+
+ let fixScriptOptions options =
+ { options with OtherOptions = FSharpCoreFix.ensureCorrectFSharpCore options.OtherOptions }
+
+ let getOptions (path: FileSystemPath) source =
+ let path = path.FullPath
+ let source = SourceText.ofString source
+ lock getScriptOptionsLock (fun _ ->
+ let getScriptOptionsAsync =
+ checkerService.Checker.GetProjectOptionsFromScript(
+ path, source,
+ otherFlags = otherFlags.Value.Value,
+ assumeDotNetFramework = not PlatformUtil.IsRunningOnCore)
+ try
+ let options, errors = getScriptOptionsAsync.RunAsTask()
+ if not errors.IsEmpty then
+ logger.Warn("Script options for {0}: {1}", path, concatErrors errors)
+ let options = fixScriptOptions options
+ Some options
+ with
+ | OperationCanceled -> reraise()
+ | exn ->
+ logger.Warn("Error while getting script options for {0}: {1}", path, exn.Message)
+ logger.LogExceptionSilently(exn)
+ None)
+
+ interface IScriptFcsProjectProvider with
+ member x.GetScriptOptions(path: FileSystemPath, source) =
+ getOptions path source
+
+ member x.GetScriptOptions(file: IPsiSourceFile) =
+ let path = file.GetLocation()
+ let source = file.Document.GetText()
+ getOptions path source
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/FcsReactorMonitor.fs b/ReSharper.FSharp/src/FSharp.Common/src/FcsReactorMonitor.fs
new file mode 100644
index 0000000000..b2d5f18eae
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Common/src/FcsReactorMonitor.fs
@@ -0,0 +1,163 @@
+namespace JetBrains.ReSharper.Plugins.FSharp
+
+open System
+open System.Collections.Concurrent
+open System.Diagnostics
+open System.IO
+open System.Text.RegularExpressions
+open System.Threading
+open JetBrains.Application.Threading
+open JetBrains.DataFlow
+open JetBrains.Diagnostics
+open JetBrains.Lifetimes
+open JetBrains.Platform.RdFramework.Util
+open JetBrains.ProjectModel
+open JetBrains.ReSharper.Plugins.FSharp.Checker
+open JetBrains.ReSharper.Host.Features.BackgroundTasks
+open JetBrains.Util
+
+[]
+module MonitoredReactorOperation =
+ let empty opName =
+ { new IMonitoredReactorOperation with
+ override __.Dispose () = ()
+ override __.OperationName = opName
+ }
+
+
+[]
+type FcsReactorMonitor
+ (lifetime: Lifetime, backgroundTaskHost: RiderBackgroundTaskHost, threading: IThreading,
+ checkerService: FSharpCheckerService, logger: ILogger, solution: ISolution) as this =
+
+ inherit TraceListener("FcsReactorMonitor")
+
+ /// How long after the reactor becoming busy that the background task should be shown
+ let showDelay = new Property("showDelay")
+
+ let mutable lastOperationId = 0L
+ let operations = ConcurrentDictionary()
+
+ /// How long after the reactor becoming free that the background task should be hidden
+ let hideDelay = TimeSpan.FromSeconds 0.5
+
+ /// How long an operation must be running for before a stack trace of the enqueuing thread is dumped
+ let dumpStackDelay = TimeSpan.FromSeconds 10.0
+
+ let mutable slowOperationTimer = null
+ let isReactorBusy = new Property("isReactorBusy")
+
+ let taskHeader = new Property("taskHeader")
+ let taskDescription = new Property("taskDescription")
+ let showBackgroundTask = new Property("showBackgroundTask")
+
+ let opStartRegex = Regex(@"--> (.+) \((.+)\), remaining \d+$", RegexOptions.Compiled)
+
+ let createNewTask (activeLifetime: Lifetime) =
+ let task =
+ RiderBackgroundTaskBuilder.Create()
+ .WithTitle("F# Compiler Service is busy...")
+ .WithHeader(taskHeader)
+ .WithDescription(taskDescription)
+ .AsIndeterminate()
+ .AsNonCancelable()
+ .Build()
+
+ // Only show the background task after we've been busy for some time
+ threading.QueueAt(
+ activeLifetime,
+ "FcsReactorMonitor.AddNewTask",
+ showDelay.Value,
+ fun () -> backgroundTaskHost.AddNewTask(activeLifetime, task))
+
+ /// Called when a FCS operation starts.
+ /// Always called from the current FCS reactor thread.
+ let onOperationStart (opName: string) (opArg: string) =
+ // Try to parse the operation ID from the front of the opName
+ let operationId, opName =
+ let endIndex = opName.IndexOf '}'
+ if endIndex = -1 || opName.[0] <> '{' then None, opName else
+
+ match Int64.TryParse(opName.Substring(1, endIndex - 1)) with
+ | false, _ -> None, opName
+ | true, operationId ->
+
+ let opName = opName.Substring(endIndex + 1)
+
+ match operations.TryGetValue operationId with
+ | null -> None, opName
+ | stackTrace ->
+
+ // Warn if the operation still hasn't finished in a few seconds
+ slowOperationTimer <-
+ let callback _ = logger.Warn("Operation '{0}' ({1}) is taking a long time. Stack trace:\n{2}", opName, opArg, stackTrace)
+ new Timer(callback, null, dumpStackDelay, Timeout.InfiniteTimeSpan)
+
+ Some operationId, opName
+
+ taskHeader.SetValue opName |> ignore
+
+ let opArg = if Path.IsPathRooted opArg then Path.GetFileName opArg else opArg
+ match operationId with
+ | None -> taskDescription.SetValue(opArg) |> ignore
+ | Some operationId -> taskDescription.SetValue(sprintf "%s (operation #%d)" opArg operationId) |> ignore
+
+ isReactorBusy.SetValue true |> ignore
+
+ /// Called when a FCS operation ends.
+ /// Always called from the current FCS reactor thread.
+ let onOperationEnd () =
+ // Cancel slow operation timer - the operation is now finished
+ if isNotNull slowOperationTimer then
+ slowOperationTimer.Dispose()
+ slowOperationTimer <- null
+
+ isReactorBusy.SetValue false |> ignore
+
+ let onTrace (message: string) =
+ // todo: add and use a proper reactor event interface in FCS instead of matching trace messages
+
+ if message.Contains "<--" then
+ onOperationEnd ()
+ else
+ let opStartMatch = opStartRegex.Match(message)
+ if opStartMatch.Success then
+ onOperationStart (opStartMatch.Groups.[1].Value) (opStartMatch.Groups.[2].Value)
+
+ do
+ solution.RdFSharpModel().FcsBusyDelayMs.FlowInto(lifetime, showDelay,
+ fun ms -> TimeSpan.FromMilliseconds(float ms))
+
+ showBackgroundTask.WhenTrue(lifetime, Action<_> createNewTask)
+
+ isReactorBusy.WhenTrue(lifetime, fun lt -> showBackgroundTask.SetValue true |> ignore)
+
+ isReactorBusy.WhenFalse(lifetime, fun lt ->
+ threading.QueueAt(lt, "FcsReactorMonitor.HideTask", hideDelay, fun () ->
+ showBackgroundTask.SetValue false |> ignore))
+
+ // Start listening for trace events
+ checkerService.FcsReactorMonitor <- this
+ Trace.Listeners.Add(this) |> ignore
+ lifetime.OnTermination(fun () ->
+ checkerService.FcsReactorMonitor <- Unchecked.defaultof<_>
+ Trace.Listeners.Remove(this)) |> ignore
+
+ override x.Write(_: string) = ()
+ override x.WriteLine(message: string) = if message.StartsWith "Reactor:" then onTrace message
+
+ interface IFcsReactorMonitor with
+ override __.MonitorOperation opName =
+ // Only monitor operations when trace logging is enabled
+ if not (logger.IsEnabled LoggingLevel.TRACE) then
+ MonitoredReactorOperation.empty opName
+ else
+
+ let stackTrace = StackTrace(1, true)
+ let operationId = Interlocked.Increment &lastOperationId
+ operations.TryAdd(operationId, stackTrace) |> ignore
+
+ { new IMonitoredReactorOperation with
+ override __.Dispose () = match operations.TryRemove operationId with _ -> ()
+ override __.OperationName = sprintf "{%d}%s" operationId opName
+ }
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/ProjectModel/FSharpProjectModelUtil.fs b/ReSharper.FSharp/src/FSharp.Common/src/ProjectModel/FSharpProjectModelUtil.fs
index 574f7c7ffe..3ab761252f 100644
--- a/ReSharper.FSharp/src/FSharp.Common/src/ProjectModel/FSharpProjectModelUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Common/src/ProjectModel/FSharpProjectModelUtil.fs
@@ -1,33 +1,48 @@
[]
module JetBrains.ReSharper.Plugins.FSharp.ProjectModel.FSharpProjectModelUtil
-open System.Collections.Generic
open JetBrains.ProjectModel
-open JetBrains.ProjectModel.Assemblies.Impl
open JetBrains.ReSharper.Psi.Modules
-let getReferencePaths assemblyFilter (psiModule: IPsiModule) =
+let getResolveContext (resolveContextManager: PsiModuleResolveContextManager) project psiModule =
+ resolveContextManager.GetOrCreateModuleResolveContext(project, psiModule, psiModule.TargetFrameworkId)
+
+let getModuleResolveContext (resolveContextManager: PsiModuleResolveContextManager) (psiModule: IPsiModule) =
+ let project = psiModule.ContainingProjectModule :?> IProject
+ getResolveContext resolveContextManager project psiModule
+
+
+let getReferencedModules (psiModule: IPsiModule) =
let project = psiModule.ContainingProjectModule :?> _
let solution = psiModule.GetSolution()
let psiModules = solution.PsiModules()
- let resolveContextManager = solution.GetComponent()
+ let resolveContextManager = solution.GetComponent()
- let result = List()
- let resolveContext = resolveContextManager.GetOrCreateProjectResolveContext(project, psiModule.TargetFrameworkId)
- for reference in psiModules.GetModuleReferences(psiModule, resolveContext) do
+ let resolveContext = getResolveContext resolveContextManager project psiModule
+ psiModules.GetModuleReferences(psiModule, resolveContext)
+ |> Seq.filter (fun reference ->
match reference.Module with
- | :? IAssemblyPsiModule as assemblyPsiModule ->
- let assembly = assemblyPsiModule.Assembly
+ | :? IProjectPsiModule as projectPsiModule -> projectPsiModule != project
+ | _ -> true)
+ |> Seq.map (fun reference -> reference.Module)
+
+let getModulePath (psiModule: IPsiModule) =
+ match psiModule with
+ | :? IAssemblyPsiModule as assemblyPsiModule ->
+ assemblyPsiModule.Assembly.Location
+
+ | :? IProjectPsiModule as projectPsiModule ->
+ projectPsiModule.Project.GetOutputFilePath(projectPsiModule.TargetFrameworkId)
- if assemblyFilter assembly then
- result.Add(assembly.Location.FullPath)
+ | _ -> FileSystemPath.Empty
- | :? IProjectPsiModule as projectPsiModule ->
- let referencedProject = projectPsiModule.Project
- if referencedProject <> project then
- result.Add(referencedProject.GetOutputFilePath(projectPsiModule.TargetFrameworkId).FullPath)
+let getModuleFullPath (psiModule: IPsiModule) =
+ let path = getModulePath psiModule
+ path.FullPath
- | _ -> ()
- result
+let getOutputPath (psiModule: IPsiModule) =
+ match psiModule.ContainingProjectModule with
+ | :? IProject as project -> project.GetOutputFilePath(psiModule.TargetFrameworkId)
+ | _ -> FileSystemPath.Empty
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/ProjectModel/FSharpScriptPsiModuleFactory.fs b/ReSharper.FSharp/src/FSharp.Common/src/ProjectModel/FSharpScriptPsiModuleFactory.fs
index 80ad0b7c7b..303db82faf 100644
--- a/ReSharper.FSharp/src/FSharp.Common/src/ProjectModel/FSharpScriptPsiModuleFactory.fs
+++ b/ReSharper.FSharp/src/FSharp.Common/src/ProjectModel/FSharpScriptPsiModuleFactory.fs
@@ -36,7 +36,7 @@ open JetBrains.Util.Dotnet.TargetFrameworkIds
[]
type FSharpScriptPsiModulesProvider
(lifetime: Lifetime, solution: ISolution, changeManager: ChangeManager, documentManager: DocumentManager,
- scriptOptionsProvider: IFSharpScriptProjectOptionsProvider, platformManager: PlatformManager,
+ scriptOptionsProvider: IScriptFcsProjectProvider, platformManager: PlatformManager,
assemblyFactory: AssemblyFactory, projectFileExtensions, projectFileTypeCoordinator) as this =
/// There may be multiple project files for a path (i.e. linked in multiple projects) and we must distinguish them.
@@ -416,6 +416,10 @@ type FSharpScriptPsiModule
if projectHandlers.IsEmpty() then
modulesProvider.RemoveProjectFilePsiModule(this)
+ override x.ToString() =
+ let typeName = this.GetType().Name
+ sprintf "%s(%s)" typeName path.FullPath
+
interface IPsiModule with
member x.Name = "F# script: " + path.Name
member x.DisplayName = "F# script: " + path.Name
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Settings/FSharpOptions.fs b/ReSharper.FSharp/src/FSharp.Common/src/Settings/FSharpOptions.fs
index 18d88a0700..ccb20f283b 100644
--- a/ReSharper.FSharp/src/FSharp.Common/src/Settings/FSharpOptions.fs
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Settings/FSharpOptions.fs
@@ -52,16 +52,15 @@ type FSharpScriptOptions =
[]
-type FSharpScriptOptionsProvider(lifetime: Lifetime, settings: IContextBoundSettingsStoreLive) =
+type FSharpScriptSettingsProvider(lifetime: Lifetime, settings: IContextBoundSettingsStoreLive) =
new (lifetime: Lifetime, solution: ISolution, settingsStore: ISettingsStore) =
let settings = settingsStore.BindToContextLive(lifetime, ContextRange.Smart(solution.ToDataContext()))
- FSharpScriptOptionsProvider(lifetime, settings)
+ FSharpScriptSettingsProvider(lifetime, settings)
member val LanguageVersion = settings.GetValueProperty(lifetime, fun s -> s.LanguageVersion)
member val CustomDefines = settings.GetValueProperty(lifetime, fun s -> s.CustomDefines)
-
module FSharpTypeHintOptions =
let [] pipeReturnTypes = "Show return type hints in |> chains"
@@ -91,7 +90,7 @@ type FSharpOptionsPage
this.AddComboEnum((fun key -> key.LanguageVersion), FSharpScriptOptions.languageVersion, FSharpLanguageVersion.toString) |> ignore
this.AddHeader("Type hints")
- let showPipeReturnTypes = this.AddBoolOption((fun key -> key.ShowPipeReturnTypes), RichText(FSharpTypeHintOptions.pipeReturnTypes), null)
+ this.AddBoolOption((fun key -> key.ShowPipeReturnTypes), RichText(FSharpTypeHintOptions.pipeReturnTypes), null) |> ignore
do
use _x = this.Indent()
[
@@ -100,7 +99,7 @@ type FSharpOptionsPage
|> Seq.iter (fun checkbox ->
this.AddBinding(checkbox, BindingStyle.IsEnabledProperty, (fun key -> key.ShowPipeReturnTypes), id)
)
-
+
this.AddHeader("FSharp.Compiler.Service options")
this.AddBoolOption((fun key -> key.BackgroundTypeCheck), RichText(backgroundTypeCheck), null) |> ignore
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpAssemblyUtil.fs b/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpAssemblyUtil.fs
index aaeb0e3d93..1991abc21f 100644
--- a/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpAssemblyUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpAssemblyUtil.fs
@@ -1,4 +1,4 @@
-[]
+[]
module JetBrains.ReSharper.Plugins.FSharp.Util.FSharpAssemblyUtil
open System.Collections.Generic
@@ -8,7 +8,6 @@ open JetBrains.Metadata.Utils
open JetBrains.ProjectModel
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Psi.Caches
-open JetBrains.ReSharper.Psi.Impl.Reflection2
open JetBrains.ReSharper.Psi.Modules
open JetBrains.ReSharper.Resources.Shell
open JetBrains.Util
@@ -97,30 +96,3 @@ let getNestedTypes (declaredElement: IClrDeclaredElement) (symbolScope: ISymbolS
| :? ITypeElement as typeElement -> typeElement.NestedTypes :> _
| _ -> Seq.empty
-let rec importAutoOpenModule (declaredElement: IClrDeclaredElement) (symbolScope: ISymbolScope)(result: ICollection) =
- result.Add(declaredElement)
- for typeElement in getNestedTypes declaredElement symbolScope do
- for attribute in getAutoOpenAttributes typeElement do
- if attribute.PositionParameterCount = 0 then
- importAutoOpenModule typeElement symbolScope result
-
-let getAutoOpenModules (psiAssemblyFileLoader: IPsiAssemblyFileLoader) (assembly: IPsiAssembly) =
- let result = List()
-
- psiAssemblyFileLoader.GetOrLoadAssembly(assembly, true, fun psiAssembly assemblyFile metadataAssembly ->
- let attributesSet = assemblyFile.CreateAssemblyAttributes()
- let attributes = getAutoOpenAttributes attributesSet
-
- if attributes.IsEmpty() then () else
-
- let psiServices = psiAssembly.PsiModule.GetPsiServices()
- let symbolScope = psiServices.Symbols.GetSymbolScope(psiAssembly.PsiModule, false, true)
-
- for attribute in attributes do
- let moduleString = attribute.PositionParameter(0).ConstantValue.Value.As()
- if moduleString.IsNullOrEmpty() then () else
-
- for declaredElement in symbolScope.GetElementsByQualifiedName(moduleString) do
- importAutoOpenModule declaredElement symbolScope result) |> ignore
-
- result
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpCompilerAttributesUtil.fs b/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpCompilerAttributesUtil.fs
index 347d814aa6..8bd645805c 100644
--- a/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpCompilerAttributesUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpCompilerAttributesUtil.fs
@@ -2,6 +2,7 @@
module JetBrains.ReSharper.Plugins.FSharp.Util.FSharpCompilerAttributesUtil
open JetBrains.ReSharper.Psi
+open JetBrains.ReSharper.Psi.ExtensionsAPI.Caches2
[]
let getCompilationMappingAttrInstanceFlag (attrInstance: IAttributeInstance) =
@@ -42,10 +43,6 @@ let isCompiledException (property: IAttributesOwner) =
getCompilationMappingFlag property = SourceConstructFlags.Exception
-[]
-let hasAutoOpenAttribute (attrsOwner: IAttributesOwner) =
- attrsOwner.HasAttributeInstance(autoOpenAttrTypeName, false)
-
[]
let getAutoOpenAttributes (attributesSet: IAttributesSet) =
attributesSet.GetAttributeInstances(autoOpenAttrTypeName, AttributesSource.Self)
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpGlobalUtil.fs b/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpGlobalUtil.fs
index 5c073dbd7f..3b5d96ed46 100644
--- a/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpGlobalUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpGlobalUtil.fs
@@ -9,7 +9,7 @@ module FSharpGlobalUtil =
| _ -> null
/// Reference equality.
- let inline (==) a b = LanguagePrimitives.PhysicalEquality a b
+ let inline (==) a b = obj.ReferenceEquals(a, b)
/// Reference inequality.
let inline (!=) a b = not (a == b)
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpHighlightingAttributeIds.fs b/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpHighlightingAttributeIds.fs
index f7e6c1ec32..c2df0dd9f2 100644
--- a/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpHighlightingAttributeIds.fs
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpHighlightingAttributeIds.fs
@@ -68,78 +68,69 @@ type FSharpSettingsNamesProvider() =
// todo: replace explicit styles with fallback ids when highlighting registration refactoring is finished.
-[);
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Keyword,
- FallbackAttributeId = DefaultLanguageAttributeIds.KEYWORD,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Syntax//Keyword",
- Layer = HighlighterLayer.SYNTAX,
- EffectType = EffectType.TEXT, ForegroundColor = "#0000E0", DarkForegroundColor = "#569CD6");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.String,
- FallbackAttributeId = DefaultLanguageAttributeIds.STRING,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Syntax//String",
- Layer = HighlighterLayer.SYNTAX,
- EffectType = EffectType.TEXT, ForegroundColor = "#A31515", DarkForegroundColor = "#D69D85");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Number,
- FallbackAttributeId = DefaultLanguageAttributeIds.NUMBER,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Syntax//Number",
- Layer = HighlighterLayer.SYNTAX,
- EffectType = EffectType.TEXT, ForegroundColor = "#000000", DarkForegroundColor = "#B5CEA8");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.LineComment,
- FallbackAttributeId = DefaultLanguageAttributeIds.LINE_COMMENT,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Comments//Line comment",
- Layer = HighlighterLayer.ADDITIONAL_SYNTAX,
- EffectType = EffectType.TEXT, ForegroundColor = "#007F00", DarkForegroundColor = "#57A64A");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.BlockComment,
- FallbackAttributeId = DefaultLanguageAttributeIds.BLOCK_COMMENT,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Comments//Block comment",
- Layer = HighlighterLayer.ADDITIONAL_SYNTAX,
- EffectType = EffectType.TEXT, ForegroundColor = "#007F00", DarkForegroundColor = "#57A64A");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.EscapeCharacter1,
- FallbackAttributeId = DefaultLanguageAttributeIds.STRING_ESCAPE_CHARACTER_1,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- Layer = FSharpHighlightingAttributeIds.LayerSyntaxPlusOne,
- VSPriority = FSharpHighlightingAttributeIds.VsPriorityPlusOne,
- EffectType = EffectType.TEXT, ForegroundColor = "#FF007F", DarkForegroundColor = "#E07A00");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.EscapeCharacter2,
- FallbackAttributeId = DefaultLanguageAttributeIds.STRING_ESCAPE_CHARACTER_2,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- Layer = FSharpHighlightingAttributeIds.LayerSyntaxPlusOne,
- VSPriority = FSharpHighlightingAttributeIds.VsPriorityPlusOne,
- EffectType = EffectType.TEXT, ForegroundColor = "#FF66B2", DarkForegroundColor = "#FF8D1C");
-
- assembly:
- RegisterHighlighter(
+[);
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Keyword,
+ FallbackAttributeId = DefaultLanguageAttributeIds.KEYWORD,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Syntax//Keyword",
+ Layer = HighlighterLayer.SYNTAX,
+ EffectType = EffectType.TEXT, ForegroundColor = "#0000E0", DarkForegroundColor = "#569CD6");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.String,
+ FallbackAttributeId = DefaultLanguageAttributeIds.STRING,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Syntax//String",
+ Layer = HighlighterLayer.SYNTAX,
+ EffectType = EffectType.TEXT, ForegroundColor = "#A31515", DarkForegroundColor = "#D69D85");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Number,
+ FallbackAttributeId = DefaultLanguageAttributeIds.NUMBER,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Syntax//Number",
+ Layer = HighlighterLayer.SYNTAX,
+ EffectType = EffectType.TEXT, ForegroundColor = "#000000", DarkForegroundColor = "#B5CEA8");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.LineComment,
+ FallbackAttributeId = DefaultLanguageAttributeIds.LINE_COMMENT,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Comments//Line comment",
+ Layer = HighlighterLayer.ADDITIONAL_SYNTAX,
+ EffectType = EffectType.TEXT, ForegroundColor = "#007F00", DarkForegroundColor = "#57A64A");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.BlockComment,
+ FallbackAttributeId = DefaultLanguageAttributeIds.BLOCK_COMMENT,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Comments//Block comment",
+ Layer = HighlighterLayer.ADDITIONAL_SYNTAX,
+ EffectType = EffectType.TEXT, ForegroundColor = "#007F00", DarkForegroundColor = "#57A64A");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.EscapeCharacter1,
+ FallbackAttributeId = DefaultLanguageAttributeIds.STRING_ESCAPE_CHARACTER_1,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ Layer = FSharpHighlightingAttributeIds.LayerSyntaxPlusOne,
+ VSPriority = FSharpHighlightingAttributeIds.VsPriorityPlusOne,
+ EffectType = EffectType.TEXT, ForegroundColor = "#FF007F", DarkForegroundColor = "#E07A00");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.EscapeCharacter2,
+ FallbackAttributeId = DefaultLanguageAttributeIds.STRING_ESCAPE_CHARACTER_2,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ Layer = FSharpHighlightingAttributeIds.LayerSyntaxPlusOne,
+ VSPriority = FSharpHighlightingAttributeIds.VsPriorityPlusOne,
+ EffectType = EffectType.TEXT, ForegroundColor = "#FF66B2", DarkForegroundColor = "#FF8D1C");
+
+ RegisterHighlighter(
FSharpHighlightingAttributeIds.PreprocessorKeyword,
FallbackAttributeId = DefaultLanguageAttributeIds.PREPROCESSOR_KEYWORD,
GroupId = FSharpHighlightingAttributeIds.GroupId,
@@ -147,229 +138,206 @@ type FSharpSettingsNamesProvider() =
Layer = HighlighterLayer.SYNTAX,
EffectType = EffectType.TEXT, ForegroundColor = "#0000E0", DarkForegroundColor = "#569CD6");
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.PreprocessorInactiveBranch,
- FallbackAttributeId = DefaultLanguageAttributeIds.PREPROCESSOR_INACTIVE_BRANCH,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Preprocessor//Inactive branch",
- Layer = HighlighterLayer.DEADCODE,
- VSPriority = VSPriority.DEADCODE,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkGray");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Namespace,
- FallbackAttributeId = DefaultLanguageAttributeIds.NAMESPACE,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Modules and namespaces//Namespace",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Module,
- FallbackAttributeId = FSharpHighlightingAttributeIds.StaticClass,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Modules and namespaces//Module",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Class,
- FallbackAttributeId = DefaultLanguageAttributeIds.CLASS,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Types//Class",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.StaticClass,
- FallbackAttributeId = FSharpHighlightingAttributeIds.Class,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Types//Static class",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Interface,
- FallbackAttributeId = DefaultLanguageAttributeIds.INTERFACE,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Types//Interface",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Delegate,
- FallbackAttributeId = DefaultLanguageAttributeIds.DELEGATE,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Types//Delegate",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Struct,
- FallbackAttributeId = DefaultLanguageAttributeIds.STRUCT,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Types//Struct",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Enum,
- FallbackAttributeId = DefaultLanguageAttributeIds.ENUM,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Types//Enum",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.TypeParameter,
- FallbackAttributeId = DefaultLanguageAttributeIds.TYPE_PARAMETER,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Types//Type parameter",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Union,
- FallbackAttributeId = FSharpHighlightingAttributeIds.Enum,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Types//Union",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.UnionCase,
- FallbackAttributeId = FSharpHighlightingAttributeIds.Class,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Types//Union Case",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Record,
- FallbackAttributeId = FSharpHighlightingAttributeIds.Class,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Types//Record",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Literal,
- FallbackAttributeId = DefaultLanguageAttributeIds.CONSTANT,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Values//Literal",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "Purple", DarkForegroundColor = "Violet",
- FontStyle = FontStyle.Bold);
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Event,
- FallbackAttributeId = DefaultLanguageAttributeIds.EVENT,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Members//Event",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "Magenta", DarkForegroundColor = "Plum");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Field,
- FallbackAttributeId = DefaultLanguageAttributeIds.FIELD,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Members//Field",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "Purple", DarkForegroundColor = "Violet");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Property,
- FallbackAttributeId = DefaultLanguageAttributeIds.PROPERTY,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Members//Property",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "Purple", DarkForegroundColor = "Violet");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Value,
- FallbackAttributeId = DefaultLanguageAttributeIds.LOCAL_VARIABLE,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Values//Value",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT);
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.MutableValue,
- FallbackAttributeId = DefaultLanguageAttributeIds.MUTABLE_LOCAL_VARIABLE,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Values//Mutable value",
- Layer = FSharpHighlightingAttributeIds.LayerSyntaxPlusOne,
- VSPriority = FSharpHighlightingAttributeIds.VsPriorityPlusOne,
- EffectType = EffectType.TEXT,
- FontStyle = FontStyle.Bold);
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Method,
- FallbackAttributeId = DefaultLanguageAttributeIds.METHOD,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Members//Method",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkCyan:Maroon", DarkForegroundColor = "Cyan");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.Operator,
- FallbackAttributeId = DefaultLanguageAttributeIds.OVERLOADED_OPERATOR,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Values//Operator",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkCyan:Blue", DarkForegroundColor = "Cyan");
-
- assembly:
- RegisterHighlighter(
- FSharpHighlightingAttributeIds.ActivePatternCase,
- FallbackAttributeId = FSharpHighlightingAttributeIds.Method,
- GroupId = FSharpHighlightingAttributeIds.GroupId,
- RiderPresentableName = "Values//Active pattern case",
- Layer = HighlighterLayer.SYNTAX,
- VSPriority = VSPriority.IDENTIFIERS,
- EffectType = EffectType.TEXT, ForegroundColor = "DarkCyan:Blue", DarkForegroundColor = "Cyan")>]
-do
- ()
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.PreprocessorInactiveBranch,
+ FallbackAttributeId = DefaultLanguageAttributeIds.PREPROCESSOR_INACTIVE_BRANCH,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Preprocessor//Inactive branch",
+ Layer = HighlighterLayer.DEADCODE,
+ VSPriority = VSPriority.DEADCODE,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkGray");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Namespace,
+ FallbackAttributeId = DefaultLanguageAttributeIds.NAMESPACE,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Modules and namespaces//Namespace",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Module,
+ FallbackAttributeId = FSharpHighlightingAttributeIds.StaticClass,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Modules and namespaces//Module",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Class,
+ FallbackAttributeId = DefaultLanguageAttributeIds.CLASS,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Types//Class",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.StaticClass,
+ FallbackAttributeId = FSharpHighlightingAttributeIds.Class,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Types//Static class",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Interface,
+ FallbackAttributeId = DefaultLanguageAttributeIds.INTERFACE,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Types//Interface",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Delegate,
+ FallbackAttributeId = DefaultLanguageAttributeIds.DELEGATE,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Types//Delegate",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Struct,
+ FallbackAttributeId = DefaultLanguageAttributeIds.STRUCT,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Types//Struct",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Enum,
+ FallbackAttributeId = DefaultLanguageAttributeIds.ENUM,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Types//Enum",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.TypeParameter,
+ FallbackAttributeId = DefaultLanguageAttributeIds.TYPE_PARAMETER,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Types//Type parameter",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Union,
+ FallbackAttributeId = FSharpHighlightingAttributeIds.Enum,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Types//Union",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.UnionCase,
+ FallbackAttributeId = FSharpHighlightingAttributeIds.Class,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Types//Union Case",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Record,
+ FallbackAttributeId = FSharpHighlightingAttributeIds.Class,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Types//Record",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkBlue", DarkForegroundColor = "LightBlue");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Literal,
+ FallbackAttributeId = DefaultLanguageAttributeIds.CONSTANT,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Values//Literal",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "Purple", DarkForegroundColor = "Violet",
+ FontStyle = FontStyle.Bold);
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Event,
+ FallbackAttributeId = DefaultLanguageAttributeIds.EVENT,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Members//Event",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "Magenta", DarkForegroundColor = "Plum");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Field,
+ FallbackAttributeId = DefaultLanguageAttributeIds.FIELD,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Members//Field",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "Purple", DarkForegroundColor = "Violet");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Property,
+ FallbackAttributeId = DefaultLanguageAttributeIds.PROPERTY,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Members//Property",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "Purple", DarkForegroundColor = "Violet");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Value,
+ FallbackAttributeId = DefaultLanguageAttributeIds.LOCAL_VARIABLE,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Values//Value",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT);
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.MutableValue,
+ FallbackAttributeId = DefaultLanguageAttributeIds.MUTABLE_LOCAL_VARIABLE,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Values//Mutable value",
+ Layer = FSharpHighlightingAttributeIds.LayerSyntaxPlusOne,
+ VSPriority = FSharpHighlightingAttributeIds.VsPriorityPlusOne,
+ EffectType = EffectType.TEXT,
+ FontStyle = FontStyle.Bold);
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Method,
+ FallbackAttributeId = DefaultLanguageAttributeIds.METHOD,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Members//Method",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkCyan:Maroon", DarkForegroundColor = "Cyan");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.Operator,
+ FallbackAttributeId = DefaultLanguageAttributeIds.OVERLOADED_OPERATOR,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Values//Operator",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkCyan:Blue", DarkForegroundColor = "Cyan");
+
+ RegisterHighlighter(
+ FSharpHighlightingAttributeIds.ActivePatternCase,
+ FallbackAttributeId = FSharpHighlightingAttributeIds.Method,
+ GroupId = FSharpHighlightingAttributeIds.GroupId,
+ RiderPresentableName = "Values//Active pattern case",
+ Layer = HighlighterLayer.SYNTAX,
+ VSPriority = VSPriority.IDENTIFIERS,
+ EffectType = EffectType.TEXT, ForegroundColor = "DarkCyan:Blue", DarkForegroundColor = "Cyan")>]
+type FSharpHighlightingAttributeIds() = class end
module MissingAssemblyReferenceWorkaround =
type T(p: FontStyle) =
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpPredefinedType.fs b/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpPredefinedType.fs
index e520dfc9fd..2b310431f7 100644
--- a/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpPredefinedType.fs
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Util/FSharpPredefinedType.fs
@@ -13,6 +13,9 @@ let sourceNameAttrTypeName = clrTypeName "Microsoft.FSharp.Core.CompilationSourc
[]
let compilationMappingAttrTypeName = clrTypeName "Microsoft.FSharp.Core.CompilationMappingAttribute"
+[]
+let compilationRepresentationAttrTypeName = clrTypeName "Microsoft.FSharp.Core.CompilationRepresentationAttribute"
+
[]
let autoOpenAttrTypeName = clrTypeName "Microsoft.FSharp.Core.AutoOpenAttribute"
diff --git a/ReSharper.FSharp/src/FSharp.Common/src/Util/Util.fs b/ReSharper.FSharp/src/FSharp.Common/src/Util/Util.fs
index c779164295..f10da474b8 100644
--- a/ReSharper.FSharp/src/FSharp.Common/src/Util/Util.fs
+++ b/ReSharper.FSharp/src/FSharp.Common/src/Util/Util.fs
@@ -62,6 +62,9 @@ module rec CommonUtil =
let isSigFile (path: FileSystemPath) =
isSigFileExtension path.ExtensionNoDot
+ let getFullPath (path: FileSystemPath) =
+ path.FullPath
+
type Line = Int32
type Column = Int32
@@ -202,9 +205,16 @@ module rec FSharpMsBuildUtils =
[]
module PsiUtil =
+ let private getModuleSymbolScope withReferences (psiModule: IPsiModule) =
+ psiModule.GetPsiServices().Symbols.GetSymbolScope(psiModule, withReferences, true)
+
[]
let getSymbolScope (psiModule: IPsiModule) =
- psiModule.GetPsiServices().Symbols.GetSymbolScope(psiModule, true, true)
+ getModuleSymbolScope true psiModule
+
+ []
+ let getModuleOnlySymbolScope (psiModule: IPsiModule) =
+ getModuleSymbolScope false psiModule
[]
let getTokenType ([] node: ITreeNode) =
diff --git a/ReSharper.FSharp/src/FSharp.ProjectModelBase/src/FSharpIcons.cs b/ReSharper.FSharp/src/FSharp.ProjectModelBase/src/FSharpIcons.cs
index 925c0441c8..e4c8c92a2a 100644
--- a/ReSharper.FSharp/src/FSharp.ProjectModelBase/src/FSharpIcons.cs
+++ b/ReSharper.FSharp/src/FSharp.ProjectModelBase/src/FSharpIcons.cs
@@ -53,23 +53,23 @@ public sealed class FSharpModule : global::JetBrains.Application.Icons.CompiledI
new global::JetBrains.Application.Icons.CompiledIconsCs.CompiledIconCsId(typeof(FSharpModule));
/// Loads the image for Themed Icon FSharpModule theme aspect SymbolsVs11Color.
- public global::JetBrains.Application.UI.Icons.Images.TiImage Load_SymbolsVs11Color()
+ public global::JetBrains.Util.Icons.TiImage Load_SymbolsVs11Color()
{
- return global::JetBrains.Application.UI.Icons.Images.TiImageConverter.FromCanonicalSExpressionAsciiString(
+ return global::JetBrains.Util.Icons.TiImageConverter.FromCanonicalSExpressionAsciiString(
@"(7:TiImage2:v1(6:Vector(4:Size5:16,16)(7:Drawing(4:Path(4:Fill(5:Solid9:#00FFFFFF))(8:Segments(1:F0:0:1:11:1)(1:L2:160:)(1:L2:162:16)(1:L0:2:16)))(4:Path(4:Fill(6:Linear(5:Start5:0.5,0)(3:End5:0.5,1)(5:Stops9:#FF5D5F620:9:#FF292C2D1:1)))(8:Segments(1:F1:21:11:11:1)(1:L2:151:1)(1:L2:152:14)(1:L1:22:14)))(4:Path(4:Fill(6:Linear(5:Start22:0.5,0.0414000000000001)(3:End10:0.5,1.0168)(5:Stops9:#FF85DAFF0:9:#FF6BB3FF1:1)))(8:Segments(1:F1:31:81:11:1)(1:L2:141:8)(1:L2:142:13)(1:L1:32:13)))(4:Path(4:Fill(6:Linear(5:Start22:0.5,0.0277999999999999)(3:End10:0.5,1.0154)(5:Stops9:#FFFF78FF0:9:#FFFC0EFF1:1)))(8:Segments(1:F1:31:21:11:1)(1:L1:81:2)(1:L1:81:7)(1:L1:31:7)))(4:Path(4:Fill(6:Linear(5:Start5:0.5,0)(3:End5:0.5,1)(5:Stops9:#FFFFF6590:9:#FFD6AF001:1)))(8:Segments(1:F1:91:21:11:1)(1:L2:141:2)(1:L2:141:7)(1:L1:91:7))))(8:ClipMask)))");
}
/// Loads the image for Themed Icon FSharpModule theme aspect SymbolsVs11Gray.
- public global::JetBrains.Application.UI.Icons.Images.TiImage Load_SymbolsVs11Gray()
+ public global::JetBrains.Util.Icons.TiImage Load_SymbolsVs11Gray()
{
- return global::JetBrains.Application.UI.Icons.Images.TiImageConverter.FromCanonicalSExpressionAsciiString(
+ return global::JetBrains.Util.Icons.TiImageConverter.FromCanonicalSExpressionAsciiString(
@"(7:TiImage2:v1(6:Vector(4:Size5:16,16)(7:Drawing(4:Path(4:Fill(5:Solid9:#00FFFFFF))(8:Segments(1:F0:0:1:11:1)(1:L2:160:)(1:L2:162:16)(1:L0:2:16)))(4:Path(4:Fill(5:Solid9:#FFF4F4F4))(8:Segments(1:F1:21:11:11:1)(1:L2:151:1)(1:L2:152:14)(1:L1:22:14)))(4:Path(4:Fill(5:Solid9:#FF642E8D))(8:Segments(1:F1:31:81:11:1)(1:L2:141:8)(1:L2:142:13)(1:L1:32:13)))(4:Path(4:Fill(5:Solid9:#FF642E8D))(8:Segments(1:F1:31:21:11:1)(1:L1:81:2)(1:L1:81:7)(1:L1:31:7)))(4:Path(4:Fill(5:Solid9:#FF642E8D))(8:Segments(1:F1:91:21:11:1)(1:L2:141:2)(1:L2:141:7)(1:L1:91:7))))(8:ClipMask)))");
}
/// Loads the image for Themed Icon FSharpModule theme aspect SymbolsVs11GrayDark.
- public global::JetBrains.Application.UI.Icons.Images.TiImage Load_SymbolsVs11GrayDark()
+ public global::JetBrains.Util.Icons.TiImage Load_SymbolsVs11GrayDark()
{
- return global::JetBrains.Application.UI.Icons.Images.TiImageConverter.FromCanonicalSExpressionAsciiString(
+ return global::JetBrains.Util.Icons.TiImageConverter.FromCanonicalSExpressionAsciiString(
@"(7:TiImage2:v1(6:Vector(4:Size5:16,16)(7:Drawing(4:Path(4:Fill(5:Solid9:#00FFFFFF))(8:Segments(1:F0:0:1:11:1)(1:L2:160:)(1:L2:162:16)(1:L0:2:16)))(4:Path(4:Fill(5:Solid9:#FF252525))(8:Segments(1:F1:21:11:11:1)(1:L2:151:1)(1:L2:152:14)(1:L1:22:14)))(4:Path(4:Fill(5:Solid9:#FFB280D3))(8:Segments(1:F1:31:81:11:1)(1:L2:141:8)(1:L2:142:13)(1:L1:32:13)))(4:Path(4:Fill(5:Solid9:#FFB280D3))(8:Segments(1:F1:31:21:11:1)(1:L1:81:2)(1:L1:81:7)(1:L1:31:7)))(4:Path(4:Fill(5:Solid9:#FFB280D3))(8:Segments(1:F1:91:21:11:1)(1:L2:141:2)(1:L2:141:7)(1:L1:91:7))))(8:ClipMask)))");
}
@@ -148,21 +148,21 @@ public sealed class ExtensionOverlay : global::JetBrains.Application.Icons.Compi
public static global::JetBrains.UI.Icons.IconId Id = new global::JetBrains.Application.Icons.CompiledIconsCs.CompiledIconCsId(typeof(ExtensionOverlay));
/// Loads the image for Themed Icon ExtensionOverlay theme aspect Color.
- public global::JetBrains.Application.UI.Icons.Images.TiImage Load_Color()
+ public global::JetBrains.Util.Icons.TiImage Load_Color()
{
- return global::JetBrains.Application.UI.Icons.Images.TiImageConverter.FromCanonicalSExpressionAsciiString(@"(7:TiImage2:v1(6:Vector(4:Size5:16,16)(7:Drawing(4:Path(4:Fill(5:Solid9:#00FFFFFF))(8:Segments(1:F0:0:1:11:1)(1:L2:160:)(1:L2:162:16)(1:L0:2:16)))(4:Path(4:Fill(6:Linear(5:Start9:0.5,0.013)(3:End20:0.5,1.00009090909091)(5:Stops9:#FF3861A00:9:#FF1B3A691:1)))(8:Segments(1:F6:15.0581:81:11:1)(1:L2:145:9.058)(1:L2:141:5)(1:L2:101:5)(1:L2:105:9.058)(1:L5:8.9421:8)(1:L1:81:8)(1:L1:86:12.414)(1:L6:11.5862:16)(1:L6:12.4142:16)(1:L2:166:12.414)(1:L2:161:8)(1:L6:15.0581:8)))(4:Path(4:Fill(6:Linear(5:Start22:0.5,0.0413333333333333)(3:End20:0.5,1.01677777777778)(5:Stops9:#FF6ED8FF0:9:#FF80FFF41:1)))(8:Segments(1:F2:111:71:11:1)(1:L2:111:6)(1:L2:131:6)(1:L2:131:7)(1:F2:111:71:10:)(1:F2:131:81:11:1)(1:L2:111:8)(1:L2:116:11.472)(1:L1:95:9.472)(1:L1:92:12)(1:L2:122:15)(1:L2:152:12)(1:L2:155:9.472)(1:L2:136:11.472)(1:F2:131:81:10:))))(8:ClipMask)))");
+ return global::JetBrains.Util.Icons.TiImageConverter.FromCanonicalSExpressionAsciiString(@"(7:TiImage2:v1(6:Vector(4:Size5:16,16)(7:Drawing(4:Path(4:Fill(5:Solid9:#00FFFFFF))(8:Segments(1:F0:0:1:11:1)(1:L2:160:)(1:L2:162:16)(1:L0:2:16)))(4:Path(4:Fill(6:Linear(5:Start9:0.5,0.013)(3:End20:0.5,1.00009090909091)(5:Stops9:#FF3861A00:9:#FF1B3A691:1)))(8:Segments(1:F6:15.0581:81:11:1)(1:L2:145:9.058)(1:L2:141:5)(1:L2:101:5)(1:L2:105:9.058)(1:L5:8.9421:8)(1:L1:81:8)(1:L1:86:12.414)(1:L6:11.5862:16)(1:L6:12.4142:16)(1:L2:166:12.414)(1:L2:161:8)(1:L6:15.0581:8)))(4:Path(4:Fill(6:Linear(5:Start22:0.5,0.0413333333333333)(3:End20:0.5,1.01677777777778)(5:Stops9:#FF6ED8FF0:9:#FF80FFF41:1)))(8:Segments(1:F2:111:71:11:1)(1:L2:111:6)(1:L2:131:6)(1:L2:131:7)(1:F2:111:71:10:)(1:F2:131:81:11:1)(1:L2:111:8)(1:L2:116:11.472)(1:L1:95:9.472)(1:L1:92:12)(1:L2:122:15)(1:L2:152:12)(1:L2:155:9.472)(1:L2:136:11.472)(1:F2:131:81:10:))))(8:ClipMask)))");
}
/// Loads the image for Themed Icon ExtensionOverlay theme aspect Gray.
- public global::JetBrains.Application.UI.Icons.Images.TiImage Load_Gray()
+ public global::JetBrains.Util.Icons.TiImage Load_Gray()
{
- return global::JetBrains.Application.UI.Icons.Images.TiImageConverter.FromCanonicalSExpressionAsciiString(@"(7:TiImage2:v1(6:Vector(4:Size5:16,16)(7:Drawing(4:Path(4:Fill(5:Solid9:#00FFFFFF))(8:Segments(1:F0:0:1:11:1)(1:L2:160:)(1:L2:162:16)(1:L0:2:16)))(4:Path(4:Fill(5:Solid9:#FFF4F4F4))(8:Segments(1:F6:15.0581:81:11:1)(1:L2:145:9.058)(1:L2:141:5)(1:L2:101:5)(1:L2:105:9.058)(1:L5:8.9421:8)(1:L1:81:8)(1:L1:86:12.414)(1:L6:11.5862:16)(1:L6:12.4142:16)(1:L2:166:12.414)(1:L2:161:8)(1:L6:15.0581:8)))(4:Path(4:Fill(5:Solid9:#FF00539C))(8:Segments(1:F2:111:71:11:1)(1:L2:111:6)(1:L2:131:6)(1:L2:131:7)(1:F2:111:71:10:)(1:F2:131:81:11:1)(1:L2:111:8)(1:L2:116:11.472)(1:L1:95:9.472)(1:L1:92:12)(1:L2:122:15)(1:L2:152:12)(1:L2:155:9.472)(1:L2:136:11.472)(1:F2:131:81:10:))))(8:ClipMask)))");
+ return global::JetBrains.Util.Icons.TiImageConverter.FromCanonicalSExpressionAsciiString(@"(7:TiImage2:v1(6:Vector(4:Size5:16,16)(7:Drawing(4:Path(4:Fill(5:Solid9:#00FFFFFF))(8:Segments(1:F0:0:1:11:1)(1:L2:160:)(1:L2:162:16)(1:L0:2:16)))(4:Path(4:Fill(5:Solid9:#FFF4F4F4))(8:Segments(1:F6:15.0581:81:11:1)(1:L2:145:9.058)(1:L2:141:5)(1:L2:101:5)(1:L2:105:9.058)(1:L5:8.9421:8)(1:L1:81:8)(1:L1:86:12.414)(1:L6:11.5862:16)(1:L6:12.4142:16)(1:L2:166:12.414)(1:L2:161:8)(1:L6:15.0581:8)))(4:Path(4:Fill(5:Solid9:#FF00539C))(8:Segments(1:F2:111:71:11:1)(1:L2:111:6)(1:L2:131:6)(1:L2:131:7)(1:F2:111:71:10:)(1:F2:131:81:11:1)(1:L2:111:8)(1:L2:116:11.472)(1:L1:95:9.472)(1:L1:92:12)(1:L2:122:15)(1:L2:152:12)(1:L2:155:9.472)(1:L2:136:11.472)(1:F2:131:81:10:))))(8:ClipMask)))");
}
/// Loads the image for Themed Icon ExtensionOverlay theme aspect GrayDark.
- public global::JetBrains.Application.UI.Icons.Images.TiImage Load_GrayDark()
+ public global::JetBrains.Util.Icons.TiImage Load_GrayDark()
{
- return global::JetBrains.Application.UI.Icons.Images.TiImageConverter.FromCanonicalSExpressionAsciiString(@"(7:TiImage2:v1(6:Vector(4:Size5:16,16)(7:Drawing(4:Path(4:Fill(5:Solid9:#00FFFFFF))(8:Segments(1:F0:0:1:11:1)(1:L2:160:)(1:L2:162:16)(1:L0:2:16)))(4:Path(4:Fill(5:Solid9:#FF252525))(8:Segments(1:F6:15.0581:81:11:1)(1:L2:145:9.058)(1:L2:141:5)(1:L2:101:5)(1:L2:105:9.058)(1:L5:8.9421:8)(1:L1:81:8)(1:L1:86:12.414)(1:L6:11.5862:16)(1:L6:12.4142:16)(1:L2:166:12.414)(1:L2:161:8)(1:L6:15.0581:8)))(4:Path(4:Fill(5:Solid9:#FF7CBEFF))(8:Segments(1:F2:111:71:11:1)(1:L2:111:6)(1:L2:131:6)(1:L2:131:7)(1:F2:111:71:10:)(1:F2:131:81:11:1)(1:L2:111:8)(1:L2:116:11.472)(1:L1:95:9.472)(1:L1:92:12)(1:L2:122:15)(1:L2:152:12)(1:L2:155:9.472)(1:L2:136:11.472)(1:F2:131:81:10:))))(8:ClipMask)))");
+ return global::JetBrains.Util.Icons.TiImageConverter.FromCanonicalSExpressionAsciiString(@"(7:TiImage2:v1(6:Vector(4:Size5:16,16)(7:Drawing(4:Path(4:Fill(5:Solid9:#00FFFFFF))(8:Segments(1:F0:0:1:11:1)(1:L2:160:)(1:L2:162:16)(1:L0:2:16)))(4:Path(4:Fill(5:Solid9:#FF252525))(8:Segments(1:F6:15.0581:81:11:1)(1:L2:145:9.058)(1:L2:141:5)(1:L2:101:5)(1:L2:105:9.058)(1:L5:8.9421:8)(1:L1:81:8)(1:L1:86:12.414)(1:L6:11.5862:16)(1:L6:12.4142:16)(1:L2:166:12.414)(1:L2:161:8)(1:L6:15.0581:8)))(4:Path(4:Fill(5:Solid9:#FF7CBEFF))(8:Segments(1:F2:111:71:11:1)(1:L2:111:6)(1:L2:131:6)(1:L2:131:7)(1:F2:111:71:10:)(1:F2:131:81:11:1)(1:L2:111:8)(1:L2:116:11.472)(1:L1:95:9.472)(1:L1:92:12)(1:L2:122:15)(1:L2:152:12)(1:L2:155:9.472)(1:L2:136:11.472)(1:F2:131:81:10:))))(8:ClipMask)))");
}
/// Returns the set of theme images for Themed Icon ExtensionOverlay.
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/FSharp.Psi.Features.fsproj b/ReSharper.FSharp/src/FSharp.Psi.Features/FSharp.Psi.Features.fsproj
index edc2bd6d38..e77e2b5a25 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/FSharp.Psi.Features.fsproj
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/FSharp.Psi.Features.fsproj
@@ -7,15 +7,16 @@
-
+
+
@@ -48,6 +49,7 @@
+
@@ -63,6 +65,7 @@
+
@@ -81,12 +84,13 @@
+
-
+
@@ -143,6 +147,8 @@
+
+
@@ -157,6 +163,8 @@
+
+
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/CodeCompletion/FSharpLookupItem.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/CodeCompletion/FSharpLookupItem.fs
index aa6ae8d11a..447a0c1fd6 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/CodeCompletion/FSharpLookupItem.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/CodeCompletion/FSharpLookupItem.fs
@@ -7,6 +7,7 @@ open JetBrains.ReSharper.Feature.Services.Lookup
open JetBrains.ReSharper.Feature.Services.ParameterInfo
open JetBrains.ReSharper.Host.Features.Completion
open JetBrains.ReSharper.Plugins.FSharp
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features
open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Services.Cs.CodeCompletion
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/ColorReferenceAnalyzer.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/ColorReferenceAnalyzer.fs
index 80233bef08..8978bcfbc4 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/ColorReferenceAnalyzer.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/ColorReferenceAnalyzer.fs
@@ -1,4 +1,4 @@
-module JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Analyzers.ColorReferenceAnalyzer
+namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Analyzers
open JetBrains.Application.Settings
open JetBrains.ReSharper.Daemon.VisualElements
@@ -6,9 +6,8 @@ open JetBrains.ReSharper.Feature.Services.Daemon
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Stages
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-[,
- HighlightingTypes = [| typeof |])>]
-type RedundantAttributeSuffixAnalyzer() =
+[, HighlightingTypes = [| typeof |])>]
+type ColorReferenceAnalyzer() =
inherit ElementProblemAnalyzer()
override x.Run(expr, analyzerData, consumer) =
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/LetDisposableAnalyzer.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/LetDisposableAnalyzer.fs
index 87f0df4180..f9c4edcc1f 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/LetDisposableAnalyzer.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/LetDisposableAnalyzer.fs
@@ -12,7 +12,7 @@ open JetBrains.ReSharper.Psi.Util
//[,
// HighlightingTypes = [| typeof |])>]
type LetDisposableAnalyzer() =
- inherit ElementProblemAnalyzer()
+ inherit ElementProblemAnalyzer()
override x.Run(letExpr, _, consumer) =
if letExpr.IsUse then () else
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/ReSpellerHelper.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/ReSpellerHelper.fs
index 3475b6e6fa..33ffab4115 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/ReSpellerHelper.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/ReSpellerHelper.fs
@@ -11,7 +11,7 @@ type ReSpellerPsiHelper() =
override x.ShouldSkipDeclaration(declaration) =
match declaration with
- | :? ISynPat as synPat -> not synPat.IsDeclaration
+ | :? IFSharpPattern as fsPattern -> not fsPattern.IsDeclaration
| :? IFSharpDeclaration as fsDeclaration -> fsDeclaration.NameIdentifier :? IActivePatternId
| _ -> true
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/RedundantNew.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/RedundantNew.fs
index 18336b904d..5f6fdcd053 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/RedundantNew.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/RedundantNew.fs
@@ -2,9 +2,9 @@ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Analyzers
open FSharp.Compiler.SourceCodeServices
open JetBrains.ReSharper.Feature.Services.Daemon
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi
[,
@@ -14,6 +14,8 @@ type RedundantNewAnalyzer() =
override x.Run(newExpr, _, consumer) =
let typeName = newExpr.TypeName
+ if isNull typeName then () else
+
let resolveResult = typeName.Reference.Resolve()
match resolveResult.DeclaredElement.As() with
| null -> ()
@@ -23,7 +25,7 @@ type RedundantNewAnalyzer() =
if typeElement.IsDescendantOf(predefinedType.IDisposable.GetTypeElement()) then () else
if isNull newExpr.NewKeyword then () else
- match newExpr.CheckerService.ResolveNameAtLocation(newExpr, typeName.Names, "RedundantNewAnalyzer") with
+ match newExpr.GetFcsCheckerService().ResolveNameAtLocation(newExpr, typeName.Names, "RedundantNewAnalyzer") with
| None -> ()
| Some symbolUse ->
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/RedundantQualifierAnalyzer.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/RedundantQualifierAnalyzer.fs
new file mode 100644
index 0000000000..2af2043620
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Analyzers/RedundantQualifierAnalyzer.fs
@@ -0,0 +1,54 @@
+module JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Analyzers.RedundantQualifierAnalyzer
+
+open JetBrains.ReSharper.Feature.Services.Daemon
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Stages
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
+open JetBrains.ReSharper.Psi
+open JetBrains.ReSharper.Psi.ExtensionsAPI
+
+let [] OpName = "RedundantQualifierAnalyzer"
+
+// todo: module decls
+
+let isRedundant (data: ElementProblemAnalyzerData) (referenceOwner: IFSharpReferenceOwner) =
+ let reference = referenceOwner.Reference
+
+ let qualifierExpr = reference.QualifierReference
+ if isNull qualifierExpr then false else
+
+ let qualifierName = qualifierExpr.GetName()
+ if qualifierName = SharedImplUtil.MISSING_DECLARATION_NAME then false else
+
+ let opens = data.GetData(FSharpErrorsStage.openedModulesProvider).GetOpenedModuleNames
+ if not (opens.Contains(qualifierName)) then false else
+// if not (opens.GetValuesSafe(shortName) |> Seq.exists (endsWith qualifierExpr.QualifiedName)) then () else
+
+ let referenceName = referenceOwner.As()
+ if isNotNull referenceName && isInOpen referenceName then false else
+
+ let declaredElement =
+ match reference.Resolve().DeclaredElement with
+ | :? IConstructor as ctor -> ctor.GetContainingType() :> IDeclaredElement
+ | declaredElement -> declaredElement
+
+ if isNull declaredElement then false else
+
+ // Don't make namespace usages unqualified, e.g. don't remove `System` leaving `Collections.Generic.List`.
+ if declaredElement :? INamespace && qualifierName <> FSharpTokenType.GLOBAL.TokenRepresentation then false else
+
+ // todo: try to check next qualified names in case we got into multiple-result resolve, i.e. for module?
+ FSharpResolveUtil.resolvesToUnqualified declaredElement reference OpName
+
+
+[; typeof; typeof |],
+ HighlightingTypes = [| typeof |])>]
+type RedundantQualifierExpressionAnalyzer() =
+ interface IElementProblemAnalyzer with
+ member x.Run(refExpr, data, consumer) =
+ let referenceOwner = refExpr :?> IFSharpReferenceOwner
+ if isRedundant data referenceOwner then
+ consumer.AddHighlighting(RedundantQualifierWarning(refExpr))
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/CommonErrors.xml b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/CommonErrors.xml
index 5b6e54031a..821f5173b2 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/CommonErrors.xml
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/CommonErrors.xml
@@ -2,8 +2,8 @@
JetBrains.ReSharper.Intentions.QuickFixes;
+ JetBrains.ReSharper.Plugins.FSharp.Psi;
JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings;
- JetBrains.ReSharper.Plugins.FSharp.Psi.Util.PsiUtil;
JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree;
JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve;
JetBrains.ReSharper.Plugins.FSharp.Psi.Impl;
@@ -90,7 +90,7 @@
-
+
fcsMessage
@@ -104,7 +104,7 @@
-
+
fcsMessage
@@ -117,7 +117,7 @@
-
+
fcsMessage
@@ -125,6 +125,7 @@
expr.GetHighlightingRange()
AddIgnoreFix
+ IntroduceVarFix
@@ -259,7 +260,7 @@
-
+
letExpr.LetOrUseToken.GetHighlightingRange()
@@ -267,7 +268,7 @@
-
+
letExpr.LetOrUseToken.GetHighlightingRange()
@@ -277,7 +278,7 @@
-
+
if prefixApp.FunctionExpression == expr then "Unexpected argument" else "Unexpected arguments"
@@ -331,4 +332,28 @@
ToAbstractFix
+
+
+
+ yieldExpr.GetHighlightingRange()
+
+ RemoveYieldFix
+
+
+
+
+
+ yieldExpr.GetHighlightingRange()
+
+ RemoveYieldFix
+
+
+
+
+ getQualifierRange treeNode
+
+
+ RemoveRedundantQualifierFix
+
+
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/ErrorHighlightings.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/ErrorHighlightings.fs
index 22900cdcde..95dc4fb315 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/ErrorHighlightings.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/ErrorHighlightings.fs
@@ -5,6 +5,10 @@ open JetBrains.DocumentModel
open JetBrains.ReSharper.Feature.Services.Daemon
open JetBrains.ReSharper.Feature.Services.Daemon.Attributes
+[]
+type FSharpErrors() =
+ class end
+
[]
type FSharpErrorHighlightingBase(message, range: DocumentRange) =
interface IHighlighting with
@@ -14,42 +18,42 @@ type FSharpErrorHighlightingBase(message, range: DocumentRange) =
member x.CalculateRange() = range
-[,
AttributeId = AnalysisHighlightingAttributeIds.ERROR,
OverlapResolve = OverlapResolveKind.NONE)>]
type ErrorHighlighting(message, range) =
inherit FSharpErrorHighlightingBase(message, range)
-[,
AttributeId = AnalysisHighlightingAttributeIds.WARNING,
OverlapResolve = OverlapResolveKind.NONE)>]
type WarningHighlighting(message, range) =
inherit FSharpErrorHighlightingBase(message, range)
-[,
AttributeId = AnalysisHighlightingAttributeIds.UNRESOLVED_ERROR,
OverlapResolve = OverlapResolveKind.NONE)>]
type UnresolvedHighlighting(message, range) =
inherit FSharpErrorHighlightingBase(message, range)
-[,
AttributeId = AnalysisHighlightingAttributeIds.DEADCODE,
OverlapResolve = OverlapResolveKind.NONE)>]
type UnusedHighlighting(message, range) =
inherit FSharpErrorHighlightingBase(message, range)
-[,
AttributeId = AnalysisHighlightingAttributeIds.ERROR,
OverlapResolve = OverlapResolveKind.NONE)>]
type UseKeywordIllegalInPrimaryCtor(message, range) =
inherit FSharpErrorHighlightingBase(message, range)
-[,
AttributeId = AnalysisHighlightingAttributeIds.DEADCODE,
OverlapResolve = OverlapResolveKind.NONE)>]
type DeadCodeHighlighting(range) =
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/FSharpErrorUtil.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/FSharpErrorUtil.fs
index 167a4c07ca..adb745f4aa 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/FSharpErrorUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/FSharpErrorUtil.fs
@@ -3,20 +3,21 @@ module JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings.FSha
open JetBrains.DocumentModel
open JetBrains.ReSharper.Feature.Services.Daemon
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Psi.Tree
-open JetBrains.Util
+
+let getTreeNodesDocumentRange (startNode: ITreeNode) (endNode: ITreeNode) =
+ let startOffset = startNode.GetDocumentStartOffset()
+ let endOffset = endNode.GetDocumentEndOffset()
+ DocumentRange(&startOffset, &endOffset)
let getUpcastRange (upcastExpr: IUpcastExpr) =
if not (isValid upcastExpr && isValid upcastExpr.OperatorToken) then DocumentRange.InvalidRange else
- let documentRange = upcastExpr.GetNavigationRange()
- let operatorRange = upcastExpr.OperatorToken.GetNavigationRange()
-
- DocumentRange(documentRange.Document, TextRange(operatorRange.StartOffset.Offset, documentRange.EndOffset.Offset))
+ getTreeNodesDocumentRange upcastExpr upcastExpr.OperatorToken
let getIndexerArgListRange (indexerExpr: IItemIndexerExpr) =
match indexerExpr.IndexerArgList with
@@ -28,7 +29,7 @@ let getLetTokenText (token: ITokenNode) =
let tokenType = if isNull tokenType then FSharpTokenType.LET else tokenType
tokenType.TokenRepresentation
-let getExpressionsRanges (exprs: ISynExpr seq) =
+let getExpressionsRanges (exprs: IFSharpExpression seq) =
exprs |> Seq.map (fun x -> if isValid x then x.GetHighlightingRange() else DocumentRange.InvalidRange)
let getRefExprNameRange (refExpr: IReferenceExpr) =
@@ -36,7 +37,7 @@ let getRefExprNameRange (refExpr: IReferenceExpr) =
| null -> refExpr.GetHighlightingRange()
| identifier -> identifier.GetHighlightingRange()
-let rec getUnusedExpr (expr: ISynExpr) =
+let rec getUnusedExpr (expr: IFSharpExpression) =
match expr with
| :? ILetOrUseExpr as letExpr ->
let inExpr = letExpr.InExpression
@@ -50,6 +51,17 @@ let rec getUnusedExpr (expr: ISynExpr) =
let getAttributeSuffixRange (attribute: IAttribute) =
let referenceName = attribute.ReferenceName
- if isNull referenceName || not (referenceName.ShortName |> endsWith "Attribute") then DocumentRange.InvalidRange else
+ if isNull referenceName || not (referenceName.ShortName |> endsWith "Attribute") then
+ DocumentRange.InvalidRange else
referenceName.GetDocumentEndOffset().ExtendLeft("Attribute".Length)
+
+let getQualifierRange (element: ITreeNode) =
+ match element with
+ | :? IReferenceExpr as refExpr -> getTreeNodesDocumentRange refExpr.Qualifier refExpr.Delimiter
+ | :? IReferenceName as referenceName -> getTreeNodesDocumentRange referenceName.Qualifier referenceName.Delimiter
+
+ | :? ITypeExtensionDeclaration as typeExtension ->
+ getTreeNodesDocumentRange typeExtension.QualifierReferenceName typeExtension.Delimiter
+
+ | _ -> DocumentRange.InvalidRange
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/TypeHintHighlighting.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/TypeHintHighlighting.fs
index a95f007175..41fb21b817 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/TypeHintHighlighting.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Highlightings/TypeHintHighlighting.fs
@@ -10,7 +10,7 @@ open JetBrains.UI.RichText
[)>]
[,
AttributeId = AnalysisHighlightingAttributeIds.PARAMETER_NAME_HINT,
OverlapResolve = OverlapResolveKind.NONE,
ShowToolTipInStatusBar = false)>]
@@ -20,16 +20,22 @@ type TypeHintHighlighting(typeNameString: string, range: DocumentRange) =
interface IHighlighting with
member x.ToolTip = null
member x.ErrorStripeToolTip = null
- member x.IsValid() = not text.IsEmpty && not range.IsEmpty
+ member x.IsValid() = x.IsValid()
member x.CalculateRange() = range
interface IHighlightingWithTestOutput with
member x.TestOutput = text.Text
member x.Text = text
+ member x.IsValid() = not text.IsEmpty && not range.IsEmpty
and [] TypeHintAdornmentProvider() =
interface IHighlighterIntraTextAdornmentProvider with
+ member x.IsValid(highlighter) =
+ match highlighter.UserData with
+ | :? TypeHintHighlighting as dm -> dm.IsValid()
+ | _ -> false
+
member x.CreateDataModel(highlighter) =
match highlighter.UserData with
| :? TypeHintHighlighting as thh ->
@@ -43,5 +49,6 @@ and [] TypeHintAdornmentProvider() =
override x.SelectionRange = Nullable<_>()
override x.IconId = null
override x.IsPreceding = false
+ override x.Order = 0
}
| _ -> null
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FSharpErrorsStage.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FSharpErrorsStage.fs
index c44648b8d8..657600dec0 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FSharpErrorsStage.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FSharpErrorsStage.fs
@@ -8,12 +8,15 @@ open JetBrains.ReSharper.Feature.Services.Daemon
open JetBrains.ReSharper.Plugins.FSharp.Daemon.Cs.Stages
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Psi.Tree
open JetBrains.Util
+[]
module FSharpErrorsStage =
let visualElementFactoryKey = Key("ColorUsageHighlightingEnabled")
+ let openedModulesProvider = Key("OpenedModulesProvider")
[ |])>]
@@ -27,15 +30,14 @@ type FSharpErrorsStage(elementProblemAnalyzerRegistrar) =
and FSharpErrorStageProcess(fsFile, daemonProcess, settings, analyzerRegistrar: ElementProblemAnalyzerRegistrar) =
inherit FSharpDaemonStageProcessBase(fsFile, daemonProcess)
- static let analyzerRunKind = ElementProblemAnalyzerRunKind.FullDaemon
-
+ let analyzerRunKind = ElementProblemAnalyzerRunKind.FullDaemon
let interruptCheck = daemonProcess.GetCheckForInterrupt()
- let elementProblemAnalyzerData = ElementProblemAnalyzerData(fsFile, settings, analyzerRunKind, interruptCheck)
- let analyzerDispatcher = analyzerRegistrar.CreateDispatcher(elementProblemAnalyzerData)
+ let analyzerData = ElementProblemAnalyzerData(fsFile, settings, analyzerRunKind, interruptCheck)
+ let analyzerDispatcher = analyzerRegistrar.CreateDispatcher(analyzerData)
do
- let visualElementHighlighter = VisualElementHighlighter(fsFile.Language, settings)
- elementProblemAnalyzerData.PutData(FSharpErrorsStage.visualElementFactoryKey, visualElementHighlighter)
+ analyzerData.PutData(visualElementFactoryKey, VisualElementHighlighter(fsFile.Language, settings))
+ analyzerData.PutData(openedModulesProvider, OpenedModulesProvider(fsFile))
override x.VisitNode(element: ITreeNode, consumer: IHighlightingConsumer) =
analyzerDispatcher.Run(element, consumer)
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FSharpIdentifierTooltipProvider.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FSharpIdentifierTooltipProvider.fs
index 09b4c4e2dd..493c032ade 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FSharpIdentifierTooltipProvider.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FSharpIdentifierTooltipProvider.fs
@@ -28,7 +28,7 @@ type FSharpIdentifierTooltipProvider(lifetime, solution, presenter, xmlDocServic
let [] opName = "FSharpIdentifierTooltipProvider"
- static member GetFSharpToolTipText(checkResults: FSharpCheckFileResults, token: FSharpIdentifierToken) =
+ static member GetFSharpToolTipText(userOpName: string, checkResults: FSharpCheckFileResults, token: FSharpIdentifierToken) =
// todo: fix getting qualifiers
let tokenNames = [token.Name]
@@ -37,8 +37,10 @@ type FSharpIdentifierTooltipProvider(lifetime, solution, presenter, xmlDocServic
let lineText = sourceFile.Document.GetLineText(coords.Line)
use cookie = CompilationContextCookie.GetOrCreate(sourceFile.GetPsiModule().GetContextFromModule())
+ use op = token.GetFcsCheckerService().FcsReactorMonitor.MonitorOperation userOpName
+
// todo: provide tooltip for #r strings in fsx, should pass String tag
- let getTooltip = checkResults.GetStructuredToolTipText(int coords.Line + 1, int coords.Column, lineText, tokenNames, FSharpTokenTag.Identifier)
+ let getTooltip = checkResults.GetStructuredToolTipText(int coords.Line + 1, int coords.Column, lineText, tokenNames, FSharpTokenTag.Identifier, op.OperationName)
getTooltip.RunAsTask()
override x.GetTooltip(highlighter) =
@@ -67,7 +69,7 @@ type FSharpIdentifierTooltipProvider(lifetime, solution, presenter, xmlDocServic
| Some results ->
let result = List()
- let (FSharpToolTipText layouts) = FSharpIdentifierTooltipProvider.GetFSharpToolTipText(results.CheckResults, token)
+ let (FSharpToolTipText layouts) = FSharpIdentifierTooltipProvider.GetFSharpToolTipText(opName, results.CheckResults, token)
layouts |> List.iter (function
| FSharpStructuredToolTipElement.None
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FcsErrorsStageProcessBase.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FcsErrorsStageProcessBase.fs
index 6fee9d5aba..44ed837e79 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FcsErrorsStageProcessBase.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/FcsErrorsStageProcessBase.fs
@@ -6,10 +6,10 @@ open FSharp.Compiler.SourceCodeServices
open JetBrains.DocumentModel
open JetBrains.ReSharper.Feature.Services.Daemon
open JetBrains.ReSharper.Plugins.FSharp.Daemon.Cs.Stages
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.Util
@@ -37,6 +37,8 @@ module FSharpErrors =
let [] FieldRequiresAssignment = 764
let [] ExpectedExpressionAfterLet = 588
let [] SuccessiveArgsShouldBeSpacedOrTupled = 597
+ let [] ConstructRequiresListArrayOrSequence = 747
+ let [] ConstructRequiresComputationExpression = 748
let [] EmptyRecordInvalid = 789
let [] UseBindingsIllegalInModules = 524
let [] LocalClassBindingsCannotBeInline = 894
@@ -190,6 +192,12 @@ type FcsErrorsStageProcessBase(fsFile, daemonProcess) =
| SuccessiveArgsShouldBeSpacedOrTupled ->
createHighlightingFromNode SuccessiveArgsShouldBeSpacedOrTupledError range
+ | ConstructRequiresListArrayOrSequence ->
+ createHighlightingFromNode YieldRequiresSeqExpressionError range
+
+ | ConstructRequiresComputationExpression ->
+ createHighlightingFromNode ReturnRequiresComputationExpressionError range
+
| EmptyRecordInvalid ->
createHighlightingFromNodeWithMessage EmptyRecordInvalidError range error
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/InferredTypeCodeVisionProvider.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/InferredTypeCodeVisionProvider.fs
index 1010464a37..887ff5322d 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/InferredTypeCodeVisionProvider.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/InferredTypeCodeVisionProvider.fs
@@ -19,12 +19,12 @@ open JetBrains.ReSharper.Resources.Shell
open JetBrains.Rider.Model
open JetBrains.Util
+module FSharpInferredTypeHighlighting =
+ let [] Id = "CodeInsights"
[]
+ Severity.INFO, typeof,
+ AttributeId = FSharpInferredTypeHighlighting.Id, OverlapResolve = OverlapResolveKind.NONE)>]
type FSharpInferredTypeHighlighting(range, text, provider: ICodeInsightsProvider) =
inherit CodeInsightsHighlighting(range, text, "", "Copy inferred type", provider, null, null)
@@ -58,7 +58,7 @@ type InferredTypeCodeVisionProvider() =
member x.OnExtraActionClick(_, _, _) = ()
-[]
+[ |])>]
type InferredTypeCodeVisionStage(provider: InferredTypeCodeVisionProvider) =
inherit FSharpDaemonStageBase()
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/InferredTypeHintStage.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/InferredTypeHintStage.fs
new file mode 100644
index 0000000000..7af37a7ae4
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/InferredTypeHintStage.fs
@@ -0,0 +1,190 @@
+namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Stages
+
+open System
+open FSharp.Compiler.SourceCodeServices
+open JetBrains.Application.Settings
+open JetBrains.ProjectModel
+open JetBrains.ReSharper.Feature.Services.InlayHints
+open JetBrains.ReSharper.Feature.Services.TypeNameHints
+open JetBrains.ReSharper.Plugins.FSharp
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
+open JetBrains.ReSharper.Psi
+open JetBrains.ReSharper.Psi.ExtensionsAPI
+open JetBrains.ReSharper.Psi.Naming
+open JetBrains.ReSharper.Psi.Naming.Impl
+open JetBrains.ReSharper.Psi.Tree
+open JetBrains.ReSharper.Psi.Util
+open JetBrains.ReSharper.Feature.Services.Daemon
+open JetBrains.ReSharper.Plugins.FSharp.Daemon.Cs.Stages
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
+open JetBrains.Util
+
+type LocalReferencePatternVisitor
+ (fsFile: IFSharpFile, highlightingContext: TypeNameHintHighlightingContext, namingPolicyProvider, nameParser) =
+ inherit TreeNodeVisitor()
+
+ let isTypeEvidentFromVariableNamePrefix (typ: IType) (variableNameParts: string[]) =
+ if not (typ.IsBool()) then false else
+
+ if variableNameParts.Length > 0 then
+ let prefix = variableNameParts.[0].ToLowerInvariant()
+ prefix = "has" || prefix = "is"
+ else
+ false
+
+ let isEvidentFromVariableName (fsType: FSharpType) variableName =
+ if not highlightingContext.HideTypeNameHintsWhenTypeNameIsEvidentFromVariableName then false else
+
+ let typ = fsType.MapType(EmptyList.InstanceList, fsFile.GetPsiModule())
+ if not (typ.IsValid()) then false else
+
+ let variableNameParts = NamesHelper.GetParts(nameParser, namingPolicyProvider, variableName)
+ if isTypeEvidentFromVariableNamePrefix typ variableNameParts then true else
+
+ match typ.GetTypeElement() with
+ | null -> false
+ | typeElement ->
+
+ let typeName = typeElement.ShortName
+ String.Equals(typeName, variableName, StringComparison.OrdinalIgnoreCase) ||
+ not (String.IsNullOrEmpty(typeName)) &&
+ not (String.IsNullOrEmpty(variableName)) &&
+ NamesHelper.IsLike(variableNameParts, NamesHelper.GetParts(nameParser, namingPolicyProvider, typeName))
+
+ let isTypeOfPatternEvident (pattern: IFSharpPattern) =
+
+ // v-- not evident
+ // x::y::z
+ // ^--^-- evident
+ let tuplePat = TuplePatNavigator.GetByPattern pattern
+ if isNotNull tuplePat then
+ let consPat = ConsPatNavigator.GetByPattern1 tuplePat
+ if isNull consPat then false else
+
+ // Are we nested inside another ConsPat?
+ let parentTuplePat = TuplePatNavigator.GetByPattern consPat
+ if isNull parentTuplePat then tuplePat.Patterns.IndexOf pattern <> 0 else
+ isNotNull (ConsPatNavigator.GetByPattern1 parentTuplePat)
+
+ else
+
+ // v-- not evident
+ // [x; y; z]
+ // ^--^-- evident
+ let listOrListPat = ArrayOrListPatNavigator.GetByPattern pattern
+ if isNotNull listOrListPat then
+ match Seq.tryHead listOrListPat.PatternsEnumerable with
+ | None -> false
+ | Some head -> head <> pattern
+
+ else
+
+ false
+
+ override x.VisitNode(node, context) =
+ for child in node.Children() do
+ match child with
+ | :? IFSharpTreeNode as treeNode -> treeNode.Accept(x, context)
+ | _ -> ()
+
+ override x.VisitLocalReferencePat(localRefPat, consumer) =
+ let pat = localRefPat.IgnoreParentParens()
+ if isNotNull (TypedPatNavigator.GetByPattern(pat)) then () else
+
+ let binding = BindingNavigator.GetByHeadPattern(pat)
+ if isNotNull binding && isNotNull binding.ReturnTypeInfo then () else
+
+ let variableName = localRefPat.SourceName
+ if variableName = SharedImplUtil.MISSING_DECLARATION_NAME then () else
+
+ if isTypeOfPatternEvident pat then () else
+
+ match box (localRefPat.GetFSharpSymbolUse()) with
+ | null -> ()
+ | symbolUse ->
+
+ let symbolUse = symbolUse :?> FSharpSymbolUse
+ match symbolUse.Symbol with
+ | :? FSharpMemberOrFunctionOrValue as mfv when not (isEvidentFromVariableName mfv.FullType variableName) ->
+ let typeNameStr =
+ symbolUse.DisplayContext.WithShortTypeNames(true)
+ |> mfv.FullType.Format
+
+ let range = localRefPat.GetNavigationRange().EndOffsetRange()
+
+ // todo: TypeNameHintHighlighting can be used when RIDER-39605 is resolved
+ consumer.AddHighlighting(TypeHintHighlighting(typeNameStr, range))
+ | _ -> ()
+
+type InferredTypeHintHighlightingProcess
+ (fsFile, settings: IContextBoundSettingsStore, highlightingContext: TypeNameHintHighlightingContext,
+ namingManager: NamingManager, nameParser: NameParser, daemonProcess) =
+ inherit FSharpDaemonStageProcessBase(fsFile, daemonProcess)
+
+ let namingPolicyProvider = namingManager.Policy.GetPolicyProvider(fsFile.Language, fsFile.GetSourceFile())
+ let hideHintsForEvidentTypes = highlightingContext.HideTypeNameHintsForImplicitlyTypedVariablesWhenTypeIsEvident
+
+ let visitor = LocalReferencePatternVisitor(fsFile, highlightingContext, namingPolicyProvider, nameParser)
+
+ let visitLetBindings (letBindings: ILetBindings) consumer =
+ if not highlightingContext.ShowTypeNameHintsForImplicitlyTypedVariables then () else
+
+ for binding in letBindings.Bindings do
+ if hideHintsForEvidentTypes && isTypeEvident binding.Expression then () else
+
+ match binding.HeadPattern with
+ | null -> ()
+ | headPat -> headPat.Accept(visitor, consumer)
+
+ override x.Execute(committer) =
+ let consumer = FilteringHighlightingConsumer(daemonProcess.SourceFile, fsFile, settings)
+ fsFile.ProcessThisAndDescendants(Processor(x, consumer))
+ committer.Invoke(DaemonStageResult(consumer.Highlightings))
+
+ override x.VisitLetModuleDecl(moduleDecl, consumer) =
+ visitLetBindings moduleDecl consumer
+
+ override x.VisitLetOrUseExpr(letOrUseExpr, consumer) =
+ visitLetBindings letOrUseExpr consumer
+
+ override x.VisitMemberParamsDeclaration(paramDecl, consumer) =
+ if highlightingContext.ShowTypeNameHintsForImplicitlyTypedVariables then
+ match paramDecl.Pattern with
+ | null -> ()
+ | pattern -> pattern.Accept(visitor, consumer)
+
+ override x.VisitMatchClause(matchClause, consumer) =
+ if highlightingContext.ShowTypeNameHintsForVarDeclarationsInPatternMatchingExpressions then
+ match matchClause.Pattern with
+ | null -> ()
+ | pattern -> pattern.Accept(visitor, consumer)
+
+ override x.VisitLambdaExpr(lambdaExpr, consumer) =
+ if not highlightingContext.ShowTypeNameHintsForLambdaExpressionParameters then () else
+
+ for pattern in lambdaExpr.Patterns do
+ if isNotNull pattern then
+ pattern.Accept(visitor, consumer)
+
+[ |])>]
+type InferredTypeHintStage(namingManager: NamingManager, nameParser: NameParser) =
+ inherit FSharpDaemonStageBase()
+
+ override x.IsSupported(sourceFile, processKind) =
+ processKind = DaemonProcessKind.VISIBLE_DOCUMENT &&
+ base.IsSupported(sourceFile, processKind) &&
+ not (sourceFile.LanguageType.Is())
+
+ override x.CreateStageProcess(fsFile, settings, daemonProcess) =
+ let context = TypeNameHintHighlightingContext(settings)
+
+ let isEnabled =
+ context.ShowTypeNameHintsForImplicitlyTypedVariables ||
+ context.ShowTypeNameHintsForLambdaExpressionParameters ||
+ context.ShowTypeNameHintsForVarDeclarationsInPatternMatchingExpressions
+
+ if not isEnabled then null else
+ InferredTypeHintHighlightingProcess(fsFile, settings, context, namingManager, nameParser, daemonProcess) :> _
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/PipeChainTypeHintStage.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/PipeChainTypeHintStage.fs
index ffdd35a5c5..6def987630 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/PipeChainTypeHintStage.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/PipeChainTypeHintStage.fs
@@ -8,10 +8,10 @@ open JetBrains.ProjectModel
open JetBrains.ReSharper.Daemon.Stages
open JetBrains.ReSharper.Plugins.FSharp
open JetBrains.ReSharper.Plugins.FSharp.Daemon.Stages.Tooltips
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Settings
open JetBrains.ReSharper.Psi.Tree
open JetBrains.ReSharper.Feature.Services.Daemon
@@ -81,7 +81,7 @@ type PipeChainHighlightingProcess(logger: ILogger, fsFile, settings: IContextBou
for token, exprToAdorn in exprs do
if daemonProcess.InterruptFlag then raise <| OperationCanceledException()
- let (FSharpToolTipText layouts) = FSharpIdentifierTooltipProvider.GetFSharpToolTipText(checkResults, token)
+ let (FSharpToolTipText layouts) = FSharpIdentifierTooltipProvider.GetFSharpToolTipText(opName, checkResults, token)
// The |> operator should have one overload and two type parameters
match layouts with
@@ -137,7 +137,7 @@ type PipeChainHighlightingProcess(logger: ILogger, fsFile, settings: IContextBou
committer.Invoke(DaemonStageResult remainingHighlightings)
-[ |])>]
+[ |])>]
type PipeChainTypeHintStage(logger: ILogger) =
inherit FSharpDaemonStageBase()
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/ScriptLoadPathsStage.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/ScriptLoadPathsStage.fs
index 917b4d44b5..f784e851ec 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/ScriptLoadPathsStage.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/ScriptLoadPathsStage.fs
@@ -52,7 +52,7 @@ type ScriptLoadPathsStageProcess(fsFile, daemonProcess) =
fsFile.Accept(visitor)
if allDirectives.IsEmpty() then () else
- match fsFile.CheckerService.OptionsProvider.GetProjectOptions(daemonProcess.SourceFile) with
+ match fsFile.CheckerService.FcsProjectProvider.GetProjectOptions(daemonProcess.SourceFile) with
| Some options when not options.OriginalLoadReferences.IsEmpty ->
let document = daemonProcess.Document
let linesCount = document.GetLineCount() |> int
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/UnusedOpensStage.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/UnusedOpensStage.fs
index 78caa3272f..3d4c83dac5 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/UnusedOpensStage.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Daemon/Stages/UnusedOpensStage.fs
@@ -7,9 +7,9 @@ open JetBrains.ReSharper.Feature.Services.Daemon
open JetBrains.ReSharper.Plugins.FSharp
open JetBrains.ReSharper.Plugins.FSharp.Daemon.Cs
open JetBrains.ReSharper.Plugins.FSharp.Daemon.Cs.Stages
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Resources.Shell
open JetBrains.Util
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Debugger/FSharpExpressionEvaluationInfoProvider.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Debugger/FSharpExpressionEvaluationInfoProvider.fs
index aff5558464..bfb3723972 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Debugger/FSharpExpressionEvaluationInfoProvider.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Debugger/FSharpExpressionEvaluationInfoProvider.fs
@@ -11,14 +11,14 @@ open JetBrains.ReSharper.Psi.Tree
[)>]
type FSharpExpressionEvaluationInfoProvider() =
- static let rec getTextToEvaluate (expr: ISynExpr) =
+ static let rec getTextToEvaluate (expr: IFSharpExpression) =
match expr with
| :? IReferenceExpr as refExpr ->
let declaredElement = refExpr.Reference.Resolve().DeclaredElement
if declaredElement :? ISelfId then "this" else
let shortName = refExpr.ShortName
- if shortName == SharedImplUtil.MISSING_DECLARATION_NAME then null else
+ if shortName = SharedImplUtil.MISSING_DECLARATION_NAME then null else
let qualifier = getTextToEvaluate refExpr.Qualifier
if isNull qualifier then shortName else qualifier + "." + shortName
@@ -43,12 +43,12 @@ type FSharpExpressionEvaluationInfoProvider() =
| _ -> null
- static member GetTextToEvaluate(expr: ISynExpr) =
+ static member GetTextToEvaluate(expr: IFSharpExpression) =
getTextToEvaluate expr
interface IExpressionEvaluationInfoProvider with
member x.FindExpression(file, range, _) =
- let expr = file.GetNode(range)
+ let expr = file.GetNode(range)
let exprName = getTextToEvaluate expr
if isNotNull exprName then
EvaluationExpressionInfo(expr, exprName, expr.GetText())
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/ExtendSelection/FSharpExtendSelectionProvider.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/ExtendSelection/FSharpExtendSelectionProvider.fs
index 8da81d2db2..ef087fa03b 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/ExtendSelection/FSharpExtendSelectionProvider.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/ExtendSelection/FSharpExtendSelectionProvider.fs
@@ -7,10 +7,10 @@ open JetBrains.ProjectModel
open JetBrains.ReSharper.Feature.Services.Editor
open JetBrains.ReSharper.Feature.Services.SelectEmbracingConstruct
open JetBrains.ReSharper.Plugins.FSharp
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Psi.Parsing
@@ -46,14 +46,14 @@ type FSharpExtendSelectionProvider(settingsStore: ISettingsStore) =
null
- | :? ISynPat as synPat ->
- let matchClause = MatchClauseNavigator.GetByPattern(synPat)
+ | :? IFSharpPattern as fsPattern ->
+ let matchClause = MatchClauseNavigator.GetByPattern(fsPattern)
if isNotNull matchClause && isNotNull matchClause.WhenExpression then
- FSharpTreeRangeSelection(fsFile, synPat, matchClause.WhenExpression) :> _ else
+ FSharpTreeRangeSelection(fsFile, fsPattern, matchClause.WhenExpression) :> _ else
null
- | :? ISynExpr as expr ->
+ | :? IFSharpExpression as expr ->
let attribute = AttributeNavigator.GetByExpression(expr)
if isNotNull attribute && isNotNull attribute.ReferenceName && isNotNull attribute.ArgExpression then
FSharpTreeRangeSelection(fsFile, attribute.ReferenceName, attribute.ArgExpression) :> _ else
@@ -63,13 +63,13 @@ type FSharpExtendSelectionProvider(settingsStore: ISettingsStore) =
FSharpTreeRangeSelection(fsFile, typeInherit.TypeName, typeInherit.CtorArg) :> _ else
let binding = BindingNavigator.GetByExpression(expr)
- let letExpr = LetLikeExprNavigator.GetByBinding(binding)
+ let letExpr = LetOrUseExprNavigator.GetByBinding(binding)
if isNotNull letExpr then
FSharpExtendSelectionProvider.CreateLetBindingSelection(fsFile, letExpr, binding) else
null
- | :? IWhenExpr as whenExpr ->
+ | :? IWhenExprClause as whenExpr ->
let matchClause = MatchClauseNavigator.GetByWhenExpression(whenExpr)
if isNotNull matchClause && isNotNull matchClause.Pattern then
FSharpTreeRangeSelection(fsFile, matchClause.Pattern, whenExpr) :> _ else
@@ -77,7 +77,7 @@ type FSharpExtendSelectionProvider(settingsStore: ISettingsStore) =
null
| :? IBinding as binding ->
- let letBindings = LetNavigator.GetByBinding(binding)
+ let letBindings = LetBindingsNavigator.GetByBinding(binding)
if isNotNull letBindings then
FSharpExtendSelectionProvider.CreateLetBindingSelection(fsFile, letBindings, binding) else
@@ -92,7 +92,7 @@ type FSharpExtendSelectionProvider(settingsStore: ISettingsStore) =
| :? ITokenNode as token ->
match token.Parent with
- | :? ILet as letExpr ->
+ | :? ILetBindings as letExpr ->
let bindings = letExpr.Bindings
if bindings.IsEmpty then null else
@@ -121,12 +121,12 @@ type FSharpExtendSelectionProvider(settingsStore: ISettingsStore) =
if not (shouldTryFindBetterNode node) then null else
FSharpExtendSelectionProvider.ExtendNodeSelection(fsFile, node)
- static member CreateLetBindingSelection(fsFile, letBindings: ILet): ISelectedRange =
+ static member CreateLetBindingSelection(fsFile, letBindings: ILetBindings): ISelectedRange =
let bindings = letBindings.Bindings
if bindings.IsEmpty then null else
FSharpExtendSelectionProvider.CreateLetBindingSelection(fsFile, letBindings, bindings.[0])
- static member CreateLetBindingSelection(fsFile, letExpr: ILet, binding): ISelectedRange =
+ static member CreateLetBindingSelection(fsFile, letExpr: ILetBindings, binding): ISelectedRange =
let bindings = letExpr.Bindings
if bindings.[0] == binding then
FSharpLetExprBindingSelection(fsFile, letExpr, letExpr.FirstChild, binding) :> _ else
@@ -266,10 +266,10 @@ and FSharpTokenPartSelection(fsFile, treeTextRange, token) =
FSharpTreeNodeSelection(fsFile, token) :> _
-and FSharpLetExprBindingSelection(fsFile: IFSharpFile, letBindings: ILet, first: ITreeNode, last: ITreeNode) =
+and FSharpLetExprBindingSelection(fsFile: IFSharpFile, letBindings: ILetBindings, first: ITreeNode, last: ITreeNode) =
inherit FSharpTreeRangeSelection(fsFile, first, last)
override x.Parent =
match letBindings with
- | :? ILetLikeExpr -> FSharpTreeRangeSelection(fsFile, letBindings.FirstChild, letBindings.Bindings.Last()) :> _
+ | :? ILetOrUseExpr -> FSharpTreeRangeSelection(fsFile, letBindings.FirstChild, letBindings.Bindings.Last()) :> _
| _ -> FSharpTreeNodeSelection(fsFile, letBindings) :> _
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Foldings/FSharpCodeFoldings.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Foldings/FSharpCodeFoldings.fs
index 948cfd3261..373fb79961 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Foldings/FSharpCodeFoldings.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Foldings/FSharpCodeFoldings.fs
@@ -1,4 +1,4 @@
-namespace rec JetBrains.ReSharper.Plugins.FSharp.Services.Foldings
+namespace JetBrains.ReSharper.Plugins.FSharp.Services.Foldings
open FSharp.Compiler.SourceCodeServices
open FSharp.Compiler.SourceCodeServices.Structure
@@ -12,14 +12,15 @@ open JetBrains.ReSharper.Psi
open JetBrains.TextControl.DocumentMarkup
open JetBrains.Util
-[)>]
-type FSharpCodeFoldingProcessFactory(logger: ILogger) =
- interface ICodeFoldingProcessorFactory with
- member x.CreateProcessor() =
- FSharpCodeFoldingProcess(logger) :> _
+module FSharpCodeFoldingAttributes =
+ let [] HashDirective = "ReSharper F# Hash Directives Block Folding"
+
+
+[]
+type FSharpCodeFoldingAttributes() = class end
-and FSharpCodeFoldingProcess(logger: ILogger) =
+type FSharpCodeFoldingProcess(logger: ILogger) =
inherit TreeNodeVisitor()
let mutable processingFinished = false
@@ -80,9 +81,8 @@ and FSharpCodeFoldingProcess(logger: ILogger) =
| _ -> ()
-module FSharpCodeFoldingAttributes =
- let [] HashDirective = "ReSharper F# Hash Directives Block Folding"
-
-
-[]
-do ()
+[)>]
+type FSharpCodeFoldingProcessFactory(logger: ILogger) =
+ interface ICodeFoldingProcessorFactory with
+ member x.CreateProcessor() =
+ FSharpCodeFoldingProcess(logger) :> _
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Formatter/FSharpReformatCode.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Formatter/FSharpReformatCode.fs
index 08c3790b56..17156a963b 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Formatter/FSharpReformatCode.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Formatter/FSharpReformatCode.fs
@@ -10,7 +10,6 @@ open JetBrains.ReSharper.Feature.Services.CSharp.CodeCleanup
open JetBrains.ReSharper.Feature.Services.CodeCleanup
open JetBrains.ReSharper.Plugins.FSharp
open JetBrains.ReSharper.Plugins.FSharp.Psi
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Psi.Tree
@@ -28,7 +27,7 @@ type FSharpReformatCode() =
member x.SetDefaultSetting(_, _) = ()
member x.IsAvailable(sourceFile) = sourceFile.PrimaryPsiLanguage :? FSharpLanguage
- member x.Process(sourceFile, rangeMarker, profile, _) =
+ member x.Process(sourceFile, rangeMarker, profile, _, _) =
if not (profile.GetSetting(ReformatCode.REFORMAT_CODE_DESCRIPTOR)) then () else
let fsFile = sourceFile.FSharpFile
@@ -67,7 +66,7 @@ type FSharpReformatCode() =
let stamp = document.LastModificationStamp
let modificationSide = TextModificationSide.NotSpecified
let newLineText = sourceFile.DetectLineEnding().GetPresentation()
- let parsingOptions = checkerService.OptionsProvider.GetParsingOptions(sourceFile)
+ let parsingOptions = checkerService.FcsProjectProvider.GetParsingOptions(sourceFile)
let checker = checkerService.Checker
let change =
@@ -85,7 +84,7 @@ type FSharpReformatCode() =
Some(DocumentChange(document, offset, oldLength, formatted, stamp, modificationSide))
with _ -> None
else
- let parsingOptions = checkerService.OptionsProvider.GetParsingOptions(sourceFile)
+ let parsingOptions = checkerService.FcsProjectProvider.GetParsingOptions(sourceFile)
let defines = parsingOptions.ConditionalCompilationDefines
let formatTask =
if List.isEmpty defines
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Fsi/FsiHost.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Fsi/FsiHost.fs
index c63d952809..ab3b1da8a4 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Fsi/FsiHost.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Fsi/FsiHost.fs
@@ -60,7 +60,7 @@ type FsiHost
let assemblyFilter (assembly: IPsiAssembly) =
let assemblyName = assembly.AssemblyName
- not (isFSharpCore assemblyName || assemblyName.PossiblyContainsPredefinedTypes())
+ not (FSharpAssemblyUtil.isFSharpCore assemblyName || assemblyName.PossiblyContainsPredefinedTypes())
let getProjectReferences projectId =
use cookie = ReadLockCookie.Create()
@@ -69,12 +69,20 @@ type FsiHost
let targetFrameworkId = project.GetCurrentTargetFrameworkId()
let psiModule = psiModules.GetPrimaryPsiModule(project, targetFrameworkId)
- getReferencePaths assemblyFilter psiModule
+ getReferencedModules psiModule
+ |> Seq.filter (fun psiModule ->
+ match psiModule with
+ | :? IAssemblyPsiModule as assemblyModule -> assemblyFilter assemblyModule.Assembly
+ | _ -> true)
+ |> Seq.map getModuleFullPath
+ |> List
do
let rdFsiHost = solution.RdFSharpModel().FSharpInteractiveHost
rdFsiHost.RequestNewFsiSessionInfo.Set(getNewFsiSessionInfo)
rdFsiHost.GetProjectReferences.Set(getProjectReferences)
+
+ rdFsiHost.FsiTools.PrepareCommands.Set(FsiTools.prepareCommands)
fsiOptions.MoveCaretOnSendLine.FlowInto(lifetime, rdFsiHost.MoveCaretOnSendLine)
fsiOptions.ExecuteRecent.FlowInto(lifetime, rdFsiHost.CopyRecentToEditor)
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Fsi/FsiTools.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Fsi/FsiTools.fs
new file mode 100644
index 0000000000..4d3684260d
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Fsi/FsiTools.fs
@@ -0,0 +1,14 @@
+namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Fsi
+
+open JetBrains.Rider.Model
+
+module FsiTools =
+ let wrapCommand (commandIndex: int, command: string) =
+ "[]\nmodule module" + (commandIndex + 1).ToString() + "=\n " + command.Replace("\n", "\n ") + "\n ignore\n"
+
+
+ let prepareCommands (rdFsiPrepareCommandsArgs: RdFsiPrepareCommandsArgs): ResizeArray =
+ let firstCommandIndex = rdFsiPrepareCommandsArgs.FirstCommandIndex
+ let commands: ResizeArray = rdFsiPrepareCommandsArgs.Commands
+
+ commands |> Seq.mapi(fun i x -> wrapCommand(firstCommandIndex + i, x)) |> ResizeArray
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ElifToIfAction.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ElifToIfAction.fs
index a1f9484c18..9e498cbf47 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ElifToIfAction.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ElifToIfAction.fs
@@ -3,10 +3,10 @@ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Intentions
open System
open JetBrains.ReSharper.Feature.Services.ContextActions
open JetBrains.ReSharper.Feature.Services.Util
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Psi.Tree
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/IfToElifAction.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/IfToElifAction.fs
index 90295632a3..599d04d4f1 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/IfToElifAction.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/IfToElifAction.fs
@@ -2,10 +2,10 @@ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Intentions
open System
open JetBrains.ReSharper.Feature.Services.ContextActions
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Psi.Tree
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/InvertIfAction.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/InvertIfAction.fs
index b71e04b5e4..b4089f8b16 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/InvertIfAction.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/InvertIfAction.fs
@@ -1,11 +1,11 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Intentions
open JetBrains.ReSharper.Feature.Services.ContextActions
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToLiteralAction.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToLiteralAction.fs
index a34fa02e85..48dd41ea67 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToLiteralAction.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToLiteralAction.fs
@@ -1,9 +1,9 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Intentions
open JetBrains.ReSharper.Feature.Services.ContextActions
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.Tree
open JetBrains.ReSharper.Resources.Shell
@@ -22,8 +22,8 @@ type ToLiteralAction(dataProvider: FSharpContextActionDataProvider) =
FSharpAttributesUtil.addAttributesList binding false
binding.AttributeLists.[0]
- let rec isSimplePattern (pat: ISynPat): bool =
- match pat with
+ let rec isSimplePattern (fsPattern: IFSharpPattern): bool =
+ match fsPattern with
| :? IReferencePat as refPat ->
let referenceName = refPat.ReferenceName
isNotNull referenceName && isNull referenceName.Qualifier
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToModuleNamespaceDeclarationAction.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToModuleNamespaceDeclarationAction.fs
index 6c09e05973..7e3ff8108e 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToModuleNamespaceDeclarationAction.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToModuleNamespaceDeclarationAction.fs
@@ -1,10 +1,10 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Intentions
open JetBrains.ReSharper.Feature.Services.ContextActions
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Psi.Tree
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToMultilineRecord.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToMultilineRecord.fs
index 10b55539fb..2b5d6d339c 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToMultilineRecord.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToMultilineRecord.fs
@@ -2,9 +2,9 @@ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Intentions
open JetBrains.ReSharper.Feature.Services.ContextActions
open JetBrains.ReSharper.Feature.Services.Util
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToMutableAction.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToMutableAction.fs
index 0a54cb08ed..32e2282598 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToMutableAction.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Intentions/ToMutableAction.fs
@@ -1,8 +1,8 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Intentions
open JetBrains.ReSharper.Feature.Services.ContextActions
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.DeclaredElement
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.Tree
// todo: fix mutable inside binding range, then replace IRecordField usage below
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpBreadcrumbsHelper.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpBreadcrumbsHelper.fs
index af5cb6803d..e4b9985f54 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpBreadcrumbsHelper.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpBreadcrumbsHelper.fs
@@ -11,4 +11,4 @@ type FSharpBreadcrumbsHelper() =
inherit BreadcrumbsHelperBase()
override x.IsApplicable(declaration) =
- declaration :? ITypeMemberDeclaration && not (declaration :? ISynPat)
+ declaration :? ITypeMemberDeclaration && not (declaration :? IFSharpPattern)
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpDeclaredElementIconProvider.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpDeclaredElementIconProvider.fs
index cbfb6fc861..9d6c1c9b7f 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpDeclaredElementIconProvider.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpDeclaredElementIconProvider.fs
@@ -27,7 +27,7 @@ type FSharpDeclaredElementIconProvider() =
canApplyExtensions <- true
match declaredElement with
- | :? IModule -> FSharpIcons.FSharpModule.Id
+ | :? IFSharpModule -> FSharpIcons.FSharpModule.Id
| :? IUnionCase as unionCase ->
canApplyExtensions <- false
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpElementFactory.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpElementFactory.fs
index a9f7600c7f..f2c07dd72d 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpElementFactory.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpElementFactory.fs
@@ -7,7 +7,6 @@ open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.CodeStyle
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Psi.Modules
@@ -28,7 +27,7 @@ type FSharpElementFactory(languageService: IFSharpLanguageService, psiModule: IP
let document = createDocument source
let parser = languageService.CreateParser(document)
- let fsFile = parser.ParseFSharpFile(StandaloneDocument = document)
+ let fsFile = parser.ParseFSharpFile(noCache = true, StandaloneDocument = document)
SandBox.CreateSandBoxFor(fsFile, psiModule)
fsFile
@@ -58,11 +57,6 @@ type FSharpElementFactory(languageService: IFSharpLanguageService, psiModule: IP
let newExpr = getExpression source
newExpr.As().InnerExpression.As()
- let createParenExpr (expr: ISynExpr) =
- let parenExpr = getExpression "(())" :?> IParenExpr
- ModificationUtil.ReplaceChild(parenExpr.InnerExpression, expr.Copy()) |> ignore
- parenExpr
-
let createAttributeList attrName: IAttributeList =
let source = sprintf "[<%s>] ()" attrName
let doDecl = getDoDecl source
@@ -120,9 +114,6 @@ type FSharpElementFactory(languageService: IFSharpLanguageService, psiModule: IP
addParensIfNeeded newArg |> ignore
newExpr
- member x.CreateAppExpr(addSpace) =
- createAppExpr addSpace
-
member x.CreateAppExpr(funExpr, argExpr, addSpace) =
let appExpr = createAppExpr addSpace
appExpr.SetFunctionExpression(funExpr.Copy()) |> ignore
@@ -169,9 +160,6 @@ type FSharpElementFactory(languageService: IFSharpLanguageService, psiModule: IP
member x.CreateParenExpr() =
getExpression "(())" :?> _
- member x.CreateParenExpr(expr) =
- createParenExpr expr
-
member x.AsReferenceExpr(typeReference: ITypeReferenceName) =
getExpression (typeReference.GetText()) :?> _
@@ -186,7 +174,7 @@ type FSharpElementFactory(languageService: IFSharpLanguageService, psiModule: IP
let forExpr = getExpression "for _ in () do ()" :?> IForEachExpr
- let expr = ModificationUtil.ReplaceChild(forExpr.InClause, expr.Copy())
+ let expr = ModificationUtil.ReplaceChild(forExpr.InExpression, expr.Copy())
let whitespace = ModificationUtil.ReplaceChild(forExpr.DoExpression.PrevSibling, Whitespace(indent))
ModificationUtil.AddChildBefore(whitespace, NewLine(expr.GetLineEnding())) |> ignore
@@ -195,7 +183,7 @@ type FSharpElementFactory(languageService: IFSharpLanguageService, psiModule: IP
member x.CreateExpr(text) =
getExpression text
- member x.CreateBinaryAppExpr(text, arg1: ISynExpr, arg2: ISynExpr) =
+ member x.CreateBinaryAppExpr(text, arg1: IFSharpExpression, arg2: IFSharpExpression) =
let source = "() " + text + " ()"
let expr = getExpression source
let appExpr = expr :?> IBinaryAppExpr
@@ -208,7 +196,7 @@ type FSharpElementFactory(languageService: IFSharpLanguageService, psiModule: IP
expr
- member x.CreateSetExpr(left: ISynExpr, right: ISynExpr) =
+ member x.CreateSetExpr(left: IFSharpExpression, right: IFSharpExpression) =
let source = "() <- ()"
let expr = getExpression source
let setExpr = expr :?> ISetExpr
@@ -221,6 +209,16 @@ type FSharpElementFactory(languageService: IFSharpLanguageService, psiModule: IP
expr
+ member x.CreateExpressionReferenceName(name) =
+ let source = sprintf "let %s = ()" name
+ let letModuleDecl = getModuleMember source :?> ILetModuleDecl
+ letModuleDecl.Bindings.[0].HeadPattern.As().ReferenceName
+
+ member x.CreateTypeReferenceName(name) =
+ let source = sprintf "type T = %s" name
+ let typeDeclarationGroup = getModuleMember source :?> ITypeDeclarationGroup
+ let typeAbbreviation = typeDeclarationGroup.TypeDeclarations.[0].As()
+ typeAbbreviation.AbbreviatedType.As().ReferenceName
member x.CreateEmptyAttributeList() =
let attributeList = createAttributeList "Foo"
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpImportTypeHelper.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpImportTypeHelper.fs
index 1ac9c6375c..869ae4efde 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpImportTypeHelper.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpImportTypeHelper.fs
@@ -5,6 +5,7 @@ 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.Features.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
@@ -98,15 +99,20 @@ type FSharpImportTypeHelper() =
[)>]
type FSharpQuickFixUtilComponent() =
+ let [] FcsOpName = "FSharpQuickFixUtilComponent.BindTo"
+
interface IQuickFixUtilComponent with
member x.BindTo(reference, typeElement, _, _) =
let reference = reference :?> FSharpSymbolReference
- let context = reference.GetElement()
- let fsFile = context.FSharpFile
- let settings = fsFile.GetSettingsStore()
- let moduleToOpen = getModuleToOpen typeElement
+ let referenceOwner = reference.GetElement()
+ use writeCookie = WriteLockCookie.Create(referenceOwner.IsPhysical())
+ FSharpReferenceBindingUtil.SetRequiredQualifiers(reference, typeElement)
+ if FSharpResolveUtil.resolvesToQualified typeElement reference FcsOpName then reference :> _ else
+
+ let moduleToOpen = getModuleToOpen typeElement
+ let fsFile = referenceOwner.FSharpFile
let namingService = NamingManager.GetNamingLanguageService(fsFile.Language)
let nameToOpen =
@@ -118,8 +124,8 @@ type FSharpQuickFixUtilComponent() =
if nameToOpen.IsNullOrEmpty() then reference :> _ else
- use writeCookie = WriteLockCookie.Create(context.IsPhysical())
- addOpen (context.GetDocumentStartOffset()) fsFile settings nameToOpen
+ let settings = fsFile.GetSettingsStore()
+ addOpen (referenceOwner.GetDocumentStartOffset()) fsFile settings nameToOpen
reference :> _
member x.AddImportsForExtensionMethod(reference, _) = reference
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpLanguageService.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpLanguageService.fs
index f531d5581a..10b7863126 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpLanguageService.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpLanguageService.fs
@@ -12,7 +12,6 @@ open JetBrains.ReSharper.Plugins.FSharp.Psi.LanguageService.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Services.Formatter
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Psi.CSharp.Impl
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpLanguageSpecificCopyPasteBehavior.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpLanguageSpecificCopyPasteBehavior.fs
new file mode 100644
index 0000000000..3b1fab852a
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpLanguageSpecificCopyPasteBehavior.fs
@@ -0,0 +1,10 @@
+namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.LanguageService
+
+open JetBrains.ReSharper.Feature.Services.Clipboard
+open JetBrains.ReSharper.Plugins.FSharp.Psi
+open JetBrains.ReSharper.Psi
+
+[)>]
+type FSharpLanguageSpecificCopyPasteBehavior() =
+ interface ILanguageSpecificCopyPasteBehavior with
+ member x.AllowSmartCopyPaste _ = false
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpProjectFileLanguageService.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpProjectFileLanguageService.fs
index a2dfb4a3de..d318a8519a 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpProjectFileLanguageService.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpProjectFileLanguageService.fs
@@ -24,7 +24,7 @@ type FSharpProjectFileLanguageService
| null -> FSharpLanguage.Instance.LanguageService().GetPrimaryLexerFactory()
| _ ->
- let defines = fsCheckerService.OptionsProvider.GetParsingOptions(sourceFile).ConditionalCompilationDefines
+ let defines = fsCheckerService.FcsProjectProvider.GetParsingOptions(sourceFile).ConditionalCompilationDefines
FSharpPreprocessedLexerFactory(defines) :> _
override x.GetPsiProperties(projectFile, sourceFile, isCompileService) =
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpQuickDefinitionService.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpQuickDefinitionService.fs
index e8378a3e04..46d093239b 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpQuickDefinitionService.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpQuickDefinitionService.fs
@@ -13,9 +13,9 @@ type FSharpQuickDefinitionService() =
override x.GetPresentableTreeRange(node) =
match node with
- | :? ISynPat as pat ->
- let pat = skipIntermediatePatParents pat
- let binding = BindingNavigator.GetByHeadPattern(pat)
- TreeRange(LetNavigator.GetByBinding(binding)) :> _
+ | :? IFSharpPattern as fsPattern ->
+ let fsPattern = skipIntermediatePatParents fsPattern
+ let binding = BindingNavigator.GetByHeadPattern(fsPattern)
+ TreeRange(LetBindingsNavigator.GetByBinding(binding)) :> _
| _ -> base.GetPresentableTreeRange(node)
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/SandboxDocumentLanguageSupportFSharpScript.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/SandboxDocumentLanguageSupportFSharpScript.fs
new file mode 100644
index 0000000000..94f223cf85
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/SandboxDocumentLanguageSupportFSharpScript.fs
@@ -0,0 +1,16 @@
+namespace JetBrains.ReSharper.Plugins.FSharp.Psi.LanguageService
+
+open JetBrains.ProjectModel
+open JetBrains.ReSharper.Host.Features.Documents
+open JetBrains.ReSharper.Plugins.FSharp
+open JetBrains.ReSharper.Plugins.FSharp.Psi
+open JetBrains.ReSharper.Psi
+
+
+[)>]
+type SandboxDocumentLanguageSupportFSharpScript() =
+ interface ISandboxDocumentLanguageSupport with
+ member x.DocumentFileExtension = FSharpScriptProjectFileType.FsScriptExtension
+ member x.ProjectFileType = FSharpScriptProjectFileType.Instance :> ProjectFileType
+ member x.SetupSandboxFile(sandboxFile, sandboxInfo, lifetime) = ()
+ member x.GetExtraInfos(sandboxDocumentInfo) = null
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpImplTreeBuilder.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpImplTreeBuilder.fs
index b3bc19489e..3bb32335e3 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpImplTreeBuilder.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpImplTreeBuilder.fs
@@ -413,8 +413,11 @@ type FSharpImplTreeBuilder(lexer, document, decls, lifetime, projectedOffset, li
| lid ->
x.ProcessReferenceName(lid)
- x.ProcessPatternParams(args, isLocal || isTopLevelPat, false)
- if isLocal then ElementType.LOCAL_PARAMETERS_OWNER_PAT else ElementType.TOP_PARAMETERS_OWNER_PAT
+ if args.IsEmpty then
+ if isLocal then ElementType.LOCAL_REFERENCE_PAT else ElementType.TOP_REFERENCE_PAT
+ else
+ x.ProcessPatternParams(args, isLocal || isTopLevelPat, false)
+ if isLocal then ElementType.LOCAL_PARAMETERS_OWNER_PAT else ElementType.TOP_PARAMETERS_OWNER_PAT
| SynPat.Typed(pat, synType, _) ->
x.ProcessPat(pat, isLocal, false)
@@ -519,12 +522,12 @@ type FSharpImplTreeBuilder(lexer, document, decls, lifetime, projectedOffset, li
let mark = x.Mark(range)
x.ProcessPat(pat, isLocal, false)
- x.Done(range, mark, ElementType.MEMBER_PARAM_DECLARATION)
+ x.Done(range, mark, ElementType.MEMBER_PARAMS_DECLARATION)
member x.MarkOtherType(TypeRange range as typ) =
let mark = x.Mark(range)
x.ProcessType(typ)
- x.Done(range, mark, ElementType.OTHER_TYPE)
+ x.Done(range, mark, ElementType.UNSUPPORTED_TYPE_USAGE)
member x.SkipOuterAttrs(attrs: SynAttributeList list, outerRange: range) =
match attrs with
@@ -664,10 +667,13 @@ type FSharpExpressionTreeBuilder(lexer, document, lifetime, projectedOffset, lin
x.ProcessExpressionList(exprs)
| SynExpr.ArrayOrList(_, exprs, _) ->
- x.ProcessListExpr(exprs, range, ElementType.ARRAY_OR_LIST_EXPR)
+ // SynExpr.ArrayOrList is currently only used for error recovery and empty lists in the parser.
+ // Non-empty SynExpr.ArrayOrList is created in the type checker only.
+ Assertion.Assert(List.isEmpty exprs, "Non-empty SynExpr.ArrayOrList: {0}", expr)
+ x.MarkAndDone(range, ElementType.ARRAY_OR_LIST_EXPR)
| SynExpr.AnonRecd(_, copyInfo, fields, _) ->
- x.PushRange(range, ElementType.ANON_RECD_EXPR)
+ x.PushRange(range, ElementType.ANON_RECORD_EXPR)
x.PushStepList(fields, anonRecordFieldListProcessor)
match copyInfo with
| Some(expr, _) -> x.ProcessExpression(expr)
@@ -714,7 +720,8 @@ type FSharpExpressionTreeBuilder(lexer, document, lifetime, projectedOffset, lin
x.ProcessExpression(enumExpr)
| SynExpr.ArrayOrListOfSeqExpr(_, expr, _) ->
- x.PushRangeAndProcessExpression(expr, range, ElementType.ARRAY_OR_LIST_OF_SEQ_EXPR)
+ let expr = match expr with | SynExpr.CompExpr(expr = expr) -> expr | _ -> expr
+ x.PushRangeAndProcessExpression(expr, range, ElementType.ARRAY_OR_LIST_EXPR)
| SynExpr.CompExpr(_, _, expr, _) ->
x.PushRangeAndProcessExpression(expr, range, ElementType.COMPUTATION_EXPR)
@@ -904,12 +911,20 @@ type FSharpExpressionTreeBuilder(lexer, document, lifetime, projectedOffset, lin
| SynExpr.ImplicitZero _ -> ()
- | SynExpr.YieldOrReturn(_, expr, _)
+ | SynExpr.YieldOrReturn(_, expr, _) ->
+ x.AdvanceToStart(range)
+ if x.TokenType == FSharpTokenType.RARROW then
+ // Remove fake yield expressions in list comprehensions
+ // by replacing `-> a` with `a` in `[ for a in 1 .. 2 -> a ]`.
+ x.ProcessExpression(expr)
+ else
+ x.PushRangeAndProcessExpression(expr, range, ElementType.YIELD_OR_RETURN_EXPR)
+
| SynExpr.YieldOrReturnFrom(_, expr, _) ->
x.PushRangeAndProcessExpression(expr, range, ElementType.YIELD_OR_RETURN_EXPR)
| SynExpr.LetOrUseBang(_, _, _, pat, expr, ands, inExpr, range) ->
- x.PushRange(range, ElementType.LET_OR_USE_BANG_EXPR)
+ x.PushRange(range, ElementType.LET_OR_USE_EXPR)
x.PushExpression(inExpr)
x.PushStepList(ands, andLocalBindingListProcessor)
x.PushRangeForMark(expr.Range, x.Mark(pat.Range), ElementType.LOCAL_BINDING)
@@ -930,10 +945,12 @@ type FSharpExpressionTreeBuilder(lexer, document, lifetime, projectedOffset, lin
x.MarkAndDone(range, ElementType.LIBRARY_ONLY_EXPR)
| SynExpr.ArbitraryAfterError _
- | SynExpr.FromParseError _
| SynExpr.DiscardAfterMissingQualificationAfterDot _ ->
x.MarkAndDone(range, ElementType.FROM_ERROR_EXPR)
+ | SynExpr.FromParseError(expr, _) ->
+ x.PushRangeAndProcessExpression(expr, range, ElementType.FROM_ERROR_EXPR)
+
| SynExpr.Fixed(expr, _) ->
x.PushRangeAndProcessExpression(expr, range, ElementType.FIXED_EXPR)
@@ -970,10 +987,10 @@ type FSharpExpressionTreeBuilder(lexer, document, lifetime, projectedOffset, lin
// Range sequence expr also contains braces in the fake app expr, mark it as a separate expr node.
if appRange <> rangeSeqRange then
- x.PushRange(appRange, ElementType.RANGE_SEQUENCE_EXPR)
+ x.PushRange(appRange, ElementType.COMPUTATION_EXPR)
let seqMark = x.Mark(fromRange)
- x.PushRangeForMark(toRange, seqMark, ElementType.RANGE_SEQUENCE)
+ x.PushRangeForMark(toRange, seqMark, ElementType.RANGE_SEQUENCE_EXPR)
x.PushExpression(toExpr)
match stepExpr with
@@ -1129,7 +1146,7 @@ type FSharpExpressionTreeBuilder(lexer, document, lifetime, projectedOffset, lin
member x.ProcessSynIndexerArg(arg) =
match arg with
- | SynIndexerArg.One(expr, _, range) ->
+ | SynIndexerArg.One(ExprRange range as expr, _, _) ->
x.PushRange(range, ElementType.INDEXER_ARG_EXPR)
x.PushExpression(getGeneratedAppArg expr)
@@ -1197,7 +1214,7 @@ type FSharpExpressionTreeBuilder(lexer, document, lifetime, projectedOffset, lin
let range = whenExpr.Range
let mark = x.MarkTokenOrRange(FSharpTokenType.WHEN, range)
- x.PushRangeForMark(range, mark, ElementType.WHEN_EXPR)
+ x.PushRangeForMark(range, mark, ElementType.WHEN_EXPR_CLAUSE)
x.ProcessExpression(whenExpr)
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpParser.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpParser.fs
index ee000b20d6..9936001e60 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpParser.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpParser.fs
@@ -11,7 +11,6 @@ open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Psi.Parsing
open JetBrains.ReSharper.Psi.Tree
@@ -32,15 +31,15 @@ type FSharpParser(lexer: ILexer, document: IDocument, path: FileSystemPath, sour
override x.CreateFSharpFile() =
x.FinishFile(x.Mark(), ElementType.F_SHARP_IMPL_FILE) }
- let parseFile () =
+ let parseFile (noCache: bool) =
use lifetimeDefinition = Lifetime.Define()
let lifetime = lifetimeDefinition.Lifetime
- let parsingOptions = checkerService.OptionsProvider.GetParsingOptions(sourceFile)
+ let parsingOptions = checkerService.FcsProjectProvider.GetParsingOptions(sourceFile)
let defines = parsingOptions.ConditionalCompilationDefines
let lexer = FSharpPreprocessedLexerFactory(defines).CreateLexer(lexer).ToCachingLexer()
- let parseResults = checkerService.ParseFile(path, document, parsingOptions)
+ let parseResults = checkerService.ParseFile(path, document, parsingOptions, noCache)
let language =
match sourceFile with
@@ -67,8 +66,8 @@ type FSharpParser(lexer: ILexer, document: IDocument, path: FileSystemPath, sour
static member val SandBoxPath = FileSystemPath.Parse("Sandbox.fs")
interface IFSharpParser with
- member this.ParseFSharpFile() = parseFile ()
- member this.ParseFile() = parseFile () :> _
+ member this.ParseFSharpFile(noCache) = parseFile noCache
+ member this.ParseFile() = parseFile false :> _
member this.ParseExpression(chameleonExpr: IChameleonExpression, document) =
let document = if isNotNull document then document else chameleonExpr.GetSourceFile().Document
@@ -93,4 +92,4 @@ type FSharpParser(lexer: ILexer, document: IDocument, path: FileSystemPath, sour
FSharpExpressionTreeBuilder(lexer, document, lifetime, projectedOffset, lineShift)
treeBuilder.ProcessTopLevelExpression(chameleonExpr.SynExpr)
- treeBuilder.GetTreeNode()) :?> ISynExpr
+ treeBuilder.GetTreeNode()) :?> IFSharpExpression
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpTreeBuilderBase.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpTreeBuilderBase.fs
index ff963d83a3..9556869ec1 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpTreeBuilderBase.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpTreeBuilderBase.fs
@@ -6,6 +6,7 @@ open FSharp.Compiler.SyntaxTree
open FSharp.Compiler.Range
open JetBrains.Diagnostics
open JetBrains.DocumentModel
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
@@ -83,6 +84,12 @@ type FSharpTreeBuilderBase(lexer, document: IDocument, lifetime, projectedOffset
let mark = x.Mark(range)
x.Done(range, mark, elementType)
+ member x.MarkAndDone(range: range, elementType1, elementType2) =
+ let mark1 = x.Mark(range)
+ let mark2 = x.Mark()
+ x.Done(range, mark2, elementType2)
+ x.Done(mark1, elementType1)
+
member x.MarkToken(elementType) =
let caseMark = x.Mark()
x.AdvanceLexer()
@@ -313,16 +320,24 @@ type FSharpTreeBuilderBase(lexer, document: IDocument, lifetime, projectedOffset
x.Done(range, mark, ElementType.RECORD_REPRESENTATION)
ElementType.RECORD_DECLARATION
- | SynTypeDefnSimpleRepr.Enum(enumCases, _) ->
+ | SynTypeDefnSimpleRepr.Enum(enumCases, range) ->
+ let casesListMark = x.Mark(range)
for case in enumCases do
x.ProcessEnumCase case
+ x.Done(range, casesListMark, ElementType.ENUM_REPRESENTATION)
ElementType.ENUM_DECLARATION
| SynTypeDefnSimpleRepr.Union(_, cases, range) ->
- let casesListMark = x.Mark(range)
+ let representationMark = x.Mark(range)
+ if not cases.IsEmpty then
+ let firstCaseRange = cases.Head.Range
+ x.AdvanceToTokenOrRangeStart(FSharpTokenType.BAR, firstCaseRange)
+
+ let caseListMark = x.Mark()
for case in cases do
x.ProcessUnionCase(case)
- x.Done(range, casesListMark, ElementType.UNION_REPRESENTATION)
+ x.Done(range, caseListMark, ElementType.UNION_CASE_LIST)
+ x.Done(representationMark, ElementType.UNION_REPRESENTATION)
ElementType.UNION_DECLARATION
| SynTypeDefnSimpleRepr.TypeAbbrev(_, (TypeRange range as synType), _) ->
@@ -414,34 +429,46 @@ type FSharpTreeBuilderBase(lexer, document: IDocument, lifetime, projectedOffset
x.MarkAndDone(range, ElementType.LOCAL_DECLARATION)
member x.ProcessImplicitCtorSimplePats(pats: SynSimplePats) =
+ let range = pats.Range
+ let paramMark = x.Mark(range)
+ let parenPatMark = x.Mark()
+
match pats with
- | SynSimplePats.SimplePats(pats, range) ->
- let mark = x.Mark(range)
+ | SynSimplePats.SimplePats([pat], _) ->
+ x.ProcessImplicitCtorParam(pat)
+
+ | SynSimplePats.SimplePats(headPat :: _ as pats, _) ->
+ let tupleMark = x.Mark(headPat.Range)
for pat in pats do
x.ProcessImplicitCtorParam(pat)
- x.Done(range, mark, ElementType.MEMBER_PARAM_DECLARATION_GROUP)
+ x.Done(tupleMark, ElementType.TUPLE_PAT)
- | SynSimplePats.Typed(pats, synType, range) ->
- let mark = x.Mark(range)
+ | SynSimplePats.Typed(pats, synType, _) ->
+ failwith "foo"
x.ProcessImplicitCtorSimplePats(pats)
x.ProcessType(synType)
- x.Done(range, mark, ElementType.MEMBER_PARAM_DECLARATION_GROUP)
+
+ | _ -> ()
+
+ x.Done(range, parenPatMark, ElementType.PAREN_PAT)
+ x.Done(range, paramMark, ElementType.MEMBER_PARAMS_DECLARATION)
member x.ProcessImplicitCtorParam(pat: SynSimplePat) =
match pat with
- | SynSimplePat.Id(id, _, _, _, _, range) ->
- let mark = x.Mark(range)
- x.ProcessLocalId(id)
- x.Done(range, mark,ElementType.MEMBER_PARAM_DECLARATION)
+ | SynSimplePat.Id(ident = IdentRange range) ->
+ x.MarkAndDone(range, ElementType.LOCAL_REFERENCE_PAT, ElementType.EXPRESSION_REFERENCE_NAME)
- // todo: check isCompilerGenerated?
- | SynSimplePat.Typed(SynSimplePat.Id(id, _, _, _, _, _), synType, range) ->
+ | SynSimplePat.Typed(pat, synType, range) ->
let mark = x.Mark(range)
- x.ProcessLocalId(id)
+ x.ProcessImplicitCtorParam(pat)
x.ProcessType(synType)
- x.Done(range, mark,ElementType.MEMBER_PARAM_DECLARATION)
+ x.Done(range, mark, ElementType.TYPED_PAT)
- | _ -> ()
+ | SynSimplePat.Attrib(pat, attrs, range) ->
+ let mark = x.Mark(range)
+ x.ProcessAttributeLists(attrs)
+ x.ProcessImplicitCtorParam(pat)
+ x.Done(range, mark, ElementType.ATTRIB_PAT)
member x.ProcessTypeMemberTypeParams(SynValTyparDecls(typeParams, _, _)) =
for param in typeParams do
@@ -554,6 +581,10 @@ type FSharpTreeBuilderBase(lexer, document: IDocument, lifetime, projectedOffset
| SynType.Var(typeParameter, _) ->
x.ProcessTypeParameter(typeParameter)
+ | SynType.Anon _ ->
+ // Produced on error
+ ()
+
| _ -> failwithf "unexpected type: %O" synType
member x.ProcessType(TypeRange range as synType) =
@@ -561,23 +592,23 @@ type FSharpTreeBuilderBase(lexer, document: IDocument, lifetime, projectedOffset
| SynType.LongIdent(lid) ->
let mark = x.Mark(range)
x.ProcessNamedTypeReference(lid.Lid)
- x.Done(range, mark, ElementType.NAMED_TYPE)
+ x.Done(range, mark, ElementType.NAMED_TYPE_USAGE)
| SynType.App(_, _, _, _, _, _, _) ->
let mark = x.Mark(range)
x.ProcessTypeAsTypeReferenceName(synType)
- x.Done(range, mark, ElementType.NAMED_TYPE)
+ x.Done(range, mark, ElementType.NAMED_TYPE_USAGE)
| SynType.LongIdentApp(_, _, ltRange, typeArgs, _, gtRange, _) ->
let mark = x.Mark(range)
x.ProcessTypeAsTypeReferenceName(synType)
- x.Done(range, mark, ElementType.NAMED_TYPE)
+ x.Done(range, mark, ElementType.NAMED_TYPE_USAGE)
| SynType.Tuple (_, types, _) ->
let mark = x.Mark(range)
for _, synType in types do
x.ProcessType(synType)
- x.Done(range, mark, ElementType.TUPLE_TYPE)
+ x.Done(range, mark, ElementType.TUPLE_TYPE_USAGE)
// todo: struct keyword?
| SynType.AnonRecd(_, fields, _) ->
@@ -587,51 +618,56 @@ type FSharpTreeBuilderBase(lexer, document: IDocument, lifetime, projectedOffset
x.MarkAndDone(range, ElementType.EXPRESSION_REFERENCE_NAME)
x.ProcessType(synType)
x.Done(range, mark, ElementType.ANON_RECORD_FIELD)
- x.Done(range, mark, ElementType.ANON_RECORD_TYPE)
+ x.Done(range, mark, ElementType.ANON_RECORD_TYPE_USAGE)
| SynType.StaticConstantNamed(synType1, synType2, _)
| SynType.MeasureDivide(synType1, synType2, _) ->
let mark = x.Mark(range)
x.ProcessType(synType1)
x.ProcessType(synType2)
- x.Done(range, mark, ElementType.OTHER_TYPE)
+ x.Done(range, mark, ElementType.UNSUPPORTED_TYPE_USAGE)
| SynType.Fun(synType1, synType2, _) ->
let mark = x.Mark(range)
x.ProcessType(synType1)
x.ProcessType(synType2)
- x.Done(range, mark, ElementType.FUN_TYPE)
+ x.Done(range, mark, ElementType.FUNCTION_TYPE_USAGE)
| SynType.WithGlobalConstraints(synType, constraints, _) ->
let mark = x.Mark(range)
x.ProcessType(synType)
for typeConstraint in constraints do
x.ProcessTypeConstraint(typeConstraint)
- x.Done(range, mark, ElementType.OTHER_TYPE)
+ x.Done(range, mark, ElementType.UNSUPPORTED_TYPE_USAGE)
| SynType.HashConstraint(synType, _)
| SynType.MeasurePower(synType, _, _) ->
let mark = x.Mark(range)
x.ProcessType(synType)
- x.Done(range, mark, ElementType.OTHER_TYPE)
+ x.Done(range, mark, ElementType.UNSUPPORTED_TYPE_USAGE)
| SynType.Array(_, synType, _) ->
let mark = x.Mark(range)
x.ProcessType(synType)
- x.Done(range, mark, ElementType.ARRAY_TYPE)
+ x.Done(range, mark, ElementType.ARRAY_TYPE_USAGE)
| SynType.Var _ ->
let mark = x.Mark(range)
x.ProcessTypeAsTypeReferenceName(synType)
- x.Done(range, mark, ElementType.NAMED_TYPE)
+ x.Done(range, mark, ElementType.NAMED_TYPE_USAGE)
// todo: mark expressions
| SynType.StaticConstantExpr _
| SynType.StaticConstant _ ->
- x.MarkAndDone(range, ElementType.OTHER_TYPE)
+ x.MarkAndDone(range, ElementType.UNSUPPORTED_TYPE_USAGE)
| SynType.Anon _ ->
- x.MarkAndDone(range, ElementType.ANON_TYPE)
+ x.MarkAndDone(range, ElementType.ANON_TYPE_USAGE)
+
+ | SynType.Paren(innerType, range) ->
+ let mark = x.Mark(range)
+ x.ProcessType(innerType)
+ x.Done(range, mark, ElementType.PAREN_TYPE_USAGE)
member x.ProcessTypeConstraint(typeConstraint: SynTypeConstraint) =
match typeConstraint with
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/ParseTreeUtil.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FcsSyntaxTreeUtil.fs
similarity index 93%
rename from ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/ParseTreeUtil.fs
rename to ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FcsSyntaxTreeUtil.fs
index fb68079254..8a3fd15468 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/ParseTreeUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FcsSyntaxTreeUtil.fs
@@ -1,5 +1,5 @@
[]
-module JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Parsing.ParseTreeUtil
+module JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Parsing.FcsSyntaxTreeUtil
open FSharp.Compiler
open FSharp.Compiler.SyntaxTree
@@ -101,3 +101,9 @@ let getGeneratedAppArg (expr: SynExpr) =
match expr with
| SynExpr.App(_, false, func, arg, _) when func.Range.IsSynthetic -> arg
| _ -> expr
+
+type SynArgPats with
+ member x.IsEmpty =
+ match x with
+ | Pats pats -> pats.IsEmpty
+ | NamePatPairs(idsAndPats, _) -> idsAndPats.IsEmpty
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/PostfixTemplates/LetPostfixTemplate.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/PostfixTemplates/LetPostfixTemplate.fs
index 260ec2a239..3f6e860766 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/PostfixTemplates/LetPostfixTemplate.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/PostfixTemplates/LetPostfixTemplate.fs
@@ -48,7 +48,7 @@ and LetPostfixTemplateBehavior(info) =
use disableFormatter = new DisableCodeFormatter()
let refExpr = x.GetExpression(context)
- if (FSharpIntroduceVariable.CanIntroduceVar(refExpr, true)) then refExpr :> ITreeNode else
+ if (FSharpIntroduceVariable.CanIntroduceVar(refExpr)) then refExpr :> ITreeNode else
let letOrUseExpr = elementFactory.CreateLetBindingExpr("_")
setBindingExpression refExpr refExpr.Indent letOrUseExpr
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/PostfixTemplates/PostfixTemplates.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/PostfixTemplates/PostfixTemplates.fs
index 0c05b288da..eb777440ab 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/PostfixTemplates/PostfixTemplates.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/PostfixTemplates/PostfixTemplates.fs
@@ -64,7 +64,7 @@ type FSharpPostfixTemplatesProvider(templatesManager, sessionExecutor, usageStat
isNotNull identifier &&
let parent = identifier.Parent
- (parent :? ISynExpr || parent :? IReferenceName) ->
+ (parent :? IFSharpExpression || parent :? IReferenceName) ->
FSharpPostfixTemplateContext(identifier, executionContext)
| _ -> null
@@ -74,28 +74,28 @@ type FSharpPostfixTemplatesProvider(templatesManager, sessionExecutor, usageStat
type FSharpPostfixTemplateBehaviorBase(info) =
inherit PostfixTemplateBehavior(info)
- let rec getContainingArgExpr (expr: ISynExpr) =
+ let rec getContainingArgExpr (expr: IFSharpExpression) =
match PrefixAppExprNavigator.GetByArgumentExpression(expr) with
| null -> expr
| appExpr -> getContainingArgExpr appExpr
let getContainingTypeExpression (typeName: IReferenceName) =
- match NamedTypeNavigator.GetByReferenceName(typeName.As()) with
+ match NamedTypeUsageNavigator.GetByReferenceName(typeName.As()) with
| null -> null
- | namedType ->
+ | namedTypeUsage ->
- let castExpr = CastExprNavigator.GetByTypeUsage(namedType)
+ let castExpr = CastExprNavigator.GetByTypeUsage(namedTypeUsage)
if isNotNull castExpr then
getContainingArgExpr castExpr else
- let typedExpr = TypedExprNavigator.GetByType(namedType)
+ let typedExpr = TypedExprNavigator.GetByType(namedTypeUsage)
if isNotNull typedExpr then
getContainingArgExpr typedExpr else
null
- let getParentExpression (token: IFSharpTreeNode): ISynExpr =
+ let getParentExpression (token: IFSharpTreeNode): IFSharpExpression =
match token with
| TokenType FSharpTokenType.RESERVED_LITERAL_FORMATS _ ->
match token.Parent.As() with
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddIgnoreFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddIgnoreFix.fs
index 0eb6fa0948..033761391b 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddIgnoreFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddIgnoreFix.fs
@@ -3,21 +3,21 @@ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
open JetBrains.ProjectModel
open JetBrains.ReSharper.Feature.Services.Navigation.CustomHighlighting
open JetBrains.ReSharper.Feature.Services.Refactorings.WorkflowOccurrences
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
open JetBrains.UI.RichText
-type AddIgnoreFix(expr: ISynExpr) =
+type AddIgnoreFix(expr: IFSharpExpression) =
inherit FSharpQuickFixBase()
let mutable expr = expr
- let shouldAddNewLine (expr: ISynExpr) =
+ let shouldAddNewLine (expr: IFSharpExpression) =
if expr.IsSingleLine then false else
if deindentsBody expr then false else
@@ -26,7 +26,7 @@ type AddIgnoreFix(expr: ISynExpr) =
| :? IDoExpr | :? IAssertExpr | :? ILazyExpr -> true
| _ -> false
- let suggestInnerExpression (expr: ISynExpr) =
+ let suggestInnerExpression (expr: IFSharpExpression) =
match expr with
| :? IIfThenElseExpr as ifExpr ->
Some(ifExpr.ThenExpr, "Then branch")
@@ -61,7 +61,7 @@ type AddIgnoreFix(expr: ISynExpr) =
[| innerExpression, text
expr, "Whole expression" |]
|> Array.map (fun (expr, text) ->
- let getRange (expr: ISynExpr) = [| expr.GetNavigationRange() |]
+ let getRange (expr: IFSharpExpression) = [| expr.GetNavigationRange() |]
WorkflowPopupMenuOccurrence(RichText(text), RichText.Empty, expr, getRange))
let occurrence =
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddMatchAllClauseFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddMatchAllClauseFix.fs
index fd18bb786b..c2ad481004 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddMatchAllClauseFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddMatchAllClauseFix.fs
@@ -1,10 +1,10 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddParensFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddParensFix.fs
index e1dfd661d2..a449b313a1 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddParensFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddParensFix.fs
@@ -1,8 +1,8 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddUnderscorePrefixFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddUnderscorePrefixFix.fs
index b0542db140..b644cea0d5 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddUnderscorePrefixFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/AddUnderscorePrefixFix.fs
@@ -1,5 +1,6 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ConvertToUseFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ConvertToUseFix.fs
index c507fdf4a0..e7a0ad04e5 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ConvertToUseFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ConvertToUseFix.fs
@@ -1,9 +1,9 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/GenerateMissingRecordFieldsFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/GenerateMissingRecordFieldsFix.fs
index ffe6a4a598..ae1da19941 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/GenerateMissingRecordFieldsFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/GenerateMissingRecordFieldsFix.fs
@@ -8,13 +8,13 @@ open JetBrains.ReSharper.Feature.Services.LiveTemplates.LiveTemplates
open JetBrains.ReSharper.Feature.Services.LiveTemplates.Hotspots
open JetBrains.ReSharper.Feature.Services.LiveTemplates.Templates
open JetBrains.ReSharper.Feature.Services.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Intentions
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util.PsiUtil
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
@@ -72,7 +72,7 @@ type GenerateMissingRecordFieldsFix(recordExpr: IRecordExpr) =
match existingBindings.LastOrDefault() with
| null ->
let lBrace = recordExpr.LeftBrace
- let rBrace = recordExpr.RightBrace :> ITreeNode
+ let rBrace = recordExpr.RightBrace
if lBrace.NextSibling == rBrace then
// Empty braces: {}
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/IntroduceVarFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/IntroduceVarFix.fs
index 9678ba08d8..1f9fc5e425 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/IntroduceVarFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/IntroduceVarFix.fs
@@ -6,7 +6,7 @@ open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
open JetBrains.ReSharper.Psi.Tree
open JetBrains.TextControl
-type IntroduceVarFix(expr: ISynExpr) =
+type IntroduceVarFix(expr: IFSharpExpression) =
inherit FSharpQuickFixBase()
new (warning: UnitTypeExpectedWarning) =
@@ -15,10 +15,13 @@ type IntroduceVarFix(expr: ISynExpr) =
new (warning: FunctionValueUnexpectedWarning) =
IntroduceVarFix(warning.Expr)
+ new (error: UnitTypeExpectedError) =
+ IntroduceVarFix(error.Expr)
+
override x.Text = "Introduce 'let' binding"
override x.IsAvailable _ =
- FSharpIntroduceVariable.CanIntroduceVar(expr, true)
+ FSharpIntroduceVariable.CanIntroduceVar(expr)
override x.Execute(solution, textControl) =
base.Execute(solution, textControl)
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveInlineFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveInlineFix.fs
index e46fdfa09d..cd16a58251 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveInlineFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveInlineFix.fs
@@ -1,7 +1,7 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
type RemoveInlineFix(error: LocalClassBindingsCannotBeInlineError) =
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveNeverMatchingRuleFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveNeverMatchingRuleFix.fs
index 5712e9325a..3591f16d83 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveNeverMatchingRuleFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveNeverMatchingRuleFix.fs
@@ -1,8 +1,8 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings.CommonErrors
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.Tree
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantAttributeParensFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantAttributeParensFix.fs
index f9c400d425..538a574dfe 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantAttributeParensFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantAttributeParensFix.fs
@@ -1,7 +1,7 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantAttributeSuffixFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantAttributeSuffixFix.fs
index b8eb5d3000..20ee01ddf7 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantAttributeSuffixFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantAttributeSuffixFix.fs
@@ -1,7 +1,7 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
open JetBrains.Util
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantBackticksFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantBackticksFix.fs
index 06c43350f3..7d25625146 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantBackticksFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantBackticksFix.fs
@@ -1,6 +1,7 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
open JetBrains.ReSharper.Feature.Services.CodeCleanup.HighlightingModule
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
@@ -28,5 +29,6 @@ type RemoveRedundantBackticksFix(warning: RedundantBackticksWarning) =
interface IHighlightingsCleanupItem with
member x.IsAvailable _ = true
member x.IsReanalysisRequired = false
+ member x.ReanalysisDependencyRoot = null
member x.IsValid() = isValid identifier
member x.Execute() = x.ExecutePsiTransaction() |> ignore
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantNewFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantNewFix.fs
index 27f941aa3c..c4a237f23f 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantNewFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantNewFix.fs
@@ -1,7 +1,7 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantQualifierFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantQualifierFix.fs
new file mode 100644
index 0000000000..e03aa76ab5
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveRedundantQualifierFix.fs
@@ -0,0 +1,36 @@
+namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+
+open JetBrains.ReSharper.Plugins.FSharp.Psi
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
+open JetBrains.ReSharper.Psi.ExtensionsAPI
+open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
+open JetBrains.ReSharper.Psi.Tree
+open JetBrains.ReSharper.Resources.Shell
+
+type RemoveRedundantQualifierFix(warning: RedundantQualifierWarning) =
+ inherit FSharpQuickFixBase()
+
+ let treeNode = warning.TreeNode
+
+ override x.Text = "Remove redundant qualifier"
+
+ override x.IsAvailable _ =
+ isValid treeNode
+
+ override x.ExecutePsiTransaction _ =
+ use writeCookie = WriteLockCookie.Create(treeNode.IsPhysical())
+ use disableFormatter = new DisableCodeFormatter()
+
+ let (qualifier: ITreeNode), delimiter =
+ match treeNode with
+ | :? IReferenceExpr as referenceExpr -> referenceExpr.Qualifier :> _, referenceExpr.Delimiter
+ | :? IReferenceName as referenceName -> referenceName.Qualifier :> _, referenceName.Delimiter
+
+ | :? ITypeExtensionDeclaration as typeExtension ->
+ typeExtension.QualifierReferenceName :> _, typeExtension.Delimiter
+
+ | _ -> failwithf "Unexpected qualifier owner: %O" treeNode
+
+ ModificationUtil.DeleteChildRange(qualifier, getLastMatchingNodeAfter isInlineSpace delimiter)
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveSubsequentFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveSubsequentFix.fs
index e7dcdb1fba..b20009fa05 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveSubsequentFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveSubsequentFix.fs
@@ -1,14 +1,14 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Psi.Util
open JetBrains.ReSharper.Resources.Shell
-type RemoveSubsequentFix(expr: ISynExpr) =
+type RemoveSubsequentFix(expr: IFSharpExpression) =
inherit FSharpQuickFixBase()
new (warning: UnitTypeExpectedWarning) =
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnexpectedArgumentsFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnexpectedArgumentsFix.fs
index d687741133..a72525edee 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnexpectedArgumentsFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnexpectedArgumentsFix.fs
@@ -1,8 +1,8 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Resources.Shell
@@ -18,7 +18,6 @@ type RemoveUnexpectedArgumentsFix(warning: NotAFunctionError) =
inherit FSharpQuickFixBase()
let expr = warning.Expr
- let exprNode = expr :> ITreeNode
let prefixApp = warning.PrefixApp
override x.Text =
@@ -33,5 +32,5 @@ type RemoveUnexpectedArgumentsFix(warning: NotAFunctionError) =
let commentNodeCandidate = skipMatchingNodesBefore isWhitespace firstUnexpectedArg
let updatedRoot = ModificationUtil.ReplaceChild(prefixApp, expr.Copy())
- if commentNodeCandidate != exprNode then
+ if commentNodeCandidate != expr then
addNodesAfter updatedRoot (TreeRange(expr.NextSibling, commentNodeCandidate)) |> ignore
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnnecessaryUpcastFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnnecessaryUpcastFix.fs
index d86836d403..3c75518ebc 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnnecessaryUpcastFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnnecessaryUpcastFix.fs
@@ -1,7 +1,7 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedLocalBindingFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedLocalBindingFix.fs
index 120e9d2c21..9835e7f19a 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedLocalBindingFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedLocalBindingFix.fs
@@ -3,10 +3,10 @@ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
open System
open JetBrains.Diagnostics
open JetBrains.ReSharper.Feature.Services.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Psi.Util
@@ -22,9 +22,9 @@ type RemoveUnusedLocalBindingFix(warning: UnusedValueWarning) =
// todo: we can also check that every top declaration pat is unused instead
let binding = BindingNavigator.GetByHeadPattern(pat)
- let letOrUse = LetNavigator.GetByBinding(binding)
+ let letOrUse = LetBindingsNavigator.GetByBinding(binding)
- let getCopyRange (expr: ILetLikeExpr) =
+ let getCopyRange (expr: ILetOrUseExpr) =
let inExpr = expr.InExpression
let inKeyword = expr.InKeyword
@@ -71,7 +71,7 @@ type RemoveUnusedLocalBindingFix(warning: UnusedValueWarning) =
ModificationUtil.DeleteChildRange(TreeRange(first, last))
- | :? ILetLikeExpr as letExpr ->
+ | :? ILetOrUseExpr as letExpr ->
let rangeToCopy = getCopyRange letExpr
ModificationUtil.ReplaceChildRange(TreeRange(letExpr), rangeToCopy) |> ignore
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedNamedAsPatFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedNamedAsPatFix.fs
index 9e291da277..f4538547de 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedNamedAsPatFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedNamedAsPatFix.fs
@@ -1,8 +1,8 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util.PsiUtil
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedOpensFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedOpensFix.fs
index fe713d5f2c..b6291846a2 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedOpensFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedOpensFix.fs
@@ -3,8 +3,8 @@ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
open JetBrains.ReSharper.Feature.Services.Intentions.Scoped
open JetBrains.ReSharper.Feature.Services.Intentions.Scoped.Actions
open JetBrains.ReSharper.Feature.Services.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedSelfIdVariableFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedSelfIdVariableFix.fs
index cde826499d..0b5a435bdc 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedSelfIdVariableFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveUnusedSelfIdVariableFix.fs
@@ -1,10 +1,10 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
open JetBrains.Diagnostics
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings.CommonErrors
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveYieldFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveYieldFix.fs
new file mode 100644
index 0000000000..bd589c2010
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/RemoveYieldFix.fs
@@ -0,0 +1,37 @@
+namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+
+open JetBrains.ReSharper.Plugins.FSharp.Psi
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
+open JetBrains.ReSharper.Psi.ExtensionsAPI
+open JetBrains.ReSharper.Resources.Shell
+
+type RemoveYieldFix(yieldExpr: IYieldOrReturnExpr) =
+ inherit FSharpQuickFixBase()
+
+ let yieldKeyword = yieldExpr.YieldKeyword
+
+ new (error: ReturnRequiresComputationExpressionError) =
+ RemoveYieldFix(error.YieldExpr)
+
+ new (error: YieldRequiresSeqExpressionError) =
+ RemoveYieldFix(error.YieldExpr)
+
+ override x.Text = "Remove " + yieldKeyword.GetTokenType().TokenRepresentation
+
+ override x.IsAvailable _ =
+ isValid yieldExpr && isValid yieldKeyword
+
+ override x.ExecutePsiTransaction _ =
+ use writeCookie = WriteLockCookie.Create(yieldExpr.IsPhysical())
+ use disableFormatter = new DisableCodeFormatter()
+
+ let expr = yieldExpr.Expression
+ let shift = expr.Indent - yieldExpr.Indent
+ if shift > 0 then
+ // Parsing `return` currently doesn't support deindenting,
+ // but we do a defensive indent diff check in case it's supported in future.
+ shiftExpr -shift yieldExpr
+
+ replaceWithCopy yieldExpr expr
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceLetWithExpressionFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceLetWithExpressionFix.fs
index 90c3e15501..760778beed 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceLetWithExpressionFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceLetWithExpressionFix.fs
@@ -1,8 +1,8 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceUseWithLetFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceUseWithLetFix.fs
index 820ff59c26..34d7bd9150 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceUseWithLetFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceUseWithLetFix.fs
@@ -1,14 +1,14 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
open JetBrains.Diagnostics
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
-type ReplaceUseWithLetFix(letNode: ILet) =
+type ReplaceUseWithLetFix(letNode: ILetBindings) =
inherit FSharpQuickFixBase()
new (warning: UseBindingsIllegalInModulesWarning) =
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceWithAssignmentExpressionFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceWithAssignmentExpressionFix.fs
index e94cb12fd2..c2d6567270 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceWithAssignmentExpressionFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceWithAssignmentExpressionFix.fs
@@ -1,10 +1,10 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
open FSharp.Compiler.SourceCodeServices
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings.CommonErrors
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util.FSharpExpressionUtil
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceWithWildPatFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceWithWildPatFix.fs
index 160a5f5a02..e8dcdea8d7 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceWithWildPatFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ReplaceWithWildPatFix.fs
@@ -1,9 +1,9 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util.PsiUtil
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
@@ -23,14 +23,19 @@ type ReplaceWithWildPatFix(pat: INamedPat) =
override x.IsAvailable _ =
isValid pat &&
- if pat.IgnoreParentParens().Parent :? IAttribPat then false else
+ let pat = pat.IgnoreParentParens()
+ if isNotNull (AttribPatNavigator.GetByPattern(pat)) then false else
+
+ let typedPat = TypedPatNavigator.GetByPattern(pat).IgnoreParentParens()
+ if isNotNull (AttribPatNavigator.GetByPattern(typedPat)) then false else
let node = skipIntermediatePatParents pat |> getParent
node :? IBinding ||
node :? IMatchClause ||
- node :? IMemberParamDeclaration && node.Parent :? IMemberDeclaration // todo: check this check
+ node :? IMemberParamsDeclaration &&
+ (node.Parent :? IMemberDeclaration || node.Parent :? IMemberConstructorDeclaration)
override x.ExecutePsiTransaction _ =
use writeLock = WriteLockCookie.Create(pat.IsPhysical())
use disableFormatter = new DisableCodeFormatter()
- replace pat (pat.FSharpLanguageService.CreateElementFactory(pat.GetPsiModule()).CreateWildPat())
+ replace pat (pat.GetFSharpLanguageService().CreateElementFactory(pat.GetPsiModule()).CreateWildPat())
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToAbstractFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToAbstractFix.fs
index 55e94cd4c5..be3585d1fb 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToAbstractFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToAbstractFix.fs
@@ -1,10 +1,10 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Resources.Shell
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToRecursiveFunctionFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToRecursiveFunctionFix.fs
index 40f7375ec6..bf047aaa6b 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToRecursiveFunctionFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToRecursiveFunctionFix.fs
@@ -3,9 +3,9 @@ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
open JetBrains.ProjectModel
open JetBrains.ReSharper.Feature.Services.Navigation.CustomHighlighting
open JetBrains.ReSharper.Feature.Services.Refactorings.WorkflowOccurrences
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.Tree
open JetBrains.ReSharper.Resources.Shell
open JetBrains.UI.RichText
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToRecursiveLetBindingsFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToRecursiveLetBindingsFix.fs
index 05577c942a..cf116ea6ca 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToRecursiveLetBindingsFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToRecursiveLetBindingsFix.fs
@@ -1,7 +1,7 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
type ToRecursiveLetBindingsFix(error: LetAndForNonRecBindingsError) =
inherit FSharpQuickFixBase()
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToUpcastFix.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToUpcastFix.fs
index ad8dfde0f7..78a9c7a5fe 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToUpcastFix.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/QuickFixes/ToUpcastFix.fs
@@ -1,9 +1,9 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Psi.Tree
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/FSharpNamingService.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/FSharpNamingService.fs
index 65085fdb34..b924388f46 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/FSharpNamingService.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/FSharpNamingService.fs
@@ -23,17 +23,17 @@ module Traverse =
| TupleItem of item: int
let makeTuplePatPath pat =
- let rec tryMakePatPath path (IgnoreParenPat pat: ISynPat) =
- match pat.Parent with
+ let rec tryMakePatPath path (IgnoreParenPat fsPattern: IFSharpPattern) =
+ match fsPattern.Parent with
| :? ITuplePat as tuplePat ->
- let item = tuplePat.Patterns.IndexOf(pat)
+ let item = tuplePat.Patterns.IndexOf(fsPattern)
Assertion.Assert(item <> -1, "item <> -1")
tryMakePatPath (TupleItem(item) :: path) tuplePat
- | _ -> pat, path
+ | _ -> fsPattern, path
tryMakePatPath [] pat
- let rec tryTraverseExprPath (path: TraverseStep list) (IgnoreInnerParenExpr expr: ISynExpr) =
+ let rec tryTraverseExprPath (path: TraverseStep list) (IgnoreInnerParenExpr expr: IFSharpExpression) =
match path with
| [] -> expr
| step :: rest ->
@@ -227,8 +227,8 @@ type FSharpNamingService(language: FSharpLanguage) =
| _ -> EmptyList.Instance :> _
- member x.AddExtraNames(namesCollection: INamesCollection, declaredElementPat: ISynPat) =
- let pat, path = makeTuplePatPath declaredElementPat
+ member x.AddExtraNames(namesCollection: INamesCollection, fsPattern: IFSharpPattern) =
+ let pat, path = makeTuplePatPath fsPattern
let entryOptions =
EntryOptions(subrootPolicy = SubrootPolicy.Decompose, emphasis = Emphasis.Good,
@@ -255,9 +255,8 @@ type FSharpNamingService(language: FSharpLanguage) =
| expr -> addNamesForExpr expr
| :? IForEachExpr as forEachExpr when forEachExpr.Pattern == pat ->
- match forEachExpr.InClause.As() with
- | null -> ()
- | expr ->
+ let expr = forEachExpr.InExpression
+ if expr :? IRangeSequenceExpr then () else
let naming = pat.GetPsiServices().Naming
let collection =
@@ -272,7 +271,7 @@ type FSharpNamingService(language: FSharpLanguage) =
| _ -> ()
- match declaredElementPat with
+ match fsPattern with
| :? INamedPat as namedPat ->
let parametersOwner = ParametersOwnerPatNavigator.GetByParameter(namedPat.IgnoreParentParens())
if isNull parametersOwner || parametersOwner.Parameters.Count <> 1 then () else
@@ -303,7 +302,7 @@ type FSharpNamingService(language: FSharpLanguage) =
if isNotNull field && field.IsConstant then base.GetNamedElementKind(element) else
let declarations = element.GetDeclarations()
- if declarations |> Seq.exists (fun decl -> decl :? ISynPat) then
+ if declarations |> Seq.exists (fun decl -> decl :? IFSharpPattern) then
NamedElementKinds.Locals
else
base.GetNamedElementKind(element)
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/IntroduceVariable.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/IntroduceVariable.fs
index 3be6d49b04..9f2bf73abc 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/IntroduceVariable.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/IntroduceVariable.fs
@@ -1,18 +1,22 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Refactorings
+open System.Collections.Generic
open JetBrains.Application.DataContext
open JetBrains.Application.UI.Actions.ActionManager
+open JetBrains.Diagnostics
open JetBrains.DocumentModel.DataContext
open JetBrains.Lifetimes
open JetBrains.ProjectModel.DataContext
open JetBrains.ReSharper.Feature.Services.LiveTemplates.Hotspots
open JetBrains.ReSharper.Feature.Services.Refactorings
open JetBrains.ReSharper.Feature.Services.Refactorings.Specific
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
+open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Psi.DataContext
open JetBrains.ReSharper.Psi.ExtensionsAPI
@@ -33,7 +37,12 @@ open JetBrains.Util
type FSharpIntroduceVariable(workflow, solution, driver) =
inherit IntroduceVariableBase(workflow, solution, driver)
- let getNames (expr: ISynExpr) =
+ /// Applies to case where source expression is the node to replace and is the last expression in a block,
+ /// i.e. it doesn't have any expression to put as InExpression in the new `let` binding expression.
+ /// Producing incomplete expression adds error but is easier to edit code immediately afterwards.
+ let alwaysGenerateCompleteBindingExpr = false
+
+ let getNames (expr: IFSharpExpression) =
let language = expr.Language
let sourceFile = expr.GetSourceFile()
@@ -53,13 +62,14 @@ type FSharpIntroduceVariable(workflow, solution, driver) =
let suggestionOptions = SuggestionOptions(null, DefaultName = "foo")
namesCollection.Prepare(namingRule, ScopeKind.Common, suggestionOptions).AllNames()
- let getReplaceRanges (expr: ISynExpr) (parent: ISynExpr) =
- let sequentialExpr = SequentialExprNavigator.GetByExpression(expr)
- if expr == parent && isNotNull sequentialExpr then
- let inRange = TreeRange(expr.NextSibling, sequentialExpr.LastChild)
+ let getReplaceRanges (contextExpr: IFSharpExpression) removeSourceExpr =
+ let sequentialExpr = SequentialExprNavigator.GetByExpression(contextExpr)
+ if isNotNull sequentialExpr then
+ let inRangeStart = if removeSourceExpr then contextExpr.NextSibling else contextExpr :> _
+ let inRange = TreeRange(inRangeStart, sequentialExpr.LastChild)
let seqExprs = sequentialExpr.Expressions
- let index = seqExprs.IndexOf(expr)
+ let index = seqExprs.IndexOf(contextExpr)
if seqExprs.Count - index > 2 then
// Replace rest expressions with a sequential expr node.
@@ -67,19 +77,23 @@ type FSharpIntroduceVariable(workflow, solution, driver) =
let newSeqExpr = ModificationUtil.ReplaceChildRange(inRange, TreeRange(newSeqExpr)).First
LowLevelModificationUtil.AddChild(newSeqExpr, Array.ofSeq inRange)
- {| ReplaceRange = TreeRange(expr, newSeqExpr)
+
+ let replaceRange =
+ if removeSourceExpr then TreeRange(contextExpr, newSeqExpr) else TreeRange(newSeqExpr)
+
+ {| ReplaceRange = replaceRange
InRange = TreeRange(newSeqExpr)
- AddNewLine = false |}
+ AddNewLine = not removeSourceExpr |}
else
// The last expression can be moved as is.
- {| ReplaceRange = TreeRange(expr, sequentialExpr.LastChild)
+ {| ReplaceRange = TreeRange(contextExpr, sequentialExpr.LastChild)
InRange = inRange
- AddNewLine = false |}
+ AddNewLine = not removeSourceExpr |}
else
- let range = TreeRange(parent)
+ let range = TreeRange(contextExpr)
{| ReplaceRange = range; InRange = range; AddNewLine = true |}
- let rec getExprToInsertBefore (expr: ISynExpr): ISynExpr =
+ let rec getExprToInsertBefore (expr: IFSharpExpression): IFSharpExpression =
let expr = expr.IgnoreParentParens()
let parent = expr.Parent
@@ -91,54 +105,122 @@ type FSharpIntroduceVariable(workflow, solution, driver) =
| :? ISequentialExpr | :? ILambdaExpr | :? ITryLikeExpr -> expr
| :? IBinding as binding when
- binding.Expression == expr && isNotNull (LetLikeExprNavigator.GetByBinding(binding)) &&
+ binding.Expression == expr && isNotNull (LetOrUseExprNavigator.GetByBinding(binding)) &&
// Don't escape function declarations
not (binding.HeadPattern :? IParametersOwnerPat) ->
- LetLikeExprNavigator.GetByBinding(binding) :> _
+ LetOrUseExprNavigator.GetByBinding(binding) :> _
+
+ | :? IRecordExprBinding as fieldBinding ->
+ let recordExpr = RecordLikeExprNavigator.GetByExprBinding(fieldBinding)
+ getExprToInsertBefore recordExpr
+
+ | :? ILetOrUseExpr as letExpr ->
+ Assertion.Assert(letExpr.InExpression == expr, "letExpr.InExpression == expr")
+ expr
+
+ | :? IBinaryAppExpr as binaryAppExpr when
+ binaryAppExpr.RightArgument == expr && isNotNull binaryAppExpr.LeftArgument ->
+ let leftArgument = binaryAppExpr.LeftArgument
- | :? ISynExpr as parentExpr -> getExprToInsertBefore parentExpr
+ if leftArgument.Indent = expr.Indent && leftArgument.EndLine + docLine 1 < expr.StartLine then
+ // Don't move up from "blocks" after empty non-code line separators.
+ // todo: allow choosing scope?
+ expr
+ else
+ // Try going up from the left part instead.
+ match leftArgument.IgnoreInnerParens() with
+ | :? IBinaryAppExpr as binaryAppExpr when isNotNull binaryAppExpr.RightArgument ->
+ getExprToInsertBefore binaryAppExpr.RightArgument
+ | _ -> getExprToInsertBefore leftArgument
+
+ | :? IFSharpExpression as parentExpr -> getExprToInsertBefore parentExpr
| _ -> expr
- let getContextDeclaration (contextExpr: ISynExpr): IModuleMember =
- let letDecl = LetModuleDeclNavigator.GetByBinding(BindingNavigator.GetByExpression(contextExpr))
+ let getCommonParentExpr (data: IntroduceVariableData) (sourceExpr: IFSharpExpression): IFSharpExpression =
+ let commonParent = data.Usages.FindLCA().As().NotNull("commonParentExpr is null")
+
+ let seqExpr = commonParent.As()
+ if isNull seqExpr then commonParent else
+
+ if sourceExpr.Parent == commonParent then sourceExpr else
+
+ let contextExpr = sourceExpr.PathToRoot() |> Seq.find (fun n -> n.Parent == commonParent)
+ contextExpr :?> _
+
+ let getContextDeclaration (contextExpr: IFSharpExpression): IModuleMember =
+ let binding = BindingNavigator.GetByExpression(contextExpr)
+ if isNull binding || binding.HeadPattern :? IParametersOwnerPat then null else
+
+ let letDecl = LetModuleDeclNavigator.GetByBinding(binding)
if isNotNull letDecl then letDecl :> _ else
let doDecl = DoNavigator.GetByExpression(contextExpr)
if isNotNull doDecl && doDecl.IsImplicit then doDecl :> _ else null
- let createBinding (context: ISynExpr) (contextDecl: IModuleMember) name: ILet =
+ let createBinding (context: IFSharpExpression) (contextDecl: IModuleMember) name: ILetBindings =
let elementFactory = context.CreateElementFactory()
if isNotNull contextDecl then
elementFactory.CreateLetModuleDecl(name) :> _
else
elementFactory.CreateLetBindingExpr(name) :> _
- let getMoveToNewLineInfo (contextExpr: ISynExpr) =
- if not contextExpr.IsSingleLine then None else
+ let isSingleLineContext (context: ITreeNode): bool =
+ let contextParent = context.Parent
+ if not contextParent.IsSingleLine then false else
- let parent = contextExpr.Parent
- let prevToken =
+ match contextParent with
+ | :? IMatchClause as matchClause ->
+ let matchClauseOwner = MatchClauseListOwnerNavigator.GetByClause(matchClause)
+ if matchClauseOwner.IsSingleLine then true else
+
+ let clauses = matchClauseOwner.Clauses
+ let index = clauses.IndexOf(matchClause)
+ if index = clauses.Count - 1 then false else
+
+ clauses.[index + 1].StartLine = matchClause.StartLine
+
+ | :? IIfThenElseExpr | :? ILambdaExpr | :? ITryLikeExpr | :? IWhenExprClause -> true
+ | _ -> false
+
+ let getMoveToNewLineInfo (contextExpr: IFSharpExpression) =
+ let requiresMultilineExpr (parent: ITreeNode) =
match parent with
+ | :? IMemberDeclaration | :? IAutoProperty -> false
+ | _ -> true
+
+ let contextExprParent = contextExpr.Parent
+ let contextParent = contextExpr.IgnoreParentChameleonExpr()
+
+ if not contextExpr.IsSingleLine && requiresMultilineExpr contextParent then None else
+
+ let prevToken =
+ match contextParent with
| :? IBinding as binding when isNotNull binding.Parent -> binding.EqualsToken
+ | :? IMemberDeclaration as memberDeclaration -> memberDeclaration.EqualsToken
+ | :? IAutoProperty as autoProperty -> autoProperty.EqualsToken
| :? IMatchClause as matchClause -> matchClause.RArrow
+ | :? IWhenExprClause as whenExpr -> whenExpr.WhenKeyword
| :? ILambdaExpr as lambdaExpr -> lambdaExpr.RArrow
| :? ITryLikeExpr as tryExpr -> tryExpr.TryKeyword
| _ -> null
if isNull prevToken then None else
+ let contextExpr: IFSharpTreeNode =
+ if contextExprParent :? IChameleonExpression then contextExprParent :?> _ else contextExpr :> _
+
let prevSignificant = skipMatchingNodesBefore isInlineSpaceOrComment contextExpr
- if not (obj.ReferenceEquals(prevSignificant, prevToken)) then None else
+ if prevSignificant != prevToken then None else
let indent =
- match parent with
- | :? IBinding -> parent.Parent.Indent
- | _ -> parent.Indent
+ match contextParent with
+ | :? IBinding -> contextParent.Parent.Indent
+ | _ -> contextParent.Indent
Some(indent + contextExpr.GetIndentSize())
- let moveToNewLine (contextExpr: ISynExpr) (indent: int) =
+ let moveToNewLine (contextExpr: IFSharpExpression) (indent: int) =
let prevSibling = contextExpr.PrevSibling
if isInlineSpace prevSibling then
let first = getFirstMatchingNodeBefore isInlineSpace prevSibling
@@ -149,16 +231,29 @@ type FSharpIntroduceVariable(workflow, solution, driver) =
Whitespace(indent)
] |> ignore
- static member val ExpressionToRemove = Key("FSharpIntroduceVariable.ExpressionToRemove")
+ static member val ExpressionToRemoveKey = Key("FSharpIntroduceVariable.ExpressionToRemove")
override x.Process(data) =
- let sourceExpr = data.SourceExpression.As()
- let commonParentExpr = data.Usages.FindLCA().As()
+ // Replace the actual source expression with the outer-most expression among usages,
+ // since it's needed for calculating a common node to replace.
+ let sourceExpr = data.Usages |> Seq.minBy (fun u -> u.GetTreeStartOffset().Offset) :?> IFSharpExpression
+ let commonParentExpr = getCommonParentExpr data sourceExpr
- // contextDecl is not null when expression is bound to a module/type let binding
+ // `contextDecl` is not null when expression is bound to a module/type let binding
let contextExpr = getExprToInsertBefore commonParentExpr
let contextDecl = getContextDeclaration contextExpr
- let moveToNewLineInfo = if isNotNull contextDecl then None else getMoveToNewLineInfo contextExpr
+
+ let contextIsSourceExpr = sourceExpr == contextExpr && isNull contextDecl
+ let isInSingleLineContext = isNull contextDecl && isSingleLineContext contextExpr
+
+ let isInSeqExpr =
+ let seqExpr = SequentialExprNavigator.GetByExpression(sourceExpr)
+ isNotNull seqExpr && sourceExpr != seqExpr.Expressions.Last()
+
+ let replaceSourceExprNode = contextIsSourceExpr && not isInSeqExpr
+
+ let moveToNewLineInfo =
+ if isNotNull contextDecl || isInSingleLineContext then None else getMoveToNewLineInfo contextExpr
let contextIndent =
if isNotNull contextDecl then contextDecl.Indent else
@@ -170,8 +265,18 @@ type FSharpIntroduceVariable(workflow, solution, driver) =
let names = getNames sourceExpr
let name = if names.Count > 0 then names.[0] else "x"
- let removeSourceExpr = sourceExpr.UserData.HasKey(FSharpIntroduceVariable.ExpressionToRemove)
- sourceExpr.UserData.RemoveKey(FSharpIntroduceVariable.ExpressionToRemove)
+ let removeSourceExpr =
+ if data.SourceExpression.UserData.HasKey(FSharpIntroduceVariable.ExpressionToRemoveKey) then true else
+ if not contextIsSourceExpr then false else
+ if data.Usages.Count = 1 then true else
+
+ let seqExpr = SequentialExprNavigator.GetByExpression(sourceExpr)
+ if isNull seqExpr then false else
+
+ let arrayOrListExpr = ArrayOrListExprNavigator.GetByExpression(seqExpr)
+ isNull arrayOrListExpr || data.Usages.Count = 1
+
+ sourceExpr.UserData.RemoveKey(FSharpIntroduceVariable.ExpressionToRemoveKey)
use writeCookie = WriteLockCookie.Create(sourceExpr.IsPhysical())
use disableFormatter = new DisableCodeFormatter()
@@ -185,33 +290,83 @@ type FSharpIntroduceVariable(workflow, solution, driver) =
let letBindings = createBinding contextExpr contextDecl name
setBindingExpression sourceExpr contextIndent letBindings
- let replacedUsages =
- data.Usages |> Seq.choose (fun usage ->
- if not (isValid usage) then None else
- if removeSourceExpr && obj.ReferenceEquals(usage, contextExpr) then None else
+ let replacedUsages, sourceExpr =
+ data.Usages |> Seq.fold (fun ((replacedUsages, sourceExpr) as acc) usage ->
+ if not (isValid usage) then acc else
+
+ let usageIsSourceExpr = usage == sourceExpr
+
+ if usageIsSourceExpr && (removeSourceExpr || replaceSourceExprNode) then
+ // Ignore this usage, it's going to be removed via replacing tree ranges later.
+ acc else
+
+ let refExpr = elementFactory.CreateReferenceExpr(name) :> IFSharpExpression
+ let replacedUsage = ModificationUtil.ReplaceChild(usage, refExpr)
- let ref = elementFactory.CreateReferenceExpr(name)
- Some (ModificationUtil.ReplaceChild(usage, ref).As().CreateTreeElementPointer()))
- |> Seq.toArray
+ let sourceExpr =
+ if usageIsSourceExpr && contextIsSourceExpr && isInSeqExpr then replacedUsage else sourceExpr
+
+ let replacedUsagePointer = replacedUsage.As().CreateTreeElementPointer()
+ replacedUsagePointer :: replacedUsages, sourceExpr) ([], sourceExpr)
+
+ let contextExpr = if contextIsSourceExpr then sourceExpr else contextExpr
+ let replacedUsages = List(Seq.rev replacedUsages)
match moveToNewLineInfo with
| Some indent -> moveToNewLine contextExpr indent
| _ -> ()
- let letBindings: ILet =
+ let letBindings: ILetBindings =
match letBindings with
+ | :? ILetOrUseExpr when replaceSourceExprNode ->
+ let letBindings = ModificationUtil.ReplaceChild(sourceExpr, letBindings)
+
+ let createRefExpr () =
+ let refExpr = elementFactory.CreateReferenceExpr(name).As()
+ let nodePointer = refExpr.CreateTreeElementPointer()
+ replacedUsages.Add(nodePointer)
+ refExpr
+
+ if alwaysGenerateCompleteBindingExpr then
+ addNodesAfter letBindings.LastChild [
+ NewLine(lineEnding)
+ Whitespace(contextIndent)
+
+ if removeSourceExpr then
+ elementFactory.CreateExpr("()")
+ else
+ createRefExpr ()
+ ] |> ignore
+
+ if isInSingleLineContext then
+ addNodesAfter letBindings.LastChild [
+ Whitespace()
+ FSharpTokenType.IN.CreateLeafElement()
+ Whitespace()
+ createRefExpr ()
+ ] |> ignore
+
+ letBindings
+
| :? ILetOrUseExpr ->
- let ranges = getReplaceRanges sourceExpr contextExpr
- let replaced = ModificationUtil.ReplaceChildRange(ranges.ReplaceRange, TreeRange(letBindings))
- let letBindings = replaced.First :?> ILet
+ let ranges = getReplaceRanges contextExpr removeSourceExpr
+ let letBindings = ModificationUtil.AddChildBefore(ranges.ReplaceRange.First, letBindings)
let binding = letBindings.Bindings.[0]
let replaceRange = TreeRange(binding.NextSibling, letBindings.LastChild)
let replaced = ModificationUtil.ReplaceChildRange(replaceRange, ranges.InRange)
- if ranges.AddNewLine then
+ if isInSingleLineContext then
+ addNodesBefore replaced.First [
+ Whitespace()
+ FSharpTokenType.IN.CreateLeafElement()
+ Whitespace()
+ ] |> ignore
+ elif ranges.AddNewLine then
let anchor = ModificationUtil.AddChildBefore(replaced.First, NewLine(lineEnding))
ModificationUtil.AddChildAfter(anchor, Whitespace(contextIndent)) |> ignore
+
+ ModificationUtil.DeleteChildRange(letBindings.NextSibling, letBindings.Parent.LastChild)
letBindings
| :? ILetModuleDecl ->
@@ -227,19 +382,25 @@ type FSharpIntroduceVariable(workflow, solution, driver) =
let nodes =
let replacedNodes =
replacedUsages
- |> Array.choose (fun pointer -> pointer.GetTreeNode() |> Option.ofObj)
+ |> Seq.choose (fun pointer -> pointer.GetTreeNode() |> Option.ofObj)
+ |> Seq.toArray
- [| letBindings.As().Bindings.[0].HeadPattern :> ITreeNode |]
+ [| letBindings.As().Bindings.[0].HeadPattern :> ITreeNode |]
|> Array.append replacedNodes
let nameExpression = NameSuggestionsExpression(names)
let hotspotsRegistry = HotspotsRegistry(solution.GetPsiServices())
hotspotsRegistry.Register(nodes, nameExpression)
- let expr = letBindings.Bindings.[0].Expression
- IntroduceVariableResult(hotspotsRegistry, expr.As().CreateTreeElementPointer())
+ let caretTarget =
+ if isInSingleLineContext && replaceSourceExprNode then
+ letBindings.LastChild
+ else
+ letBindings.Bindings.[0].Expression :> _
+
+ IntroduceVariableResult(hotspotsRegistry, caretTarget.CreateTreeElementPointer())
- static member IntroduceVar(expr: ISynExpr, textControl: ITextControl, ?removeSourceExpr) =
+ static member IntroduceVar(expr: IFSharpExpression, textControl: ITextControl, ?removeSourceExpr) =
let removeSourceExpr = defaultArg removeSourceExpr false
let name = "FSharpIntroduceVar"
@@ -258,22 +419,17 @@ type FSharpIntroduceVariable(workflow, solution, driver) =
let dataContext = actionManager.DataContexts.CreateWithDataRules(lifetime.Lifetime, rules)
if removeSourceExpr then
- expr.UserData.PutKey(FSharpIntroduceVariable.ExpressionToRemove)
+ expr.UserData.PutKey(FSharpIntroduceVariable.ExpressionToRemoveKey)
let workflow = IntroduceVariableWorkflow(solution, null)
RefactoringActionUtil.ExecuteRefactoring(dataContext, workflow)
- static member CanIntroduceVar(expr: ISynExpr, allowInSeqExprOnly) =
+ static member CanIntroduceVar(expr: IFSharpExpression) =
if not (isValid expr) then false else
- let isInSeqExpr (expr: ISynExpr) =
- let sequentialExpr = SequentialExprNavigator.GetByExpression(expr)
- if isNull sequentialExpr then false else
+ let rec isValidExpr (expr: IFSharpExpression) =
+ if FSharpMethodInvocationUtil.isNamedArgReference expr then false else
- let nextMeaningfulSibling = expr.GetNextMeaningfulSibling()
- nextMeaningfulSibling :? ISynExpr && nextMeaningfulSibling.Indent = expr.Indent
-
- let rec isValidExpr (expr: ISynExpr) =
match expr with
| :? IReferenceExpr as refExpr ->
let declaredElement = refExpr.Reference.Resolve().DeclaredElement
@@ -282,15 +438,16 @@ type FSharpIntroduceVariable(workflow, solution, driver) =
| :? IParenExpr as parenExpr ->
isValidExpr parenExpr.InnerExpression
+ | :? IRangeSequenceExpr | :? IComputationExpr | :? IYieldOrReturnExpr -> false
+
| _ -> true
- let isAllowedContext (expr: ISynExpr) =
- let topLevelExpr = skipIntermediateParentsOfSameType(expr)
+ let isAllowedContext (expr: IFSharpExpression) =
+ let topLevelExpr = skipIntermediateParentsOfSameType(expr)
if isNotNull (AttributeNavigator.GetByExpression(topLevelExpr)) then false else
true
- if allowInSeqExprOnly && not (isInSeqExpr expr) then false else
if not (isAllowedContext expr) then false else
isValidExpr expr
@@ -299,18 +456,18 @@ type FSharpIntroduceVarHelper() =
inherit IntroduceVariableHelper()
let isExpressionToRemove (expr: ITreeNode) =
- expr.UserData.HasKey(FSharpIntroduceVariable.ExpressionToRemove)
+ expr.UserData.HasKey(FSharpIntroduceVariable.ExpressionToRemoveKey)
override x.IsLanguageSupported = true
override x.CheckAvailability(node) =
- let expr = node.As()
+ let expr = node.As()
if isNull expr then false else
- if expr.UserData.HasKey(FSharpIntroduceVariable.ExpressionToRemove) then true else
+ if expr.UserData.HasKey(FSharpIntroduceVariable.ExpressionToRemoveKey) then true else
if not (expr.FSharpExperimentalFeaturesEnabled()) then false else
- FSharpIntroduceVariable.CanIntroduceVar(expr, false)
+ FSharpIntroduceVariable.CanIntroduceVar(expr)
override x.CheckOccurrence(expr, occurrence) =
if isExpressionToRemove occurrence then true else
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/Rename.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/Rename.fs
index 1ec72e70a8..083ffa2d9d 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/Rename.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Refactorings/Rename.fs
@@ -86,18 +86,22 @@ type FSharpRenameHelper(namingService: FSharpNamingService) =
newDeclaredElement.PresentationLanguage.Is()
override x.IsLocalRename(element: IDeclaredElement) =
+ if not (element :? IFSharpLocalDeclaration) then false else
+
match element with
- | :? IParametersOwnerPat as longIdentPat -> longIdentPat.IsDeclaration
- | _ -> element :? IFSharpLocalDeclaration
+ | :? INamedPat as namedPat -> namedPat.IsDeclaration
+ | _ -> true
- override x.CheckLocalRenameSameDocument(element: IDeclaredElement) = x.IsLocalRename(element)
+ override x.CheckLocalRenameSameDocument(element: IDeclaredElement) =
+ x.IsLocalRename(element)
override x.GetSecondaryElements(element: IDeclaredElement, newName) =
match element with
| :? ILocalReferencePat as localNamedPat ->
- let mutable pat = localNamedPat :> ISynPat
- while (pat.Parent :? ISynPat) && not (pat.Parent :? IParametersOwnerPat && (pat.Parent :?> ISynPat).IsDeclaration) do
- pat <- pat.Parent :?> ISynPat
+ let mutable pat = localNamedPat :> IFSharpPattern
+ while pat.Parent :? IFSharpPattern &&
+ not (pat.Parent :? IParametersOwnerPat && (pat.Parent :?> IFSharpPattern).IsDeclaration) do
+ pat <- pat.Parent :?> IFSharpPattern
pat.Declarations
|> Seq.cast
@@ -109,7 +113,7 @@ type FSharpRenameHelper(namingService: FSharpNamingService) =
| :? IGeneratedConstructorParameterOwner as parameterOwner ->
[| parameterOwner.GetParameter() :> IDeclaredElement |] :> _
- | :? IModule -> EmptyArray.Instance :> _
+ | :? IFSharpModule -> EmptyArray.Instance :> _
| :? IFSharpTypeElement as fsTypeElement ->
match fsTypeElement.GetModuleToUpdateName(newName) with
@@ -181,12 +185,12 @@ type FSharpAtomicRenamesFactory() =
override x.CheckRenameAvailability(element: IDeclaredElement) =
match element with
| :? FSharpGeneratedMemberBase -> RenameAvailabilityCheckResult.CanNotBeRenamed
- | :? IParametersOwnerPat as pat when not pat.IsDeclaration -> RenameAvailabilityCheckResult.CanNotBeRenamed
+ | :? INamedPat as pat when not pat.IsDeclaration -> RenameAvailabilityCheckResult.CanNotBeRenamed
| :? IFSharpDeclaredElement as fsElement when fsElement.SourceName = SharedImplUtil.MISSING_DECLARATION_NAME ->
RenameAvailabilityCheckResult.CanNotBeRenamed
- | :? IModule as fsModule when fsModule.IsAnonymous ->
+ | :? IFSharpModule as fsModule when fsModule.IsAnonymous ->
RenameAvailabilityCheckResult.CanNotBeRenamed // todo: needs a special implementation
| _ ->
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpItemOccurrenceKind.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpItemOccurrenceKind.fs
index 1605f0ba1b..b3806685e9 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpItemOccurrenceKind.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpItemOccurrenceKind.fs
@@ -63,35 +63,35 @@ type FSharpItemOccurenceKindProvider() =
if isNotNull (NewExprNavigator.GetByTypeName(typeReferenceName)) then
[| OccurrenceKind.NewInstanceCreation |] :> _ else
- let namedType = NamedTypeNavigator.GetByReferenceName(typeReferenceName)
- if isNull namedType then EmptyList.Instance :> _ else
+ let namedTypeUsage = NamedTypeUsageNavigator.GetByReferenceName(typeReferenceName)
+ if isNull namedTypeUsage then EmptyList.Instance :> _ else
// todo: return type in `a -> b`
- if isNotNull (ReturnTypeInfoNavigator.GetByReturnType(namedType)) then
+ if isNotNull (ReturnTypeInfoNavigator.GetByReturnType(namedTypeUsage)) then
[| FSharpOccurrenceKinds.typeSpecification |] :> _ else
- if isNotNull (AnonRecordFieldNavigator.GetByType(namedType)) ||
- isNotNull (RecordFieldDeclarationNavigator.GetByType(namedType)) ||
- isNotNull (CaseFieldDeclarationNavigator.GetByType(namedType)) then
+ if isNotNull (AnonRecordFieldNavigator.GetByType(namedTypeUsage)) ||
+ isNotNull (RecordFieldDeclarationNavigator.GetByType(namedTypeUsage)) ||
+ isNotNull (CaseFieldDeclarationNavigator.GetByType(namedTypeUsage)) then
[| OccurrenceKind.FieldTypeDeclaration |] :> _ else
- if isNotNull (TypedPatNavigator.GetByType(namedType)) ||
- isNotNull (TypedExprNavigator.GetByType(namedType)) then
+ if isNotNull (TypedPatNavigator.GetByType(namedTypeUsage)) ||
+ isNotNull (TypedExprNavigator.GetByType(namedTypeUsage)) then
[| FSharpOccurrenceKinds.typeSpecification |] :> _ else
- if isNotNull (IsInstPatNavigator.GetByType(namedType)) ||
- isNotNull (TypeTestExprNavigator.GetByTypeUsage(namedType)) then
+ if isNotNull (IsInstPatNavigator.GetByType(namedTypeUsage)) ||
+ isNotNull (TypeTestExprNavigator.GetByTypeUsage(namedTypeUsage)) then
[| CSharpSpecificOccurrenceKinds.TypeChecking |] :> _ else
- if isNotNull (CastExprNavigator.GetByTypeUsage(namedType)) then
+ if isNotNull (CastExprNavigator.GetByTypeUsage(namedTypeUsage)) then
[| CSharpSpecificOccurrenceKinds.TypeConversions |] :> _ else
- if isNotNull (TypeAbbreviationDeclarationNavigator.GetByAbbreviatedType(namedType)) then
+ if isNotNull (TypeAbbreviationDeclarationNavigator.GetByAbbreviatedType(namedTypeUsage)) then
[| FSharpOccurrenceKinds.typeAbbreviation |] :> _ else
- if isNotNull (TypeArgumentListNavigator.GetByType(namedType)) ||
- isNotNull (TupleTypeNavigator.GetByItem(namedType)) ||
- isNotNull (ArrayTypeNavigator.GetByType(namedType)) then
+ if isNotNull (TypeArgumentListNavigator.GetByType(namedTypeUsage)) ||
+ isNotNull (TupleTypeUsageNavigator.GetByItem(namedTypeUsage)) ||
+ isNotNull (ArrayTypeUsageNavigator.GetByType(namedTypeUsage)) then
[| CSharpSpecificOccurrenceKinds.TypeArgument |] :> _ else
EmptyList.Instance :> _
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpPathReference.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpPathReference.fs
index a6ee0a5ec5..f0b2a728e3 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpPathReference.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpPathReference.fs
@@ -48,7 +48,7 @@ type FSharpPathReference(owner, sourceFile) =
let fsFile = owner.GetContainingFile() :?> IFSharpFile
let document = sourceFile.Document
let tokenStartOffset = owner.Parent.GetTreeStartOffset()
- fsFile.CheckerService.OptionsProvider.GetProjectOptions(sourceFile)
+ fsFile.CheckerService.FcsProjectProvider.GetProjectOptions(sourceFile)
|> Option.bind (fun options ->
options.OriginalLoadReferences
|> List.tryFind (fun (range, _, _) -> getTreeStartOffset document range = tokenStartOffset)
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpSearchGuru.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpSearchGuru.fs
index d69afa7527..cd3b2c69cd 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpSearchGuru.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Search/FSharpSearchGuru.fs
@@ -8,50 +8,55 @@ open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Psi.ExtensionsAPI.Finder
open JetBrains.ReSharper.Psi.Modules
-type ElementDeclarationFileIndex =
- { FileIndex: int
- Module: IPsiModule }
+type FSharpSearchGuruElementId =
+ { DeclaredElement: IDeclaredElement
+ PsiModule: IPsiModule
+ FileIndex: int }
[]
-type FSharpSearchGuru(fsProjectOptionsProvider: IFSharpProjectOptionsProvider) =
+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.IsAvailable _ = true
member x.BuzzWordFilter(_, words) = words
member x.GetElementId(element) =
- match element.As() with
- | null -> null
- | fsElement ->
+ let fsDeclaredElement = element.As()
+ if isNull fsDeclaredElement then null else
- match getTypeElement fsElement with
- | null -> null
- | typeElement ->
+ let typeElement = getTypeElement fsDeclaredElement
+ if isNull typeElement then null else
- let sourceFiles = typeElement.GetSourceFiles().ReadOnlyList()
- if sourceFiles.Count = 0 then null else
+ let sourceFiles = typeElement.GetSourceFiles()
+ if sourceFiles.IsEmpty then null else
let declarationFileIndex =
- sourceFiles
- |> Seq.map (fun sourceFile -> fsProjectOptionsProvider.GetFileIndex(sourceFile))
+ sourceFiles.ReadOnlyList()
+ |> Seq.map fsProjectOptionsProvider.GetFileIndex
|> Seq.min
if declarationFileIndex = -1 then null else
- { Module = typeElement.Module
+ { DeclaredElement = element
+ PsiModule = fsDeclaredElement.Module
FileIndex = declarationFileIndex } :> _
member x.CanContainReferences(sourceFile, elementId) =
- let fileIndex = elementId :?> ElementDeclarationFileIndex
-
if not (sourceFile.LanguageType.Is()) then true else
- if sourceFile.PsiModule != fileIndex.Module 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 >= fileIndex.FileIndex
+ sourceFileIndex >= fsElementId.FileIndex
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpAttributesUtil.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpAttributesUtil.fs
index e032de4a3c..fbd4de3dda 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpAttributesUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpAttributesUtil.fs
@@ -1,9 +1,9 @@
module JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util.FSharpAttributesUtil
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpAutoOpenUtil.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpAutoOpenUtil.fs
new file mode 100644
index 0000000000..3a2e5cded0
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpAutoOpenUtil.fs
@@ -0,0 +1,39 @@
+[]
+module JetBrains.ReSharper.Plugins.FSharp.Psi.Util.FSharpAutoOpenUtil
+
+open System.Collections.Generic
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
+open JetBrains.ReSharper.Plugins.FSharp.Util
+open JetBrains.ReSharper.Plugins.FSharp.Util.FSharpAssemblyUtil
+open JetBrains.ReSharper.Psi
+open JetBrains.ReSharper.Psi.Caches
+open JetBrains.ReSharper.Psi.Impl.Reflection2
+open JetBrains.Util
+
+let rec getNestedAutoImportedModules (declaredElement: IClrDeclaredElement) (symbolScope: ISymbolScope) = seq {
+ for typeElement in getNestedTypes declaredElement symbolScope do
+ if typeElement.HasAutoOpenAttribute() then
+ yield typeElement
+ yield! getNestedAutoImportedModules typeElement symbolScope }
+
+let getAutoOpenModules (psiAssemblyFileLoader: IPsiAssemblyFileLoader) (assembly: IPsiAssembly) =
+ let result = List()
+
+ psiAssemblyFileLoader.GetOrLoadAssembly(assembly, true, fun psiAssembly assemblyFile metadataAssembly ->
+ let attributesSet = assemblyFile.CreateAssemblyAttributes()
+ let attributes = getAutoOpenAttributes attributesSet
+
+ if attributes.IsEmpty() then () else
+
+ let psiServices = psiAssembly.PsiModule.GetPsiServices()
+ let symbolScope = psiServices.Symbols.GetSymbolScope(psiAssembly.PsiModule, false, true)
+
+ for attribute in attributes do
+ let moduleString = attribute.PositionParameter(0).ConstantValue.Value.As()
+ if moduleString.IsNullOrEmpty() then () else
+
+ for declaredElement in symbolScope.GetElementsByQualifiedName(moduleString) do
+ result.Add(declaredElement)
+ result.AddRange(getNestedAutoImportedModules declaredElement symbolScope)) |> ignore
+
+ result
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpExpressionUtil.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpExpressionUtil.fs
index b6a0421a29..c9e945ebf7 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpExpressionUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpExpressionUtil.fs
@@ -2,17 +2,17 @@
module JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util.FSharpExpressionUtil
open JetBrains.Diagnostics
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Psi.Tree
-let isPredefinedFunctionRef name (expr: ISynExpr) =
+let isPredefinedFunctionRef name (expr: IFSharpExpression) =
let refExpr = expr.IgnoreInnerParens().As()
if isNull refExpr then false else
@@ -31,7 +31,7 @@ let inline isPredefinedInfixOpApp name (binaryAppExpr: IBinaryAppExpr) =
if isNull binaryAppExpr then false else
isPredefinedFunctionRef name binaryAppExpr.Operator
-let inline isPredefinedFunctionApp name (expr: ISynExpr) (arg: outref) =
+let inline isPredefinedFunctionApp name (expr: IFSharpExpression) (arg: outref) =
match expr with
| :? IPrefixAppExpr as prefixApp when
isPredefinedFunctionRef name prefixApp.FunctionExpression ->
@@ -52,7 +52,7 @@ let inline isPredefinedFunctionApp name (expr: ISynExpr) (arg: outref)
| _ -> false
-let rec createLogicallyNegatedExpression (expr: ISynExpr): ISynExpr =
+let rec createLogicallyNegatedExpression (expr: IFSharpExpression): IFSharpExpression =
if isNull expr then null else
let expr = expr.IgnoreInnerParens()
@@ -65,7 +65,7 @@ let rec createLogicallyNegatedExpression (expr: ISynExpr): ISynExpr =
let binaryApp = expr.As()
- let replaceBinaryApp nameTo negateArgs: ISynExpr =
+ let replaceBinaryApp nameTo negateArgs: IFSharpExpression =
let arg1 = binaryApp.LeftArgument
let arg2 = binaryApp.RightArgument
@@ -101,10 +101,25 @@ let rec createLogicallyNegatedExpression (expr: ISynExpr): ISynExpr =
factory.CreateAppExpr("not", expr) :> _
-let setBindingExpression (expr: ISynExpr) contextIndent (letBindings: #ILet) =
+let setBindingExpression (expr: IFSharpExpression) contextIndent (letBindings: #ILetBindings) =
let newExpr = letBindings.Bindings.[0].SetExpression(expr.Copy())
if not expr.IsSingleLine then
let indentSize = expr.GetIndentSize()
ModificationUtil.AddChildBefore(newExpr, NewLine(expr.GetLineEnding())) |> ignore
ModificationUtil.AddChildBefore(newExpr, Whitespace(contextIndent + indentSize)) |> ignore
shiftExpr indentSize newExpr
+
+let rec isTypeEvident (expr: IFSharpExpression) =
+ match expr.IgnoreInnerParens() with
+ | :? IObjExpr
+ | :? ICastExpr
+ | :? ILambdaExpr
+ | :? ILiteralExpr -> true
+ | :? ITupleExpr as tupleExpr ->
+ tupleExpr.Expressions |> Seq.forall isTypeEvident
+ | :? IArrayOrListExpr as arrayOrListExpr ->
+ match arrayOrListExpr.Expression with
+ | :? ISequentialExpr as seqExpr ->
+ isTypeEvident (seqExpr.ExpressionsEnumerable.FirstOrDefault())
+ | _ -> false
+ | _ -> false
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpMethodInvocationUtil.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpMethodInvocationUtil.fs
index 35ef224c23..d2b6f19197 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpMethodInvocationUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpMethodInvocationUtil.fs
@@ -1,44 +1,88 @@
module JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util.FSharpMethodInvocationUtil
+open FSharp.Compiler.SourceCodeServices
open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
open JetBrains.ReSharper.Psi
-open JetBrains.ReSharper.Psi.Tree
+open JetBrains.ReSharper.Psi.ExtensionsAPI
-let tryGetNamedArg (expr: ISynExpr) =
+let tryGetNamedArgRefExpr (expr: IFSharpExpression) =
let binaryAppExpr = expr.As()
if isNull binaryAppExpr then null else
-
if binaryAppExpr.Operator.Reference.GetName() <> "=" then null else
- let refExpr = binaryAppExpr.LeftArgument.As()
- if isNull refExpr then null else
+ binaryAppExpr.LeftArgument.As()
+
+
+let isNamedArgReference (expr: IFSharpExpression) =
+ let refExpr = tryGetNamedArgRefExpr expr
+ if isNull refExpr then false else
+
+ match refExpr.Reference.GetFSharpSymbol() with
+ | :? FSharpParameter -> true
+ | :? FSharpField as fsField -> fsField.IsUnionCaseField
+ | _ -> false
+
+
+let tryGetNamedArg (expr: IFSharpExpression) =
+ match tryGetNamedArgRefExpr expr with
+ | null -> null
+ | refExpr -> refExpr.Reference.Resolve().DeclaredElement.As()
+
+
+let getMatchingParameter (expr: IFSharpExpression) =
+ let argsOwner =
+ let tupleExpr = TupleExprNavigator.GetByExpression(expr.IgnoreParentParens())
+ let exprContext = if isNull tupleExpr then expr else tupleExpr :> _
+ FSharpArgumentOwnerNavigator.GetByArgumentExpression(exprContext.IgnoreParentParens())
+
+ if isNull argsOwner then null else
+
+ let namedArgRefExpr = tryGetNamedArgRefExpr expr
+
+ let namedParam =
+ match namedArgRefExpr with
+ | null -> null
+ | namedRef -> namedRef.Reference.Resolve().DeclaredElement.As()
- refExpr.Reference.Resolve().DeclaredElement.As()
+ if isNotNull namedParam then namedParam else
-let getMatchingParameter (initialExpr: ISynExpr) =
- let expr = initialExpr.IgnoreInnerParens()
- let tupleExpr = TupleExprNavigator.GetByExpression(expr)
- let tupleExprContext = tupleExpr.IgnoreParentParens()
+ let symbolReference = argsOwner.Reference
+ if isNull symbolReference then null else
- let appExpr = PrefixAppExprNavigator.GetByArgumentExpression(if isNull tupleExpr then expr else tupleExprContext)
- if isNull appExpr then null else
+ let mfv =
+ symbolReference.TryGetFSharpSymbol()
+ |> Option.bind (function
+ | :? FSharpMemberOrFunctionOrValue as mfv -> Some mfv
+ | _ -> None)
- let refExpr = appExpr.FunctionExpression.As()
- if isNull refExpr then null else
+ match mfv with
+ | None -> null
+ | Some mfv ->
- use compilationContextCookie = CompilationContextCookie.OverrideOrCreate(expr.GetResolveContext())
+ let paramOwner = symbolReference.Resolve().DeclaredElement.As()
+ if isNull paramOwner then null else
- let parameter = tryGetNamedArg initialExpr
- if isNotNull parameter then parameter else
+ let param =
+ if isNotNull namedArgRefExpr then
+ // If this is a named argument, but FCS couldn't match it, try matching ourselves by name
+ paramOwner.Parameters
+ |> Seq.tryFind (fun param -> param.ShortName = namedArgRefExpr.Reference.GetName())
+ else
+ let args = argsOwner.ParameterArguments
+ match args |> Seq.tryFindIndex (fun argExpr -> expr.Equals(argExpr)) with
+ | None -> None
+ | Some paramIndex ->
- let method = refExpr.Reference.Resolve().DeclaredElement.As()
- let parameters = method.Parameters
- if parameters.Count = 1 then parameters.[0] else
+ let invokingExtensionMethod = mfv.IsExtensionMember && Some mfv.ApparentEnclosingEntity <> mfv.DeclaringEntity
+ let offset = if invokingExtensionMethod then 1 else 0
+ Some paramOwner.Parameters.[paramIndex + offset]
- let index = tupleExpr.Expressions.IndexOf(expr)
- if index < parameters.Count then parameters.[index] else null
+ // Skip unnamed parameters
+ match param with
+ | Some param when param.ShortName <> SharedImplUtil.MISSING_DECLARATION_NAME -> param
+ | _ -> null
[)>]
type FSharpMethodInvocationUtil() =
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpParensUtil.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpParensUtil.fs
index ef1dbf241e..376f0433b9 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpParensUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpParensUtil.fs
@@ -3,13 +3,13 @@ module JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util.FSharpParensUtil
open System
open FSharp.Compiler
+open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
open JetBrains.ReSharper.Psi.Tree
-let deindentsBody (expr: ISynExpr) =
+let deindentsBody (expr: IFSharpExpression) =
match expr with
| :? IMatchClauseListOwner as matchExpr ->
if expr.IsSingleLine then false else
@@ -31,7 +31,7 @@ let deindentsBody (expr: ISynExpr) =
let (|Prefix|_|) (other: string) (str: string) =
if str.StartsWith(other, StringComparison.Ordinal) then someUnit else None
-let precedence (expr: ISynExpr): int =
+let precedence (expr: IFSharpExpression): int =
match expr with
| :? IBinaryAppExpr as binaryApp ->
let refExpr = binaryApp.Operator
@@ -71,9 +71,9 @@ let isHighPrecedenceApp (appExpr: IPrefixAppExpr) =
let argStartOffset = argExpr.GetTreeStartOffset()
funEndOffset = argStartOffset
-let private canBeTopLevelArgInHighPrecedenceApp (expr: ISynExpr) =
- expr :? IArrayOrListExpr || expr :? IArrayOrListOfSeqExpr ||
- expr :? IObjExpr || expr :? IRecordExpr
+let private canBeTopLevelArgInHighPrecedenceApp (expr: IFSharpExpression) =
+ // todo: check `ignore{| Field = 1 + 1 |}.Field` vs `ignore[].Head`
+ expr :? IArrayOrListExpr || expr :? IObjExpr || expr :? IRecordLikeExpr
let rec private isHighPrecedenceAppRequired (appExpr: IPrefixAppExpr) =
let argExpr = appExpr.ArgumentExpression.IgnoreInnerParens()
@@ -83,7 +83,7 @@ let rec private isHighPrecedenceAppRequired (appExpr: IPrefixAppExpr) =
false
-let rec needsParens (expr: ISynExpr) =
+let rec needsParens (expr: IFSharpExpression) =
if isNull expr then false else
let context = expr.IgnoreParentParens()
@@ -98,10 +98,8 @@ let rec needsParens (expr: ISynExpr) =
| :? IParenExpr | :? IQuoteExpr
| :? IConstExpr | :? INullExpr
- | :? IRecordExpr | :? IAnonRecdExpr
- | :? IArrayOrListExpr | :? IArrayOrListOfSeqExpr
- | :? IObjExpr | :? IComputationLikeExpr
- | :? IAddressOfExpr -> false
+ | :? IRecordLikeExpr | :? IArrayOrListExpr | :? IComputationExpr
+ | :? IObjExpr | :? IAddressOfExpr -> false
| :? IBinaryAppExpr as binaryAppExpr when
isNotNull (AppExprNavigator.GetByArgument(context)) ->
@@ -140,7 +138,7 @@ let rec needsParens (expr: ISynExpr) =
precedence binaryApp.LeftArgument < precedence binaryApp
-let addParens (expr: ISynExpr) =
+let addParens (expr: IFSharpExpression) =
let exprCopy = expr.Copy()
let factory = expr.CreateElementFactory()
@@ -152,6 +150,6 @@ let addParens (expr: ISynExpr) =
expr
-let addParensIfNeeded (expr: ISynExpr) =
+let addParensIfNeeded (expr: IFSharpExpression) =
if not (needsParens expr) then expr else
addParens expr
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpResolveUtil.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpResolveUtil.fs
new file mode 100644
index 0000000000..721846bc50
--- /dev/null
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/FSharpResolveUtil.fs
@@ -0,0 +1,34 @@
+module JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Util.FSharpResolveUtil
+
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Resolve
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
+open JetBrains.ReSharper.Plugins.FSharp.Util
+open JetBrains.ReSharper.Psi
+open JetBrains.ReSharper.Psi.Impl.Reflection2
+
+let private resolvesTo (declaredElement: IDeclaredElement) (reference: FSharpSymbolReference) qualified opName =
+ match reference.ResolveWithFcs(opName, qualified) with
+ | None -> false
+ | Some symbolUse ->
+
+ let referenceOwner = reference.GetElement()
+ let unqualifiedElement = symbolUse.Symbol.GetDeclaredElement(referenceOwner.GetPsiModule(), referenceOwner)
+ if declaredElement.Equals(unqualifiedElement) then true else
+
+ // Workaround for case where unqualified resolve may return module with implicit suffix instead of type.
+ let compiledTypeElement = unqualifiedElement.As()
+ if isNull compiledTypeElement then false else
+
+ let shortName = reference.GetName()
+ if not (unqualifiedElement.ShortName.HasModuleSuffix() && not (shortName.HasModuleSuffix())) then false else
+ if not (isCompiledModule compiledTypeElement) then false else
+
+ let typeElement = FSharpImplUtil.TryGetAssociatedType(compiledTypeElement, shortName)
+ declaredElement.Equals(typeElement)
+
+let resolvesToUnqualified (declaredElement: IDeclaredElement) (reference: FSharpSymbolReference) opName =
+ resolvesTo declaredElement reference false opName
+
+let resolvesToQualified (declaredElement: IDeclaredElement) (reference: FSharpSymbolReference) opName =
+ resolvesTo declaredElement reference true opName
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/IFSharpElementFactory.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/IFSharpElementFactory.fs
deleted file mode 100644
index 830b1fde76..0000000000
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/IFSharpElementFactory.fs
+++ /dev/null
@@ -1,46 +0,0 @@
-namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Util
-
-open JetBrains.DocumentModel
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
-open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
-open JetBrains.ReSharper.Psi.Modules
-
-type IFSharpElementFactory =
- abstract CreateOpenStatement: ns: string -> IOpenStatement
- abstract CreateWildPat: unit -> IWildPat
-
- abstract CreateParenExpr: unit -> IParenExpr
- abstract CreateParenExpr: ISynExpr -> IParenExpr
-
- abstract CreateConstExpr: text: string -> IConstExpr
-
- abstract CreateAppExpr: addSpace: bool -> IPrefixAppExpr
- abstract CreateAppExpr: funcName: string * arg: ISynExpr -> IPrefixAppExpr
- abstract CreateAppExpr: funExpr: ISynExpr * argExpr: ISynExpr * addSpace: bool -> IPrefixAppExpr
- abstract CreateBinaryAppExpr: string * left: ISynExpr * right: ISynExpr -> ISynExpr
- abstract CreateSetExpr: left: ISynExpr * right: ISynExpr -> ISynExpr
-
- abstract CreateExpr: string -> ISynExpr
- abstract CreateReferenceExpr: string -> ISynExpr
-
- abstract CreateLetBindingExpr: bindingName: string -> ILetOrUseExpr
- abstract CreateLetModuleDecl: bindingName: string -> ILetModuleDecl
-
- abstract CreateIgnoreApp: ISynExpr * newLine: bool -> IBinaryAppExpr
- abstract CreateRecordExprBinding: fieldName: string * addSemicolon: bool -> IRecordExprBinding
-
- abstract CreateMatchExpr: ISynExpr -> IMatchExpr
- abstract CreateMatchClause: unit -> IMatchClause
-
- abstract CreateForEachExpr: ISynExpr -> IForEachExpr
-
- abstract AsReferenceExpr: typeReference: ITypeReferenceName -> IReferenceExpr
-
- abstract CreateEmptyAttributeList: unit -> IAttributeList
- abstract CreateAttribute: attrName: string -> IAttribute
-
-
-[]
-type IFSharpLanguageService =
- abstract CreateParser: IDocument -> IFSharpParser
- abstract CreateElementFactory: IPsiModule -> IFSharpElementFactory
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/OpensUtil.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/OpensUtil.fs
index 28cf24cb8c..ec7f8c3747 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/OpensUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/OpensUtil.fs
@@ -1,12 +1,14 @@
[]
module JetBrains.ReSharper.Plugins.FSharp.Psi.Util.OpensUtil
+open System.Collections.Generic
open JetBrains.Application.Settings
open JetBrains.DocumentModel
open JetBrains.ReSharper.Plugins.FSharp.Psi
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
+open JetBrains.ReSharper.Plugins.FSharp.Psi.Util
open JetBrains.ReSharper.Plugins.FSharp.Settings
open JetBrains.ReSharper.Plugins.FSharp.Util
open JetBrains.ReSharper.Psi
@@ -140,3 +142,47 @@ let addOpen (offset: DocumentOffset) (fsFile: IFSharpFile) (settings: IContextBo
| _ -> failwithf "Unexpected module: %O" moduleDecl
insertAfterAnchor anchor indent
+
+let isInOpen (referenceName: IReferenceName) =
+ match skipIntermediateParentsOfSameType referenceName with
+ | null -> false
+ | node -> node.Parent :? IOpenStatement
+
+type OpenedModulesProvider(fsFile: IFSharpFile) =
+ let map = HashSet()
+
+ let psiModule = fsFile.GetPsiModule()
+ let symbolScope = getModuleOnlySymbolScope psiModule
+
+// let getQualifiedName (element: IClrDeclaredElement) =
+// match toQualifiedList element with
+// | [] -> "global"
+// | names -> names |> List.map (fun el -> el.GetSourceName()) |> String.concat "."
+
+ let import (element: IClrDeclaredElement) =
+ map.Add(element.GetSourceName()) |> ignore
+ for autoImportedModule in getNestedAutoImportedModules element symbolScope do
+ map.Add(autoImportedModule.GetSourceName()) |> ignore
+
+ do
+ import symbolScope.GlobalNamespace
+
+ for moduleDecl in fsFile.ModuleDeclarationsEnumerable do
+ let topLevelModuleDecl = moduleDecl.As()
+ if isNotNull topLevelModuleDecl then
+ match topLevelModuleDecl.DeclaredElement with
+ | :? INamespace as ns -> import ns
+ | :? ITypeElement as ty -> import (ty.GetContainingNamespace())
+ | _ -> ()
+
+ match fsFile.GetParseAndCheckResults(true, "OpenedModulesProvider") with
+ | None -> ()
+ | Some results ->
+
+ for fcsOpenDecl in results.CheckResults.OpenDeclarations do
+ for fcsEntity in fcsOpenDecl.Modules do
+ let declaredElement = fcsEntity.GetDeclaredElement(psiModule).As()
+ if isNotNull declaredElement then
+ import declaredElement
+
+ member x.GetOpenedModuleNames = map
diff --git a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/PsiUtil.fs b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/PsiUtil.fs
index 10cb8cbc99..70c70ebe56 100644
--- a/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/PsiUtil.fs
+++ b/ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/PsiUtil.fs
@@ -1,5 +1,5 @@
[]
-module JetBrains.ReSharper.Plugins.FSharp.Psi.Util.PsiUtil
+module JetBrains.ReSharper.Plugins.FSharp.Psi.PsiUtil
open FSharp.Compiler.Range
open JetBrains.Application.Settings
@@ -60,15 +60,6 @@ type IFile with
x.GetNode<'T>(documentRange.StartOffset)
type IFSharpTreeNode with
- member x.FSharpLanguageService =
- x.Language.LanguageService().As()
-
- member x.CreateElementFactory() =
- x.FSharpLanguageService.CreateElementFactory(x.GetPsiModule())
-
- member x.CheckerService =
- x.FSharpFile.CheckerService
-
member x.GetLineEnding() =
let fsFile = x.FSharpFile
fsFile.DetectLineEnding(fsFile.GetPsiServices()).GetPresentation()
@@ -131,9 +122,10 @@ let (|TokenType|_|) tokenType (treeNode: ITreeNode) =
let (|Whitespace|_|) (treeNode: ITreeNode) =
if getTokenType treeNode == FSharpTokenType.WHITESPACE then Some treeNode else None
-let inline (|IgnoreParenPat|) (pat: ISynPat) = pat.IgnoreParentParens()
+let inline (|IgnoreParenPat|) (fsPattern: IFSharpPattern) =
+ fsPattern.IgnoreParentParens()
-let inline (|IgnoreInnerParenExpr|) (expr: ISynExpr) =
+let inline (|IgnoreInnerParenExpr|) (expr: IFSharpExpression) =
expr.IgnoreInnerParens()
let isInlineSpaceOrComment (node: ITreeNode) =
@@ -328,8 +320,8 @@ let rec skipIntermediateParentsOfSameType<'T when 'T :> ITreeNode> (node: 'T) =
| :? 'T as pat -> skipIntermediateParentsOfSameType pat
| _ -> node
-let rec skipIntermediatePatParents (pat: ISynPat) =
- skipIntermediateParentsOfSameType pat
+let rec skipIntermediatePatParents (fsPattern: IFSharpPattern) =
+ skipIntermediateParentsOfSameType fsPattern
let inline isValid (node: ^T) =
@@ -338,7 +330,7 @@ let inline isValid (node: ^T) =
[)>]
type FSharpExpressionSelectionProvider() =
- inherit ExpressionSelectionProviderBase()
+ inherit ExpressionSelectionProviderBase()
override x.IsTokenSkipped(token) =
// todo: also ;; ?
@@ -357,7 +349,7 @@ let shouldEraseSemicolon (node: ITreeNode) =
not (settingsStore.GetValue(fun (key: FSharpFormatSettingsKey) -> key.SemicolonAtEndOfLine))
-let shiftExpr shift (expr: ISynExpr) =
+let shiftExpr shift (expr: IFSharpExpression) =
if shift = 0 then () else
for child in List.ofSeq (expr.Tokens()) do
@@ -382,13 +374,13 @@ let shiftExpr shift (expr: ISynExpr) =
ModificationUtil.AddChildAfter(child, Whitespace(shift)) |> ignore
-let rec tryFindRootPrefixAppWhereExpressionIsFunc (expr: ISynExpr) =
+let rec tryFindRootPrefixAppWhereExpressionIsFunc (expr: IFSharpExpression) =
let prefixApp = PrefixAppExprNavigator.GetByFunctionExpression(expr.IgnoreParentParens())
if isNotNull prefixApp && isNotNull prefixApp.ArgumentExpression then
tryFindRootPrefixAppWhereExpressionIsFunc(prefixApp)
else expr
-let rec getAllExpressionArgs (expr: ISynExpr) =
+let rec getAllExpressionArgs (expr: IFSharpExpression) =
let mutable currentExpr = expr
seq {
while isNotNull currentExpr do
diff --git a/ReSharper.FSharp/src/FSharp.Psi/src/CodeFormatter/FSharpCodeFormatter.cs b/ReSharper.FSharp/src/FSharp.Psi/src/CodeFormatter/FSharpCodeFormatter.cs
index 07a7231e4a..e2a065010b 100644
--- a/ReSharper.FSharp/src/FSharp.Psi/src/CodeFormatter/FSharpCodeFormatter.cs
+++ b/ReSharper.FSharp/src/FSharp.Psi/src/CodeFormatter/FSharpCodeFormatter.cs
@@ -73,7 +73,7 @@ public override ITreeRange Format(ITreeNode firstElement, ITreeNode lastElement,
if (!firstElement.FSharpFormatterEnabled())
return new TreeRange(firstElement, lastElement);
- var formatterSettings = GetFormattingSettings(task.FirstElement, parameters);
+ var formatterSettings = GetFormattingSettings(task.FirstElement, parameters, myFormatterInfoProvider);
DoDeclarativeFormat(formatterSettings, myFormatterInfoProvider, null, new[] {task},
parameters, null, null, null, false);
diff --git a/ReSharper.FSharp/src/FSharp.Psi/src/CodeFormatter/FSharpCodeFormatterInfoProvider.cs b/ReSharper.FSharp/src/FSharp.Psi/src/CodeFormatter/FSharpCodeFormatterInfoProvider.cs
index 9de08498cf..6ae0c3b30a 100644
--- a/ReSharper.FSharp/src/FSharp.Psi/src/CodeFormatter/FSharpCodeFormatterInfoProvider.cs
+++ b/ReSharper.FSharp/src/FSharp.Psi/src/CodeFormatter/FSharpCodeFormatterInfoProvider.cs
@@ -1,9 +1,11 @@
using System.Linq;
using JetBrains.Application.Settings;
+using JetBrains.Application.Settings.Calculated.Interface;
+using JetBrains.Application.Threading;
+using JetBrains.Lifetimes;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Plugins.FSharp.Psi;
using JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree;
-using JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing;
using JetBrains.ReSharper.Plugins.FSharp.Psi.Tree;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.ExtensionsAPI.Tree;
@@ -16,8 +18,16 @@ namespace JetBrains.ReSharper.Plugins.FSharp.Services.Formatter
public class FSharpFormatterInfoProvider :
FormatterInfoProviderWithFluentApi
{
- public FSharpFormatterInfoProvider(ISettingsSchema settingsSchema) : base(settingsSchema)
+ public FSharpFormatterInfoProvider(ISettingsSchema settingsSchema,
+ ICalculatedSettingsSchema calculatedSettingsSchema, IThreading threading, Lifetime lifetime)
+ : base(settingsSchema, calculatedSettingsSchema, threading, lifetime)
{
+ }
+
+ protected override void Initialize()
+ {
+ base.Initialize();
+
var bindingAndModuleDeclIndentingRulesParameters = new[]
{
("NestedModuleDeclaration", ElementType.NESTED_MODULE_DECLARATION, NestedModuleDeclaration.MODULE_MEMBER),
@@ -29,7 +39,7 @@ public FSharpFormatterInfoProvider(ISettingsSchema settingsSchema) : base(settin
("NamedModuleDeclName", ElementType.NAMED_MODULE_DECLARATION, NamedModuleDeclaration.IDENTIFIER),
};
- var synExprIndentingRulesParameters = new[]
+ var fsExprIndentingRulesParameters = new[]
{
("ForExpr", ElementType.FOR_EXPR, ForExpr.DO_EXPR),
("ForEachExpr", ElementType.FOR_EACH_EXPR, ForEachExpr.DO_EXPR),
@@ -45,29 +55,45 @@ public FSharpFormatterInfoProvider(ISettingsSchema settingsSchema) : base(settin
("IfThenExpr", ElementType.IF_THEN_ELSE_EXPR, IfThenElseExpr.THEN_EXPR),
("ElifThenExpr", ElementType.ELIF_EXPR, ElifExpr.THEN_EXPR),
("LambdaExprBody", ElementType.LAMBDA_EXPR, LambdaExpr.EXPR),
+ ("MatchExpr_Expr", ElementType.MATCH_EXPR, MatchExpr.EXPR),
+ ("MatchExpr_With", ElementType.MATCH_EXPR, MatchExpr.WITH),
};
var typeDeclarationIndentingRulesParameters = new[]
{
- ("EnumDeclaration", ElementType.ENUM_DECLARATION, EnumDeclaration.ENUM_MEMBER),
+ ("EnumDeclaration", ElementType.ENUM_DECLARATION, EnumDeclaration.ENUM_REPR),
("UnionDeclarationCases", ElementType.UNION_DECLARATION, UnionDeclaration.UNION_REPR),
("TypeAbbreviation", ElementType.TYPE_ABBREVIATION_DECLARATION, TypeAbbreviationDeclaration.TYPE_OR_UNION_CASE),
("ModuleAbbreviation", ElementType.MODULE_ABBREVIATION, ModuleAbbreviation.TYPE_REFERENCE),
};
+ var alignmentRulesParameters = new[]
+ {
+ ("MatchClauses", ElementType.MATCH_EXPR),
+ ("UnionCases", ElementType.UNION_CASE_LIST),
+ ("UnionRepresentation", ElementType.UNION_REPRESENTATION),
+ ("EnumCases", ElementType.ENUM_REPRESENTATION),
+ ("SequentialExpr", ElementType.SEQUENTIAL_EXPR),
+ ("BinaryExpr", ElementType.BINARY_APP_EXPR),
+ };
+
lock (this)
{
bindingAndModuleDeclIndentingRulesParameters
- .Union(synExprIndentingRulesParameters)
+ .Union(fsExprIndentingRulesParameters)
.Union(typeDeclarationIndentingRulesParameters)
.ToList()
.ForEach(DescribeSimpleIndentingRule);
+ alignmentRulesParameters
+ .ToList()
+ .ForEach(DescribeSimpleAlignmentRule);
+
Describe()
.Name("TryWith_WithClauseIndent")
.Where(
Parent().HasType(ElementType.TRY_WITH_EXPR),
- Node().HasRole(TryWithExpr.CLAUSE))
+ Node().HasRole(TryWithExpr.MATCH_CLAUSE))
.Switch(
settings => settings.IndentOnTryWith,
When(true).Return(IndentType.External),
@@ -81,7 +107,7 @@ public FSharpFormatterInfoProvider(ISettingsSchema settingsSchema) : base(settin
Node()
.HasRole(PrefixAppExpr.ARG_EXPR)
.Satisfies((node, context) =>
- !(node is IComputationLikeExpr) ||
+ !(node is IComputationExpr) ||
!node.ContainsLineBreak(context.CodeFormatter)))
.Return(IndentType.External)
.Build();
@@ -126,6 +152,20 @@ public FSharpFormatterInfoProvider(ISettingsSchema settingsSchema) : base(settin
Node().HasRole(Do.CHAMELEON_EXPR))
.Return(IndentType.External)
.Build();
+
+ Describe()
+ .Name("UnionRepresentationCasesIndent")
+ .Where(
+ Parent()
+ .HasType(ElementType.UNION_REPRESENTATION)
+ .Satisfies((node, context) =>
+ {
+ var modifier = ((IUnionRepresentation) node).AccessModifier;
+ return modifier != null && modifier.HasNewLineAfter(context.CodeFormatter);
+ }),
+ Node().HasRole(UnionRepresentation.UNION_CASE_LIST))
+ .Return(IndentType.External)
+ .Build();
}
}
@@ -142,6 +182,15 @@ private void DescribeSimpleIndentingRule((string name, CompositeNodeType parentT
.Build();
}
+ private void DescribeSimpleAlignmentRule((string name, CompositeNodeType nodeType) parameters)
+ {
+ Describe()
+ .Name(parameters.name + "Alignment")
+ .Where(Node().HasType(parameters.nodeType))
+ .Return(IndentType.AlignThrough)
+ .Build();
+ }
+
private static bool IndentElseExpr(ITreeNode elseExpr, CodeFormattingContext context) =>
elseExpr.GetPreviousMeaningfulSibling().IsFirstOnLine(context.CodeFormatter) && !(elseExpr is IElifExpr);
diff --git a/ReSharper.FSharp/src/FSharp.Psi/src/FSharp.psi b/ReSharper.FSharp/src/FSharp.Psi/src/FSharp.psi
index 8a9f116bd5..e761637ca0 100644
--- a/ReSharper.FSharp/src/FSharp.Psi/src/FSharp.psi
+++ b/ReSharper.FSharp/src/FSharp.Psi/src/FSharp.psi
@@ -98,7 +98,7 @@ namedNamespaceDeclaration options { stubBase="FSharpDeclarationBase"; }:
REC?
(
referenceName
- DOT
+ DOT
)?
fSharpIdentifier
moduleMember*;
@@ -118,7 +118,7 @@ namedModuleDeclaration options { stubBase="FSharpTypeElementDeclarationBase"; }
accessModifier{ACCESS_MODIFIER, AccessModifier}?
(
referenceName
- DOT
+ DOT
)?
fSharpIdentifier
moduleMember*;
@@ -149,20 +149,10 @@ letModuleDecl options { stubBase="DummyDeclaration"; } extras {
REC?
LIST binding SEP AND;
-
-interface let:
- letBindings |
- letOrUseBangExpr;
-
interface letBindings:
letModuleDecl |
letOrUseExpr;
-interface letLikeExpr:
- letOrUseExpr |
- letOrUseBangExpr;
-
-
interface binding:
topBinding |
localBinding;
@@ -174,7 +164,7 @@ topBinding extras {
attributeList*
INLINE?
MUTABLE?
- synPat
+ fSharpPattern
returnTypeInfo?
EQUALS
chameleonExpression;
@@ -185,19 +175,19 @@ localBinding extras {
attributeList*
INLINE?
MUTABLE?
- synPat