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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions vsintegration/src/FSharp.Editor/Common/Constants.fs
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,7 @@ module internal Guids =
[<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"
3 changes: 3 additions & 0 deletions vsintegration/src/FSharp.Editor/FSharp.Editor.resx
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@
<data name="6010" xml:space="preserve">
<value>Code Fixes</value>
</data>
<data name="6011" xml:space="preserve">
<value>Performance</value>
</data>
<data name="TheValueIsUnused" xml:space="preserve">
<value>The value is unused</value>
</data>
Expand Down
15 changes: 10 additions & 5 deletions vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ open Microsoft.CodeAnalysis.Completion
open Microsoft.CodeAnalysis.Options
open Microsoft.VisualStudio
open Microsoft.VisualStudio.Editor
open Microsoft.VisualStudio.Text
open Microsoft.VisualStudio.TextManager.Interop
open Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService
open Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
Expand All @@ -46,7 +45,12 @@ type internal FSharpCheckerProvider

let checker =
lazy
let checker = FSharpChecker.Create(projectCacheSize = 200, keepAllBackgroundResolutions = false (* , MaxMemory = 2300 *), legacyReferenceResolver=Microsoft.FSharp.Compiler.MSBuildReferenceResolver.Resolver)
let checker =
FSharpChecker.Create(
projectCacheSize = Settings.LanguageServicePerformance.ProjectCheckCacheSize,
keepAllBackgroundResolutions = false,
(* , MaxMemory = 2300 *)
legacyReferenceResolver=Microsoft.FSharp.Compiler.MSBuildReferenceResolver.Resolver)

// This is one half of the bridge between the F# background builder and the Roslyn analysis engine.
// When the F# background builder refreshes the background semantic build context for a file,
Expand Down Expand Up @@ -126,18 +130,18 @@ type internal ProjectInfoManager
// compiled and #r will refer to files on disk
let referencedProjectFileNames = [| |]
let site = ProjectSitesAndFiles.CreateProjectSiteForScript(fileName, referencedProjectFileNames, options)
return ProjectSitesAndFiles.GetProjectOptionsForProjectSite(tryGetOptionsForReferencedProject,site,fileName,options.ExtraProjectInfo,serviceProvider, true)
return ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject,site,fileName,options.ExtraProjectInfo,serviceProvider, true)
else
let site = ProjectSitesAndFiles.ProjectSiteOfSingleFile(fileName)
return ProjectSitesAndFiles.GetProjectOptionsForProjectSite(tryGetOptionsForReferencedProject,site,fileName,extraProjectInfo,serviceProvider, true)
return ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject,site,fileName,extraProjectInfo,serviceProvider, true)
}

/// Update the info for a project in the project table
member this.UpdateProjectInfo(tryGetOrCreateProjectId, projectId: ProjectId, site: IProjectSite, workspace: Workspace, userOpName) =
this.AddOrUpdateProject(projectId, (fun isRefresh ->
let extraProjectInfo = Some(box workspace)
let tryGetOptionsForReferencedProject f = f |> tryGetOrCreateProjectId |> Option.bind this.TryGetOptionsForProject
let referencedProjects, options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(tryGetOptionsForReferencedProject, site, site.ProjectFileName(), extraProjectInfo, serviceProvider, true)
let referencedProjects, options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, site.ProjectFileName(), extraProjectInfo, serviceProvider, true)
let referencedProjectIds = referencedProjects |> Array.choose tryGetOrCreateProjectId
checkerProvider.Checker.InvalidateConfiguration(options, startBackgroundCompileIfAlreadySeen = not isRefresh, userOpName= userOpName + ".UpdateProjectInfo")
referencedProjectIds, options))
Expand Down Expand Up @@ -231,6 +235,7 @@ type
[<ProvideLanguageEditorOptionPage(typeof<OptionsUI.IntelliSenseOptionPage>, "F#", null, "IntelliSense", "6008")>]
[<ProvideLanguageEditorOptionPage(typeof<OptionsUI.QuickInfoOptionPage>, "F#", null, "QuickInfo", "6009")>]
[<ProvideLanguageEditorOptionPage(typeof<OptionsUI.CodeFixesOptionPage>, "F#", null, "Code Fixes", "6010")>]
[<ProvideLanguageEditorOptionPage(typeof<OptionsUI.LanguageServicePerformanceOptionPage>, "F#", null, "Performance", "6011")>]
[<ProvideLanguageService(languageService = typeof<FSharpLanguageService>,
strLanguageName = FSharpConstants.FSharpLanguageName,
languageResourceID = 100,
Expand Down
16 changes: 16 additions & 0 deletions vsintegration/src/FSharp.Editor/Options/EditorOptions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ type CodeFixesOptions =
AlwaysPlaceOpensAtTopLevel: bool
UnusedOpens: bool }

[<CLIMutable>]
type LanguageServicePerformanceOptions =
{ EnableInMemoryCrossProjectReferences: bool
ProjectCheckCacheSize: int }

[<Export(typeof<ISettings>)>]
type internal Settings [<ImportingConstructor>](store: SettingsStore) =
do // Initialize default settings
Expand All @@ -56,11 +61,16 @@ type internal Settings [<ImportingConstructor>](store: SettingsStore) =
AlwaysPlaceOpensAtTopLevel = false
UnusedOpens = true }

