Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/release-notes/.VisualStudio/18.vNext.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
* Add maintainer-requested F# Apex Visual Studio integration tests on DartLab-1ES CloudTest, using PR pipeline definitions pinned to an explicitly requested commit SHA. ([PR #20625](https://github.com/dotnet/fsharp/pull/20625))
* Code-fixes for FS3888 (compiler-semantic attribute on the `.fs` but not the `.fsi`): copy the attribute into the `.fsi`, or remove it from the `.fs`. ([Issue #19560](https://github.com/dotnet/fsharp/issues/19560), [PR #19880](https://github.com/dotnet/fsharp/pull/19880))
* Expand `<inheritdoc/>` in IDE tooltips, completion, and signature help, inheriting XML documentation from base classes, interfaces, overridden members, and constructors. ([Issue #19175](https://github.com/dotnet/fsharp/issues/19175), [PR #19188](https://github.com/dotnet/fsharp/pull/19188))
* Added a **Tools > Options > F# Tools > Compiler** option, **"Use the .NET SDK F# compiler for builds"**, on by default. Visual Studio uses the .NET SDK F# compiler when the project supplies SDK paths, matching `dotnet build`. Otherwise, it uses the bundled .NET Framework compiler. Turn the option off to use the bundled compiler for all projects. Changes are saved on Apply or OK; Cancel discards unsaved changes. Command-line builds are unaffected. ([Issue #20484](https://github.com/dotnet/fsharp/issues/20484), [PR #20485](https://github.com/dotnet/fsharp/pull/20485))
* Move F# editor and Interactive options to 43 native Unified Settings with independent roaming and a one-time import of existing settings. Preserve the legacy groupings and Interactive setting order, with restart requirements displayed by Unified Settings. Quick Info's preferred description width is a checkbox with a dependent integer control. Remove the eight legacy options pages; the user-wide compiler setting remains external. Typing and deletion completion triggers are independent. ([PR #20877](https://github.com/dotnet/fsharp/pull/20877))
* Added a **Compiler** option in F# Unified Settings, **"Use the .NET SDK F# compiler for builds"**, on by default. Visual Studio uses the .NET SDK F# compiler when the project supplies SDK paths, matching `dotnet build`. Otherwise, it uses the bundled .NET Framework compiler. Turn the option off to use the bundled compiler for all projects. Command-line builds are unaffected. ([Issue #20484](https://github.com/dotnet/fsharp/issues/20484), [PR #20485](https://github.com/dotnet/fsharp/pull/20485))
* F# types, modules, members and values now appear in the GitHub Copilot Chat `#` mention picker, and attach their declaration source as context. ([PR #20409](https://github.com/dotnet/fsharp/pull/20409))

### Fixed
Expand Down Expand Up @@ -39,3 +40,4 @@
* The VS project options reactor keeps single-file and script project options in a named record instead of a five-place tuple, and its text-view subscription plumbing uses `voption` instead of `option`. ([PR #20455](https://github.com/dotnet/fsharp/pull/20455))
* The Debug build no longer exports OpenTelemetry unless `FSHARP_OTEL_EXPORT` asks it to (the variable can also carry the collector endpoint), so the default `VisualFSharpDebug` launch profile no longer stalls or retries against a missing collector; the new `OTEL Export` profile turns it back on. ([PR #20468](https://github.com/dotnet/fsharp/pull/20468))
* `FSharpFindUsagesService.onSymbolFound` looks up a reference's definition item with `voption` instead of `option`. No functional change. ([PR #20534](https://github.com/dotnet/fsharp/pull/20534))
* F# options now read Unified Settings directly. A one-time import uses one local completion flag and is skipped when any native F# setting has already been saved. The old editor JSON and Interactive properties are retained but no longer updated. Interactive settings now roam. Legacy options-page automation and page-based settings import/export are removed. ([PR #20877](https://github.com/dotnet/fsharp/pull/20877))
1 change: 1 addition & 0 deletions eng/Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
<PackageVersion Include="Microsoft.VisualStudio.Shell.Immutable.11.0" Version="11.0.50727" />
<PackageVersion Include="Microsoft.VisualStudio.Shell.Immutable.15.0" Version="15.0.25123-Dev15Preview" />
<PackageVersion Include="Microsoft.VisualStudio.Shell.Interop" Version="18.9.438" />
<PackageVersion Include="Microsoft.VisualStudio.Settings.Manifest.Build" Version="18.13.785" />
<!-- Shell.15.0 references SolutionPersistence at runtime without declaring the NuGet dependency (it is expected
from the VS install). The standalone VS unit-test host loads Shell.15.0 into a MEF catalog, so the assembly
must be deployed next to it or Assembly.GetTypes throws and every legacy VS unit test fails. -->
Expand Down
28 changes: 0 additions & 28 deletions vsintegration/src/FSharp.Editor/Common/Constants.fs
Original file line number Diff line number Diff line change
Expand Up @@ -69,34 +69,6 @@ module internal FSharpProviderConstants =
[<RequireQualifiedAccess>]
module internal Guids =

/// "9B164E40-C3A2-4363-9BC5-EB4039DEF653"
let svsSettingsPersistenceManagerId = Guid "{9B164E40-C3A2-4363-9BC5-EB4039DEF653}"

[<Literal>]
/// "9b3c6b8a-754a-461d-9ebe-de1a682d57c1"
let intelliSenseOptionPageIdString = "9b3c6b8a-754a-461d-9ebe-de1a682d57c1"

[<Literal>]
/// "1e2b3290-4d67-41ff-a876-6f41f868e28f"
let quickInfoOptionPageIdString = "1e2b3290-4d67-41ff-a876-6f41f868e28f"

[<Literal>]
/// "9A66EB6A-DE52-4169-BC26-36FBD4312FD7"
let codeFixesOptionPageIdString = "9A66EB6A-DE52-4169-BC26-36FBD4312FD7"

[<Literal>]
/// "8FDA964A-263D-4B4E-9560-29897535217C"
let languageServicePerformanceOptionPageIdString =
"8FDA964A-263D-4B4E-9560-29897535217C"

[<Literal>]
/// "9007718C-357A-4327-A193-AB3EC38D7EE8"
let advancedSettingsPageIdString = "9007718C-357A-4327-A193-AB3EC38D7EE8"

[<Literal>]
/// "9EBEBCE8-A79B-46B0-A8C5-A9818AEED17D"
let formattingOptionPageIdString = "9EBEBCE8-A79B-46B0-A8C5-A9818AEED17D"

let blueHighContrastThemeId = Guid "{ce94d289-8481-498b-8ca9-9b6191a315b9}"

[<RequireQualifiedAccess>]
Expand Down
10 changes: 8 additions & 2 deletions vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
<Compile Include="Common\FSharpCodeAnalysisExtensions.fs" />
<Compile Include="Common\CodeAnalysisExtensions.fs" />
<Compile Include="Common\Vs.fs" />
<Compile Include="Options\SettingsStore.fs" />
<Compile Include="Options\UIHelpers.fs" />
<Compile Include="Options\UnifiedSettings.fs" />
<Compile Include="Options\EditorOptions.fs" />
<Compile Include="Options\UnifiedSettingsMigration.fs" />
<Compile Include="Telemetry\TelemetryReporter.fs" />
<Compile Include="LanguageService\ProvideBraceCompletionAttribute.fs" />
<Compile Include="LanguageService\FSharpEditorFactory.fs" />
Expand Down Expand Up @@ -187,9 +187,15 @@
<PackageReference Include="Microsoft.VisualStudio.LanguageServices.ExternalAccess" PrivateAssets="all" ExcludeAssets="runtime;contentFiles;build;analyzers;native" />
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem" PrivateAssets="all" ExcludeAssets="runtime;contentFiles;build;analyzers;native" />
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.Managed" PrivateAssets="all" ExcludeAssets="runtime;contentFiles;build;analyzers;native" />
<PackageReference Include="Microsoft.VisualStudio.Settings.Manifest.Build" PrivateAssets="all" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Condition="'$(Configuration)' == 'Debug'" />
</ItemGroup>

<ItemGroup>
<VsSettingsManifest Include="Options\fsharpSettings.registration.json" Validate="true" IncludeInVSIX="false" />
<Content Include="Options\fsharpSettings.registration.json" Link="fsharpSettings.registration.json" CopyToOutputDirectory="PreserveNewest" IncludeInVSIX="true" />
</ItemGroup>

<ItemGroup>
<AssemblyAttribute Include="Microsoft.VisualStudio.Shell.ProvideCodeBaseAttribute">
<AssemblyName>FSharp.Editor</AssemblyName>
Expand Down
72 changes: 71 additions & 1 deletion vsintegration/src/FSharp.Editor/FSharp.Editor.resx
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,74 @@ Use live (unsaved) buffers for analysis</value>
{2}</value>
<comment>Tooltip of an F# declaration in the Copilot Chat "#" picker, as Copilot shows a C# one. {0} is the kind of declaration (Class, Method, Field...), {1} the file name, {2} the declaration's name.</comment>
</data>
</root>
<data name="UnifiedSettingsIntelliSenseTitle" xml:space="preserve">
<value>IntelliSense</value>
</data>
<data name="UnifiedSettingsQuickInfoTitle" xml:space="preserve">
<value>Quick Info</value>
</data>
<data name="UnifiedSettingsAdvancedTitle" xml:space="preserve">
<value>Advanced</value>
</data>
<data name="UnifiedSettingsInteractiveTitle" xml:space="preserve">
<value>F# Interactive</value>
</data>
<data name="UnifiedSettingsBackingStoreDescription" xml:space="preserve">
<value>This compiler setting uses the user-wide F# compiler configuration.</value>
<comment>Description of the storage for the F# compiler option in Unified Settings. User-wide means shared by Visual Studio instances for the same Windows user.</comment>
</data>
<data name="UnifiedSettingsCompilerUseNetSdkTitle" xml:space="preserve">
<value>Use the .NET SDK F# compiler for builds</value>
</data>
<data name="UnifiedSettingsCompilerUseNetSdkDescription" xml:space="preserve">
<value>When enabled (the default), Visual Studio builds F# projects with the compiler from the installed .NET SDK, matching command-line 'dotnet build'. Turn it off to build with the .NET Framework F# compiler bundled with Visual Studio - for example when a project uses a type provider that ships only a .NET Framework build. Command-line builds are unaffected. Changing this takes effect on the next (re)build.</value>
</data>
<data name="UnifiedSettingsShowCompletionAfterTypingTitle" xml:space="preserve">
<value>Show completion list after a character is typed</value>
</data>
<data name="UnifiedSettingsShowCompletionAfterDeletionTitle" xml:space="preserve">
<value>Show completion list after a character is deleted</value>
</data>
<data name="UnifiedSettingsShowUnopenedSymbolsTitle" xml:space="preserve">
<value>Show symbols in unopened namespaces</value>
</data>
<data name="UnifiedSettingsInMemoryCrossProjectReferencesTitle" xml:space="preserve">
<value>Enable in-memory cross project references</value>
</data>
<data name="UnifiedSettingsShowNavigationLinksTitle" xml:space="preserve">
<value>Show navigation links</value>
</data>
<data name="UnifiedSettingsUnderlineStyleTitle" xml:space="preserve">
<value>Navigation link underline style</value>
</data>
<data name="UnifiedSettingsDotUnderlineLabel" xml:space="preserve">
<value>Dot underline</value>
</data>
<data name="UnifiedSettingsDashUnderlineLabel" xml:space="preserve">
<value>Dash underline</value>
</data>
<data name="UnifiedSettingsSolidUnderlineLabel" xml:space="preserve">
<value>Solid underline</value>
</data>
<data name="UnifiedSettingsDescriptionWidthTitle" xml:space="preserve">
<value>Use a preferred description width</value>
</data>
<data name="UnifiedSettingsDescriptionWidthDescription" xml:space="preserve">
<value>Format signatures to the preferred width by adding line breaks conforming with F# syntax rules.</value>
</data>
<data name="UnifiedSettingsMigrationDescription" xml:space="preserve">
<value>Import existing F# settings</value>
</data>
<data name="UnifiedSettingsCacheFactorDescription" xml:space="preserve">
<value>Enter an integer from 1 to 10000. Higher numbers use more memory for caching. Changing the value wipes the cache.</value>
</data>
<data name="UnifiedSettingsStaleCompletionDescription" xml:space="preserve">
<value>Enter an integer from 0 to 10000 milliseconds before stale results are used.</value>
</data>
<data name="UnifiedSettingsTransparentCompilerDescription" xml:space="preserve">
<value>WARNING! Transparent Compiler does not yet support all features and can cause crashes or give incorrect results. Use at your own risk! Enabling this also opts in to additional performance telemetry.</value>
</data>
<data name="UnifiedSettingsOperationFailed" xml:space="preserve">
<value>Unable to read or update the F# setting. See the Activity Log for details.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,8 @@ type internal FSharpSettingsFactory [<Composition.ImportingConstructor>] (settin
member _.CreateService(_) = upcast settings

[<Guid(FSharpConstants.packageGuidString)>]
[<ProvideOptionPage(typeof<FSharp.Interactive.FsiPropertyPage>, "F# Tools", "F# Interactive", 6000s, 6001s, true)>] // true = supports automation
[<ProvideOptionPage(typeof<FSharp.Interactive.FSharpCompilerPropertyPage>, "F# Tools", "Compiler", 6000s, 6015s, true)>]

[<ProvideSettingsManifest(PackageRelativeManifestFile = "fsharpSettings.registration.json")>]
[<ProvideService(typeof<FSharpSettingsProvider>, IsAsyncQueryable = true)>]
[<ProvideKeyBindingTable("{dee22b65-9761-4a26-8fb2-759b971d6dfc}", 6001s)>] // <-- resource ID for localised name

[<ProvideToolWindow(typeof<FSharp.Interactive.FsiToolWindow>,
Expand All @@ -276,17 +275,6 @@ type internal FSharpSettingsFactory [<Composition.ImportingConstructor>] (settin
Window = "34E76E81-EE4A-11D0-AE2E-00A0C90FFFC3")
// The following should place the ToolWindow with the OutputWindow by default.
>]
[<ProvideLanguageEditorOptionPage(typeof<OptionsUI.IntelliSenseOptionPage>, "F#", null, "IntelliSense", "6008", "IntelliSensePageKeywords")>]
[<ProvideLanguageEditorOptionPage(typeof<OptionsUI.QuickInfoOptionPage>, "F#", null, "QuickInfo", "6009", "QuickInfoPageKeywords")>]
[<ProvideLanguageEditorOptionPage(typeof<OptionsUI.CodeFixesOptionPage>, "F#", null, "Code Fixes", "6010", "CodeFixesPageKeywords")>]
[<ProvideLanguageEditorOptionPage(typeof<OptionsUI.LanguageServicePerformanceOptionPage>,
"F#",
null,
"Performance",
"6011",
"PerformancePageKeywords")>]
[<ProvideLanguageEditorOptionPage(typeof<OptionsUI.AdvancedSettingsOptionPage>, "F#", null, "Advanced", "6012", "AdvancedPageKeywords")>]
[<ProvideLanguageEditorOptionPage(typeof<OptionsUI.FormattingOptionPage>, "F#", null, "Formatting", "6014", "FormattingPageKeywords")>]
[<ProvideFSharpVersionRegistration(FSharpConstants.projectPackageGuidString, "Microsoft Visual F#")>]
// 64 represents a hex number. It needs to be greater than 37 so the TextMate editor will not be chosen as higher priority.
[<ProvideEditorExtension(typeof<FSharpEditorFactory>, ".fs", 64)>]
Expand Down Expand Up @@ -329,18 +317,71 @@ type internal FSharpPackage() as this =

let mutable solutionEventsOpt = None

let mutable settingsLifetime = None

let initializeSettings =
lazy
(task {
let! native = this.GetServiceAsync(typeof<Microsoft.Internal.VisualStudio.Shell.Interop.SVsUnifiedSettingsManager>)

let native =
native :?> Microsoft.VisualStudio.Utilities.UnifiedSettings.ISettingsManager

let! legacy = this.GetServiceAsync(typeof<Microsoft.Internal.VisualStudio.Shell.Interop.SVsSettingsPersistenceManager>)
let! metadata = this.GetServiceAsync(typeof<Microsoft.Internal.VisualStudio.Shell.Interop.SVsUnifiedSettingsMetadata>)

let! migration =
UnifiedSettingsMigration.startAsync
native
(legacy :?> Microsoft.VisualStudio.Settings.ISettingsManager5)
(metadata :?> Microsoft.Internal.VisualStudio.Services.UnifiedSettings.IUnifiedSettingsMetadata)
this.DisposalToken

try
let interactive = UnifiedSettings.subscribeToInteractive (native.GetReader())

settingsLifetime <-
Some
{ new IDisposable with
member _.Dispose() =
interactive.Dispose()
migration.Dispose()
}
with error ->
migration.Dispose()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(error).Throw()
})

// FSI-LINKAGE-POINT: unsited init
do FSharp.Interactive.Hooks.fsiConsoleWindowPackageCtorUnsited (this :> Package)

do
this.AddService(
typeof<FSharpSettingsProvider>,
AsyncServiceCreatorCallback(fun _ cancellationToken _ ->
cancellationToken.ThrowIfCancellationRequested()

Task.FromResult<obj>(
new FSharpSettingsProvider(
(fun () -> FSharp.Interactive.FSharpCompilerSettings.UseNetSdkCompiler),
(fun value -> FSharp.Interactive.FSharpCompilerSettings.UseNetSdkCompiler <- value),
(fun error -> ActivityLog.LogError("F# Unified Settings", error.ToString()))
)
)),
true
)

#if DEBUG
let flushTelemetry = DebugHelpers.FSharpServiceTelemetry.otelExport ()
#endif

override this.Dispose(disposing: bool) =
base.Dispose(disposing: bool)

if disposing then
settingsLifetime |> Option.iter _.Dispose()
#if DEBUG
flushTelemetry ()
#endif
base.Dispose(disposing: bool)

override this.RegisterInitializeAsyncWork(packageRegistrationTasks: PackageLoadTasks) : unit =
base.RegisterInitializeAsyncWork(packageRegistrationTasks)
Expand All @@ -349,14 +390,12 @@ type internal FSharpPackage() as this =
true,
(fun _tasks cancellationToken ->
foregroundCancellableTask {
do! initializeSettings.Value
let exportProvider = this.ComponentModel.DefaultExportProvider

let theme = exportProvider.GetExport<ISetThemeColors>().Value
theme.SetColors()

// FSI-LINKAGE-POINT: private method GetDialogPage forces fsi options to be loaded
this.GetDialogPage(typeof<FSharp.Interactive.FsiPropertyPage>) |> ignore

let! commandService = this.GetServiceAsync(typeof<IMenuCommandService>)
let commandService = commandService :?> OleMenuCommandService

Expand All @@ -370,6 +409,7 @@ type internal FSharpPackage() as this =
false,
(fun _tasks cancellationToken ->
cancellableTask {
do! initializeSettings.Value
let exportProvider = this.ComponentModel.DefaultExportProvider

let workspace = exportProvider.GetExportedValue<VisualStudioWorkspace>()
Expand Down
Loading
Loading