store.RegisterDefault
{ EnableInMemoryCrossProjectReferences = true
ProjectCheckCacheSize = 200 }

interface ISettings

static member IntelliSense : IntelliSenseOptions = getSettings()
static member QuickInfo : QuickInfoOptions = getSettings()
static member CodeFixes : CodeFixesOptions = getSettings()
static member LanguageServicePerformance : LanguageServicePerformanceOptions = getSettings()

module internal OptionsUI =

Expand Down Expand Up @@ -89,3 +99,9 @@ module internal OptionsUI =
inherit AbstractOptionPage<CodeFixesOptions>()
override this.CreateView() =
upcast CodeFixesOptionControl()

[<Guid(Guids.languageServicePerformanceOptionPageIdString)>]
type internal LanguageServicePerformanceOptionPage() =
inherit AbstractOptionPage<LanguageServicePerformanceOptions>()
override this.CreateView() =
upcast LanguageServicePerformanceOptionControl()
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ type internal FSharpLanguageServiceBackgroundRequests
// This portion is executed on the UI thread.
let rdt = getServiceProvider().RunningDocumentTable
let projectSite = getProjectSitesAndFiles().FindOwningProject(rdt,fileName)
let _, checkOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite((fun _ -> None), projectSite, fileName, None, getServiceProvider(), false)
let enableInMemoryCrossProjectReferences = true
let _, checkOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, (fun _ -> None), projectSite, fileName, None, getServiceProvider(), false)
let projectFileName = projectSite.ProjectFileName()
let data =
{ ProjectSite = projectSite
Expand Down
16 changes: 9 additions & 7 deletions vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ type internal ProjectSitesAndFiles() =
| None -> ()
}

static let rec referencedProjectsOf (tryGetOptionsForReferencedProject, projectSite:IProjectSite, extraProjectInfo, serviceProvider:System.IServiceProvider, useUniqueStamp) =
static let rec referencedProjectsOf (enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite:IProjectSite, extraProjectInfo, serviceProvider:System.IServiceProvider, useUniqueStamp) =
[| for (p,ps) in referencedProvideProjectSites (projectSite, serviceProvider) do
match fullOutputAssemblyPath p with
| None -> ()
Expand All @@ -132,14 +132,16 @@ type internal ProjectSitesAndFiles() =
// Lookup may not succeed if the project has not been established yet
// In this case we go and compute the options recursively.
match tryGetOptionsForReferencedProject p.FileName with
| None -> getProjectOptionsForProjectSite (tryGetOptionsForReferencedProject, ps.GetProjectSite(), p.FileName, extraProjectInfo, serviceProvider, useUniqueStamp) |> snd
| None -> getProjectOptionsForProjectSite (enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, ps.GetProjectSite(), p.FileName, extraProjectInfo, serviceProvider, useUniqueStamp) |> snd
| Some options -> options
yield (p.FileName, (path, referencedProjectOptions)) |]

and getProjectOptionsForProjectSite(tryGetOptionsForReferencedProject, projectSite:IProjectSite, fileName, extraProjectInfo, serviceProvider, useUniqueStamp) =
and getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite:IProjectSite, fileName, extraProjectInfo, serviceProvider, useUniqueStamp) =
let referencedProjectFileNames, referencedProjectOptions =
referencedProjectsOf(tryGetOptionsForReferencedProject, projectSite, extraProjectInfo, serviceProvider, useUniqueStamp)
|> Array.unzip
if enableInMemoryCrossProjectReferences then
referencedProjectsOf(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, extraProjectInfo, serviceProvider, useUniqueStamp)
|> Array.unzip
else [| |], [| |]

let options =
{ProjectFileName = projectSite.ProjectFileName()
Expand Down Expand Up @@ -238,11 +240,11 @@ type internal ProjectSitesAndFiles() =
|> Seq.toArray

/// Create project options for this project site.
static member GetProjectOptionsForProjectSite(tryGetOptionsForReferencedProject, projectSite:IProjectSite,filename,extraProjectInfo,serviceProvider:System.IServiceProvider, useUniqueStamp) =
static member GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite:IProjectSite,filename,extraProjectInfo,serviceProvider:System.IServiceProvider, useUniqueStamp) =
match projectSite with
| :? IHaveCheckOptions as hco -> hco.OriginalCheckOptions()
| _ ->
getProjectOptionsForProjectSite(tryGetOptionsForReferencedProject, projectSite, filename, extraProjectInfo, serviceProvider, useUniqueStamp)
getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, filename, extraProjectInfo, serviceProvider, useUniqueStamp)

/// Create project site for these project options
static member CreateProjectSiteForScript (filename, referencedProjectFileNames, checkOptions) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
<Compile Include="CodeFixesOptionControl.xaml.cs">
<DependentUpon>CodeFixesOptionControl.xaml</DependentUpon>
</Compile>
<Compile Include="IntergerCheckValidationRule.cs" />
<Compile Include="LanguageServicePerformanceOptionControl.xaml.cs">
<DependentUpon>LanguageServicePerformanceOptionControl.xaml</DependentUpon>
</Compile>
<Compile Include="IntelliSenseOptionControl.xaml.cs">
<DependentUpon>IntelliSenseOptionControl.xaml</DependentUpon>
</Compile>
Expand All @@ -78,6 +82,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="LanguageServicePerformanceOptionControl.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="IntelliSenseOptionControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand All @@ -95,6 +103,7 @@
<EmbeddedResource Include="Strings.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Strings.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Expand Down
54 changes: 27 additions & 27 deletions vsintegration/src/FSharp.UIResources/IntelliSenseOptionControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,34 @@
x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Microsoft.VisualStudio.FSharp.UIResources"
mc:Ignorable="d"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="OptionPageStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel>
<GroupBox Header="{x:Static local:Strings.Completion_Lists}">
<StackPanel>
<CheckBox x:Name="charTyped" IsChecked="{Binding ShowAfterCharIsTyped}"
Content="{x:Static local:Strings.Show_completion_list_after_a_character_is_typed}"/>
<StackPanel Margin="15 0 0 0">
<CheckBox x:Name="charDeleted" IsEnabled="{Binding IsChecked, ElementName=charTyped}" IsChecked="{Binding ShowAfterCharIsDeleted}"
Content="{x:Static local:Strings.Show_completion_list_after_a_character_is_deleted}"/>
</StackPanel>
<CheckBox x:Name="showAllSymbols" IsChecked="{Binding ShowAllSymbols}"
Content="{x:Static local:Strings.Show_all_symbols}"/>
</StackPanel>
</GroupBox>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="OptionPageStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel>
<GroupBox Header="{x:Static local:Strings.Completion_Lists}">
<StackPanel>
<CheckBox x:Name="charTyped" IsChecked="{Binding ShowAfterCharIsTyped}"
Content="{x:Static local:Strings.Show_completion_list_after_a_character_is_typed}"/>
<StackPanel Margin="15 0 0 0">
<CheckBox x:Name="charDeleted" IsEnabled="{Binding IsChecked, ElementName=charTyped}" IsChecked="{Binding ShowAfterCharIsDeleted}"
Content="{x:Static local:Strings.Show_completion_list_after_a_character_is_deleted}"/>
</StackPanel>
</ScrollViewer>
</Grid>
<CheckBox x:Name="showAllSymbols" IsChecked="{Binding ShowAllSymbols}"
Content="{x:Static local:Strings.Show_all_symbols}"/>
</StackPanel>
</GroupBox>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Globalization;
using System.Windows.Controls;

namespace Microsoft.VisualStudio.FSharp.UIResources
{

public class IntegerRangeValidationRule : ValidationRule
{
public IntegerRangeValidationRule()
: base(ValidationStep.RawProposedValue, true)
{
}

public int Min { get; set; }

public int Max { get; set; }

public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if (value is string text)
{
if (int.TryParse(text, out int i) &&
i >= Min && i <= Max)
{
return ValidationResult.ValidResult;
}
}

return new ValidationResult(false, $"Expected a number between {Min} and {Max}");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<UserControl x:Class="Microsoft.VisualStudio.FSharp.UIResources.LanguageServicePerformanceOptionControl"
x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Microsoft.VisualStudio.FSharp.UIResources"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="OptionPageStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel>
<GroupBox Header="{x:Static local:Strings.Language_Service_Performance}">
<StackPanel>
<CheckBox x:Name="enableInMemoryCrossProjectReferences" IsChecked="{Binding EnableInMemoryCrossProjectReferences}"
Content="{x:Static local:Strings.Enable_in_memory_cross_project_references}"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="70" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" x:Name="projectCheckCacheSizeLabel" Content="{x:Static local:Strings.Project_check_cache_size}"/>
<TextBox Grid.Column="1"
HorizontalContentAlignment="Right"
VerticalContentAlignment="Center">
<TextBox.Text>
<Binding Path="ProjectCheckCacheSize">
<Binding.ValidationRules>
<local:IntegerRangeValidationRule Min="1" Max="1000" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid>
</StackPanel>
</GroupBox>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>
Loading