From c6e2b7f4f6d1de11425a96b3c6f7c7790ed7b29d Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Wed, 19 Apr 2023 21:02:18 +0200 Subject: [PATCH 1/7] Make in-memory cross-project references the only option (by removing the switch) (#15116) * Make in-memory cross-project references the only option (by removing the switch) * Cleanup translations * Automated command ran: fantomas Co-authored-by: vzarytovskii <1260985+vzarytovskii@users.noreply.github.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Kevin Ransom (msft) --- .../FSharpProjectOptionsManager.fs | 37 ++++++++----------- .../LanguageService/LanguageService.fs | 4 -- .../FSharp.Editor/Options/EditorOptions.fs | 5 --- ...nguageServicePerformanceOptionControl.xaml | 4 -- .../FSharp.UIResources/Strings.Designer.cs | 18 --------- .../src/FSharp.UIResources/Strings.resx | 6 --- .../src/FSharp.UIResources/xlf/Strings.cs.xlf | 10 ----- .../src/FSharp.UIResources/xlf/Strings.de.xlf | 10 ----- .../src/FSharp.UIResources/xlf/Strings.es.xlf | 10 ----- .../src/FSharp.UIResources/xlf/Strings.fr.xlf | 10 ----- .../src/FSharp.UIResources/xlf/Strings.it.xlf | 10 ----- .../src/FSharp.UIResources/xlf/Strings.ja.xlf | 10 ----- .../src/FSharp.UIResources/xlf/Strings.ko.xlf | 10 ----- .../src/FSharp.UIResources/xlf/Strings.pl.xlf | 10 ----- .../FSharp.UIResources/xlf/Strings.pt-BR.xlf | 10 ----- .../src/FSharp.UIResources/xlf/Strings.ru.xlf | 10 ----- .../src/FSharp.UIResources/xlf/Strings.tr.xlf | 10 ----- .../xlf/Strings.zh-Hans.xlf | 10 ----- .../xlf/Strings.zh-Hant.xlf | 10 ----- 19 files changed, 15 insertions(+), 189 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs index a5b6f2a44c2..0cf3c14676b 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs @@ -85,13 +85,9 @@ module private FSharpProjectOptionsHelpers = let v2 = p2.GetDependentVersionAsync(ct).Result v1 <> v2)) - let isProjectInvalidated (oldProject: Project) (newProject: Project) ct = - let hasProjectVersionChanged = hasProjectVersionChanged oldProject newProject - - if newProject.AreFSharpInMemoryCrossProjectReferencesEnabled then - hasProjectVersionChanged || hasDependentVersionChanged oldProject newProject ct - else - hasProjectVersionChanged + let inline isProjectInvalidated (oldProject: Project) (newProject: Project) ct = + hasProjectVersionChanged oldProject newProject + || hasDependentVersionChanged oldProject newProject ct [] type private FSharpProjectOptionsMessage = @@ -276,21 +272,18 @@ type private FSharpProjectOptionsReactor(checker: FSharpChecker) = let referencedProjects = ResizeArray() - if project.AreFSharpInMemoryCrossProjectReferencesEnabled then - for projectReference in project.ProjectReferences do - let referencedProject = project.Solution.GetProject(projectReference.ProjectId) - - if referencedProject.Language = FSharpConstants.FSharpLanguageName then - match! tryComputeOptions referencedProject ct with - | None -> canBail <- true - | Some (_, projectOptions) -> - referencedProjects.Add( - FSharpReferencedProject.CreateFSharp(referencedProject.OutputFilePath, projectOptions) - ) - elif referencedProject.SupportsCompilation then - let! comp = referencedProject.GetCompilationAsync(ct) |> Async.AwaitTask - let peRef = createPEReference referencedProject comp - referencedProjects.Add(peRef) + for projectReference in project.ProjectReferences do + let referencedProject = project.Solution.GetProject(projectReference.ProjectId) + + if referencedProject.Language = FSharpConstants.FSharpLanguageName then + match! tryComputeOptions referencedProject ct with + | None -> canBail <- true + | Some (_, projectOptions) -> + referencedProjects.Add(FSharpReferencedProject.CreateFSharp(referencedProject.OutputFilePath, projectOptions)) + elif referencedProject.SupportsCompilation then + let! comp = referencedProject.GetCompilationAsync(ct) |> Async.AwaitTask + let peRef = createPEReference referencedProject comp + referencedProjects.Add(peRef) if canBail then return None diff --git a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs index 6f63b565f0e..be378e972e8 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs @@ -126,9 +126,6 @@ type internal FSharpWorkspaceServiceFactory [] type LanguageServicePerformanceOptions = { - EnableInMemoryCrossProjectReferences: bool AllowStaleCompletionResults: bool TimeUntilStaleCompletion: int EnableParallelReferenceResolution: bool @@ -89,7 +88,6 @@ type LanguageServicePerformanceOptions = static member Default = { - EnableInMemoryCrossProjectReferences = true AllowStaleCompletionResults = true TimeUntilStaleCompletion = 2000 // In ms, so this is 2 seconds EnableParallelReferenceResolution = false @@ -217,9 +215,6 @@ module EditorOptionsExtensions = member private this.EditorOptions = this.Solution.Workspace.Services.GetService() - member this.AreFSharpInMemoryCrossProjectReferencesEnabled = - this.EditorOptions.LanguageServicePerformance.EnableInMemoryCrossProjectReferences - member this.IsFSharpCodeFixesAlwaysPlaceOpensAtTopLevelEnabled = this.EditorOptions.CodeFixes.AlwaysPlaceOpensAtTopLevel diff --git a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml index 64714ca418d..4642e2f9c10 100644 --- a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml +++ b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml @@ -19,10 +19,6 @@ - diff --git a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs index 1cafe38a4f0..1708adc1c27 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs +++ b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs @@ -132,15 +132,6 @@ public static string Enable_Fast_Find_References { } } - /// - /// Looks up a localized string similar to _Enable in-memory cross project references. - /// - public static string Enable_in_memory_cross_project_references { - get { - return ResourceManager.GetString("Enable_in_memory_cross_project_references", resourceCulture); - } - } - /// /// Looks up a localized string similar to Use live (unsaved) buffers for checking (restart required). /// @@ -456,15 +447,6 @@ public static string Time_until_stale_completion { } } - /// - /// Looks up a localized string similar to In-memory cross-project references store project-level data in memory to allow IDE features to work across projects.. - /// - public static string Tooltip_in_memory_cross_project_references { - get { - return ResourceManager.GetString("Tooltip_in_memory_cross_project_references", resourceCulture); - } - } - /// /// Looks up a localized string similar to Format signature to the given width by adding line breaks conforming with F# syntax rules. . /// diff --git a/vsintegration/src/FSharp.UIResources/Strings.resx b/vsintegration/src/FSharp.UIResources/Strings.resx index 8036c30d271..f7f87534ac6 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.resx +++ b/vsintegration/src/FSharp.UIResources/Strings.resx @@ -147,9 +147,6 @@ _Show completion list after a character is typed - - _Enable in-memory cross project references - S_how navigation links as @@ -195,9 +192,6 @@ Enable stale data for IntelliSense features - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - Always add new line on enter diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf index c8518ec15ea..5035800a03b 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf @@ -127,11 +127,6 @@ _Zobrazovat seznam dokončení po zadání znaku - - _Enable in-memory cross project references - _Povolit odkazy mezi projekty v paměti - - S_how navigation links as Zo_brazit navigační odkazy jako @@ -207,11 +202,6 @@ Povolit zastaralá data pro funkce IntelliSense - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - V odkazech v paměti pro různé projekty jsou uložená data na úrovni projektů, aby mohly mezi projekty fungovat funkce IDE. - - Always add new line on enter Při stisku Enter vždy přidat nový řádek diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf index a5242f6b03c..0ca429bced4 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf @@ -127,11 +127,6 @@ _Vervoll­ständigungsliste nach Eingabe eines Zeichens anzeigen - - _Enable in-memory cross project references - Proj_ektübergreifende Verweise im Arbeitsspeicher aktivieren - - S_how navigation links as Navigationslink_s anzeigen als @@ -207,11 +202,6 @@ Veraltete Daten für IntelliSense-Features aktivieren - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - Bei projektübergreifenden In-Memory-Verweisen werden Daten auf Projektebene im Arbeitsspeicher abgelegt, damit IDE-Features projektübergreifend verwendet werden können. - - Always add new line on enter Nach Drücken der EINGABETASTE immer neue Zeile hinzufügen diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf index 907812312da..dea7e11508b 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf @@ -127,11 +127,6 @@ _Mostrar lista de finalización después de escribir un carácter - - _Enable in-memory cross project references - _Habilitar referencias entre proyectos en memoria - - S_how navigation links as M_ostrar vínculos de navegación como @@ -207,11 +202,6 @@ Habilitar datos obsoletos para características de IntelliSense - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - Las referencias en memoria entre proyectos almacenan los datos de nivel de proyecto en memoria para permitir que las características del IDE funcionen de unos proyectos a otros. - - Always add new line on enter Siempre agregar una nueva línea al pulsar Intro diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf index 1947b681c18..056366ae465 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf @@ -127,11 +127,6 @@ _Afficher la liste de saisie semi-automatique après la saisie d'un caractère - - _Enable in-memory cross project references - _Activer les références de projet croisé en mémoire - - S_how navigation links as Affic_her les liens de navigation en tant que @@ -207,11 +202,6 @@ Activer les données périmées pour les fonctionnalités IntelliSense - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - Les références inter-projets en mémoire stockent les données de niveau projet dans la mémoire pour permettre aux fonctionnalités de l'IDE de fonctionner sur plusieurs projets. - - Always add new line on enter Toujours ajouter une nouvelle ligne en appuyant sur Entrée diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf index b10835d5a01..34169833d7c 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf @@ -127,11 +127,6 @@ Mo_stra elenco di completamento dopo la digitazione di un carattere - - _Enable in-memory cross project references - _Abilita i riferimenti tra progetti in memoria - - S_how navigation links as M_ostra collegamenti di navigazione come @@ -207,11 +202,6 @@ Abilita dati non aggiornati per le funzionalità IntelliSense - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - I riferimenti tra progetti in memoria consentono di archiviare in memoria i dati a livello di progetto per consentire l'uso di funzionalità IDE tra progetti. - - Always add new line on enter Aggiungi sempre una nuova riga dopo INVIO diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf index 01e908209eb..c2997864851 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf @@ -127,11 +127,6 @@ 文字が入力された後に入力候補一覧を表示する(_S) - - _Enable in-memory cross project references - メモリ内のプロジェクト間参照を有効にする(_E) - - S_how navigation links as 次としてナビゲーション リンクを表示する(_H) @@ -207,11 +202,6 @@ IntelliSense 機能に対して古いデータを有効にする - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - メモリ内のプロジェクト間参照に、プロジェクトをまたいで IDE 機能を動作可能にするプロジェクト レベルのデータが格納されます。 - - Always add new line on enter Enter を押すと常に新しい行を追加します diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf index 4f70ec137f6..16cce4abb6d 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf @@ -127,11 +127,6 @@ 문자를 입력하면 완성 목록 표시(_S) - - _Enable in-memory cross project references - 메모리 내 크로스 프로젝트 참조 사용(_E) - - S_how navigation links as 탐색 링크를 다음으로 표시(_H) @@ -207,11 +202,6 @@ IntelliSense 기능에 대해 부실 데이터 사용 - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - 메모리 내 크로스 프로젝트 참조가 메모리에 프로젝트 수준 데이터를 저장하여 IDE 기능이 프로젝트에서 작동하도록 합니다. - - Always add new line on enter 입력 시 새 줄 항상 추가 diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf index 3a0047883c1..464a45a0790 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf @@ -127,11 +127,6 @@ _Pokaż listę uzupełniania po wpisaniu znaku - - _Enable in-memory cross project references - _Włącz odwołania między projektami w pamięci - - S_how navigation links as P_okaż linki nawigacyjne jako @@ -207,11 +202,6 @@ Włącz dane nieodświeżone na potrzeby funkcji IntelliSense - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - Odwołania między projektami w pamięci przechowują dane na poziomie projektu w pamięci, aby umożliwić funkcjom środowiska IDE działanie w wielu projektach. - - Always add new line on enter Zawsze dodawaj nowy wiersz po naciśnięciu klawisza Enter diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf index 0a9e4c48b66..1a70eb3c62f 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf @@ -127,11 +127,6 @@ _Mostrar lista de conclusão depois que um caractere é digitado - - _Enable in-memory cross project references - _Habilitar referências de projeto cruzado na memória - - S_how navigation links as E_xibir link de navegação como @@ -207,11 +202,6 @@ Habilitar dados obsoletos para os recursos do IntelliSense - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - As referências entre projetos na memória armazenam os dados de nível de projeto na memória para permitir que os recursos do IDE funcionem nos projetos. - - Always add new line on enter Sempre adicionar uma nova linha ao pressionar enter diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf index 5df9fce3172..bfbddfc12e5 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf @@ -127,11 +127,6 @@ _Показывать список завершения после ввода знака - - _Enable in-memory cross project references - _Включить перекрестные ссылки между проектами в памяти - - S_how navigation links as П_оказать ссылки навигации как @@ -207,11 +202,6 @@ Включение устаревших данных для функций IntelliSense - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - Перекрестные ссылки между проектами в памяти хранят данные уровня проекта в памяти, поэтому функции и компоненты IDE могут работать в разных проектах. - - Always add new line on enter Всегда добавлять новую строку при нажатии клавиши ВВОД diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf index 5216125925c..6f590b99b0f 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf @@ -127,11 +127,6 @@ Bir karakter yazıldıktan sonra tamamlanma listesini _göster - - _Enable in-memory cross project references - _Bellek içi çapraz proje başvurularını etkinleştir - - S_how navigation links as Gezinti bağlantılarını farklı _göster @@ -207,11 +202,6 @@ IntelliSense özellikleri için eski verileri etkinleştir - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - Bellek içi projeler arası başvurular, IDE özelliklerinin farklı projelerde çalışmasına imkan tanımak için bellekte proje düzeyi veriler depolar. - - Always add new line on enter Enter'a basıldığında her zaman yeni satır ekle diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf index a344b87be1b..13caff6cc04 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf @@ -127,11 +127,6 @@ 键入字符后显示完成列表(_S) - - _Enable in-memory cross project references - 启用内存中跨项目引用(_E) - - S_how navigation links as 导航链接显示方式(_H) @@ -207,11 +202,6 @@ 针对 IntelliSense 功能启用过时数据 - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - 内存中跨项目引用将项目级数据存储在内存中,让 IDE 功能能够跨项目工作。 - - Always add new line on enter 始终在点击回车时时添加新行 diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf index 80c95f5ecd7..052b9037fbb 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf @@ -127,11 +127,6 @@ 輸入一個字元後顯示完成清單(_S) - - _Enable in-memory cross project references - 允許記憶體內跨專案參考(_E) - - S_how navigation links as 顯示導覽連結為(_H) @@ -207,11 +202,6 @@ 為 IntelliSense 功能啟用過時資料 - - In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - 記憶體內跨專案參考,會在記憶體中儲存專案等級的資料,以允許 IDE 功能在各專案中皆可運作。 - - Always add new line on enter 一律在按 ENTER 時新增新行 From ed1c8a78c7f7b1612a178a79f64ce2aaf874db72 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Wed, 19 Apr 2023 15:22:08 -0700 Subject: [PATCH 2/7] trimming tests for more core F# types (#15113) * printf %A for a more core F# types * ComparisonIdentity HashIdentity * rename tests * messages --- tests/fsharp/core/libtest/test.fsx | 1 - .../SelfContained_Trimming_Test/Program.fs | 249 +++++++++++++++++- .../SelfContained_Trimming_Test/check.ps1 | 2 +- 3 files changed, 249 insertions(+), 3 deletions(-) diff --git a/tests/fsharp/core/libtest/test.fsx b/tests/fsharp/core/libtest/test.fsx index e4aa2382cec..27ff143f922 100644 --- a/tests/fsharp/core/libtest/test.fsx +++ b/tests/fsharp/core/libtest/test.fsx @@ -20,7 +20,6 @@ let test s b = else (stderr.WriteLine ("failure: " + s); reportFailure s) - let format_uint64 outc formatc width left_justify add_zeros num_prefix_if_pos (n:uint64) = let _ = match formatc with 'd' | 'i' | 'u' -> 10UL | 'o' -> 8UL | 'x' | 'X'-> 16UL | _ -> failwith "invalid value" in failwith "hello" diff --git a/tests/projects/SelfContained_Trimming_Test/Program.fs b/tests/projects/SelfContained_Trimming_Test/Program.fs index a6005136e07..22de634e776 100644 --- a/tests/projects/SelfContained_Trimming_Test/Program.fs +++ b/tests/projects/SelfContained_Trimming_Test/Program.fs @@ -1,7 +1,8 @@ module Core_printf -open Printf open Microsoft.FSharp.Reflection +open Printf +open System.Collections.Generic let failures = ref [] @@ -11,6 +12,10 @@ let report_failure (s : string) = failures := !failures @ [s] () +let check s e r = + if r <> e then + (stderr.WriteLine ($"\n***** {s}: Expected: '{e}' Results: '{r}' = FAIL\n"); report_failure s) + let test t (s1:Lazy) s2 = let s1 = s1.Force() @@ -9094,10 +9099,39 @@ module PercentAPublicTests = test "test8902" (lazy (sprintf "%A" (IntNumber 10 )).Replace("\n", ";")) """IntNumber 10""" test "test8903" (lazy (sprintf "%A" (DoubleNumber 12.0)).Replace("\n", ";")) """DoubleNumber 12.0""" + let testPercentAOptionChoiceTypes () = + test "test8920" (lazy (sprintf "%A" None).Replace("\n", ";")) "None" + test "test8921" (lazy (sprintf "%A" (Some 1.030m)).Replace("\n", ";")) "Some 1.030M" + test "test8922" (lazy (sprintf "%A" ValueNone).Replace("\n", ";")) "ValueNone" + test "test8923" (lazy (sprintf "%A" (ValueSome 1.030m)).Replace("\n", ";")) "ValueSome 1.030M" + test "test8924" (lazy (sprintf "%A" (Choice1Of2 "Hello")).Replace("\n", ";")) "Choice1Of2 \"Hello\"" + test "test8924" (lazy (sprintf "%A" (Choice1Of2 1.032m)).Replace("\n", ";")) "Choice1Of2 1.032M" + + let testUnit () = + test "test8925" (lazy (sprintf "%A" ()).Replace("\n", ";")) "()" + + let testTupleTypes () = + test "test8930" (lazy (sprintf "%A" (1, 1.020m, "Hello, World!!!!")).Replace("\n", ";")) """(1, 1.020M, "Hello, World!!!!")""" + test "test8931" (lazy (sprintf "%A" struct ( 1, 1.020m, "Hello, World!!!!" )).Replace("\n", ";")) """struct (1, 1.020M, "Hello, World!!!!")""" + + let testCollectionsTypes () = + test "test8940" (lazy (sprintf "%A" [|1;2;3;4;5;6;7;8;9|]).Replace("\n", ";")) "[|1; 2; 3; 4; 5; 6; 7; 8; 9|]" + test "test8941" (lazy (sprintf "%A" [1;2;3;4;5;6;7;8;9]).Replace("\n", ";")) "[1; 2; 3; 4; 5; 6; 7; 8; 9]" + test "test8942" (lazy (sprintf "%A" (seq {1;2;3;4;5;6;7;8;9})).Replace("\n", ";")) "seq [1; 2; 3; 4; ...]" + test "test8943" (lazy (sprintf "%A" [|[|1,2|],[|3,4|]|]).Replace("\n", ";")) "[|([|(1, 2)|], [|(3, 4)|])|]" + test "test8944" (lazy (sprintf "%A" [|[|1;2|];[|3;4|]|]).Replace("\n", ";")) "[|[|1; 2|]; [|3; 4|]|]" + test "test8945" (lazy (sprintf "%A" (dict [(1, "a"); (2, "b"); (3, "c")])).Replace("\n", ";")) "seq [[1, a]; [2, b]; [3, c]]" + test "test8946" (lazy (sprintf "%A" (set [1; 2; 3; 4; 5])).Replace("\n", ";")) "set [1; 2; 3; 4; 5]" + test "test8947" (lazy (sprintf "%A" ([ ("One", 1); ("Two", 2) ] |> Map.ofSeq))) """map [("One", 1); ("Two", 2)]""" + let tests () = testPercentAMyRecord () testPercentAMyAnnonymousRecord () testDiscriminatedUnion () + testPercentAOptionChoiceTypes () + testUnit () + testTupleTypes () + testCollectionsTypes () module PercentAInternalTests = type internal MyInternalRecord = @@ -9123,9 +9157,220 @@ module PercentAInternalTests = testPercentA () testPercentPlusA () +module ClassWithEvents = + + type EventClass () = + let event = new Event () + + [] + member _.Event = event.Publish + + member _.TriggerEvent (arg) = event.Trigger (arg) + + let testWithEventClass () = + test "test9200" ( + lazy ( + let mutable eventstring = "" + let evt = EventClass() + evt.Event.Add(fun arg -> eventstring <- eventstring + $"Event handler: {arg}") + evt.TriggerEvent("Hello World!") + eventstring + )) + """Event handler: Hello World!""" + test "test9201" ( + lazy ( + let mutable eventstring = "" + let evt = EventClass(); + evt.Event.Add(fun arg -> eventstring <- eventstring + $"First handler: {arg}") + evt.Event.Add(fun arg -> eventstring <- eventstring + $" Second handler: {arg}") + evt.TriggerEvent("Hello World!") + eventstring + )) + """First handler: Hello World! Second handler: Hello World!""" + let tests () = + testWithEventClass () + +module SameTestsUsingNonStructuralComparison2 = + open NonStructuralComparison + + do check "test9200" (3 > 1) true + do check "test9201" (3y > 1y) true + do check "test9202" (3uy > 1uy) true + do check "test9203" (3s > 1s) true + do check "test9204" (3us > 1us) true + do check "test9205" (3 > 1) true + do check "test9206" (3u > 1u) true + do check "test9207" (3L > 1L) true + do check "test9208" (3UL > 1UL) true + do check "test9209" (3.14 > 3.1) true + do check "test9210" (3.14f > 3.1f) true + do check "test9211" ("bbb" > "aaa") true + do check "test9212" ("bbb" > "bbb") false + do check "test9213" ("aaa" > "bbb") false + do check "test9214" ('b' > 'a') true + do check "test9215" ('a' > 'b') false + do check "test9216" ('b' > 'b') false + + do check "test9217" (3 >= 3) true + do check "test9218" (3y >= 3y) true + do check "test9219" (3uy >= 3uy) true + do check "test9220" (3s >= 3s) true + do check "test9221" (3us >= 3us) true + do check "test9222" (3 >= 3) true + do check "test9223" (3u >= 3u) true + do check "test9224" (3L >= 3L) true + do check "test9225" (3UL >= 3UL) true + do check "test9226" (3.14 >= 3.1) true + do check "test9227" (3.14f >= 3.1f) true + do check "test9228" (3.14M >= 3.1M) true + do check "test9229" ("bbb" >= "aaa") true + do check "test9230" ("bbb" >= "bbb") true + do check "test9231" ("aaa" >= "bbb") false + do check "test9232" ('b' >= 'a') true + do check "test9233" ('a' >= 'b') false + do check "test9234" ('b' >= 'b') true + + do check "test9235" (3 < 1) false + do check "test9236" (3y < 1y) false + do check "test9237" (3uy < 1uy) false + do check "test9238" (3s < 1s) false + do check "test9239" (3us < 1us) false + do check "test9240" (3 < 1) false + do check "test9241" (3u < 1u) false + do check "test9242" (3L < 1L) false + do check "test9243" (3UL < 1UL) false + do check "test9244" (3.14 < 1.0) false + do check "test9245" (3.14f < 1.0f) false + do check "test9246" (3.14M < 1.0M) false + do check "test9247" ("bbb" < "aaa") false + do check "test9248" ("bbb" < "bbb") false + do check "test9249" ("aaa" < "bbb") true + do check "test9250" ('b' < 'a') false + do check "test9251" ('a' < 'b') true + do check "test9252" ('b' < 'b') false + + do check "test9253" (3 <= 1) false + do check "test9254" (3y <= 1y) false + do check "test9255" (3uy <= 1uy) false + do check "test9256" (3s <= 1s) false + do check "test9257" (3us <= 1us) false + do check "test9258" (3 <= 1) false + do check "test9259" (3u <= 1u) false + do check "test9260" (3L <= 1L) false + do check "test9261" (3UL <= 1UL) false + do check "test9262" (3.14 <= 1.0) false + do check "test9263" (3.14f <= 1.0f) false + do check "test9264" (3.14M <= 1.0M) false + do check "test9265" ("bbb" <= "aaa") false + do check "test9266" ("bbb" <= "bbb") true + do check "test9267" ("aaa" <= "bbb") true + do check "test9268" ('b' <= 'a') false + do check "test9269" ('a' <= 'b') true + do check "test9270" ('b' <= 'b') true + do check "test9271" (3 <= 3) true + do check "test9272" (3y <= 3y) true + do check "test9273" (3uy <= 3uy) true + do check "test9274" (3s <= 3s) true + do check "test9275" (3us <= 3us) true + do check "test9276" (3 <= 3) true + do check "test9277" (3u <= 3u) true + do check "test9278" (3L <= 3L) true + do check "test9279" (3UL <= 3UL) true + do check "test9280" (3.14 <= 3.14) true + do check "test9281" (3.14f <= 3.14f) true + do check "test9282" (3.14M <= 3.14M) true + +module NonStructuralComparisonOverDateTime = + open NonStructuralComparison + let now = System.DateTime.Now + let tom = now.AddDays 1.0 + + do check "test9283" (now = tom) false + do check "test9284" (now <> tom) true + do check "test9285" (now < tom) true + do check "test9286" (now <= now) true + do check "test9287" (now <= tom) true + do check "test9288" (tom > now) true + do check "test9289" (now >= now) true + do check "test9290" (tom >= now) true + do check "test9291" (compare now now) 0 + do check "test9292" (compare now tom) -1 + do check "test9293" (compare tom now) 1 + do check "test9294" (max tom tom) tom + do check "test9295" (max tom now) tom + do check "test9296" (max now tom) tom + do check "test9297" (min tom tom) tom + do check "test9298" (min tom now) now + do check "test9299" (min now tom) now + + do check "test9301" (ComparisonIdentity.NonStructural.Compare (1, 1)) 0 + do check "test9302" (ComparisonIdentity.NonStructural.Compare (0, 1)) -1 + do check "test9303" (ComparisonIdentity.NonStructural.Compare (1, 0)) 1 + do check "test9304" (ComparisonIdentity.NonStructural.Compare (now, now)) 0 + do check "test9305" (ComparisonIdentity.NonStructural.Compare (now, tom)) -1 + do check "test9306" (ComparisonIdentity.NonStructural.Compare (tom, now)) 1 + do check "test9307" (HashIdentity.NonStructural.Equals (now, now)) true + do check "test9308" (HashIdentity.NonStructural.Equals (now, tom)) false + do check "test9309" (HashIdentity.NonStructural.Equals (tom, now)) false + do check "test9310" (HashIdentity.NonStructural.GetHashCode now) (hash now) + do check "test9311" (HashIdentity.NonStructural.GetHashCode tom) (hash tom) + do check "test9312" (HashIdentity.NonStructural.GetHashCode 11) (hash 11) + do check "test9313" (HashIdentity.NonStructural.GetHashCode 11L) (hash 11L) + do check "test9314" (HashIdentity.NonStructural.GetHashCode 11UL) (hash 11UL) + do check "test9315" (HashIdentity.NonStructural.Equals (1, 1)) true + do check "test9316" (HashIdentity.NonStructural.Equals (1, 0)) false + do check "test9317" (HashIdentity.NonStructural.Equals (0, 1)) false + +module NonStructuralComparisonOverTimeSpan = + open NonStructuralComparison + let now = System.TimeSpan.Zero + let tom = System.TimeSpan.FromDays 1.0 + + do check "test9318" (now = tom) false + do check "test9319" (now <> tom) true + do check "test9320" (now < tom) true + do check "test9381" (now <= now) true + do check "test9382" (now <= tom) true + do check "test9383" (tom > now) true + do check "test9384" (now >= now) true + do check "test9385" (tom >= now) true + do check "test9386" (compare now now) 0 + do check "test9387" (compare now tom) -1 + do check "test9388" (compare tom now) 1 + do check "test9389" (max tom tom) tom + do check "test9390" (max tom now) tom + do check "test9391" (max now tom) tom + do check "test9392" (min tom tom) tom + do check "test9393" (min tom now) now + do check "test9394" (min now tom) now + +// Check you can use the operators without opening the module by naming them +module NonStructuralComparisonOverTimeSpanDirect = + let now = System.TimeSpan.Zero + let tom = System.TimeSpan.FromDays 1.0 + + do check "test9395" (NonStructuralComparison.(=) now tom) false + do check "test9396" (NonStructuralComparison.(<>) now tom) true + do check "test9397" (NonStructuralComparison.(<) now tom) true + do check "test9398" (NonStructuralComparison.(<=) now now) true + do check "test9399" (NonStructuralComparison.(>) tom now) true + do check "test9400" (NonStructuralComparison.(>=) now now) true + do check "test9401" (NonStructuralComparison.compare now now) 0 + do check "test9402" (NonStructuralComparison.max tom now) tom + do check "test9403" (NonStructuralComparison.min tom now) now + + do check "test9404" (NonStructuralComparison.hash now) (Operators.hash now) + do check "test9405" (NonStructuralComparison.hash tom) (Operators.hash tom) + do check "test9406" (NonStructuralComparison.hash 11) (Operators.hash 11) + do check "test9407" (NonStructuralComparison.hash 11L) (Operators.hash 11L) + do check "test9408" (NonStructuralComparison.hash 11UL) (Operators.hash 11UL) + + [] let main _ = + testing1() + func0() func1000() func2000() @@ -9135,9 +9380,11 @@ let main _ = func6000() func7000() func8000() + PresenceOfReflectionApi.tests () PercentAPublicTests.tests () PercentAInternalTests.tests () + ClassWithEvents.testWithEventClass () match !failures with | [] -> diff --git a/tests/projects/SelfContained_Trimming_Test/check.ps1 b/tests/projects/SelfContained_Trimming_Test/check.ps1 index c1505120df8..0c959cb1715 100644 --- a/tests/projects/SelfContained_Trimming_Test/check.ps1 +++ b/tests/projects/SelfContained_Trimming_Test/check.ps1 @@ -14,7 +14,7 @@ if (-not ($output -eq $expected)) } # Checking that FSharp.Core binary is of expected size (needs adjustments if test is updated). -$expected_len = 265216 # In bytes +$expected_len = 287744 # In bytes $file = Get-Item .\bin\Release\net7.0\win-x64\publish\FSharp.Core.dll $file_len = $file.Length if (-not ($file_len -eq $expected_len)) From f69e2f5fa3a7e818f4cd90878836507120b215c0 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 20 Apr 2023 08:54:36 +0200 Subject: [PATCH 3/7] Aggregation function for Array.Parallel module (#14924) * Aggregation functions for Array.Parallel module --- src/FSharp.Core/array.fs | 94 +++++- src/FSharp.Core/array.fsi | 295 ++++++++++++++++++ ...p.Core.SurfaceArea.netstandard20.debug.bsl | 14 + ...Core.SurfaceArea.netstandard20.release.bsl | 14 + ...p.Core.SurfaceArea.netstandard21.debug.bsl | 14 + ...Core.SurfaceArea.netstandard21.release.bsl | 14 + .../ArrayModule2.fs | 95 +++++- .../CollectionModulesConsistency.fs | 49 +-- .../ListProperties.fs | 10 +- .../Microsoft.FSharp.Collections/Utils.fs | 11 +- 10 files changed, 576 insertions(+), 34 deletions(-) diff --git a/src/FSharp.Core/array.fs b/src/FSharp.Core/array.fs index 3d4ffa4474f..21fee099a9e 100644 --- a/src/FSharp.Core/array.fs +++ b/src/FSharp.Core/array.fs @@ -2081,7 +2081,7 @@ module Array = let private maxPartitions = Environment.ProcessorCount // The maximum number of partitions to use let private minChunkSize = 256 // The minimum size of a chunk to be sorted in parallel - let private createPartitionsUpTo maxIdxExclusive (array: 'T[]) = + let private createPartitionsUpToWithMinChunkSize maxIdxExclusive minChunkSize (array: 'T[]) = [| let chunkSize = match maxIdxExclusive with @@ -2098,6 +2098,98 @@ module Array = yield new ArraySegment<'T>(array, offset, maxIdxExclusive - offset) |] + let private createPartitionsUpTo maxIdxExclusive (array: 'T[]) = + createPartitionsUpToWithMinChunkSize maxIdxExclusive minChunkSize array + + (* This function is there also as a support vehicle for other aggregations. + It is public in order to be called from inlined functions, the benefit of inlining call into it is significant *) + [] + let reduceBy (projection: 'T -> 'U) (reduction: 'U -> 'U -> 'U) (array: 'T[]) = + checkNonNull "array" array + + if array.Length = 0 then + invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString + + let chunks = createPartitionsUpToWithMinChunkSize array.Length 2 array // We need at least 2 elements/chunk for 'reduction' + + let chunkResults = + Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked chunks.Length + + Parallel.For( + 0, + chunks.Length, + fun chunkIdx -> + let chunk = chunks[chunkIdx] + let mutable res = projection array[chunk.Offset] + let lastIdx = chunk.Offset + chunk.Count - 1 + + for i = chunk.Offset + 1 to lastIdx do + let projected = projection array[i] + res <- reduction res projected + + chunkResults[chunkIdx] <- res + ) + |> ignore + + let mutable finalResult = chunkResults[0] + + for i = 1 to chunkResults.Length - 1 do + finalResult <- reduction finalResult chunkResults[i] + + finalResult + + [] + let inline reduce ([] reduction) (array: _[]) = + array |> reduceBy id reduction + + let inline vFst struct (a, _) = + a + + let inline vSnd struct (_, b) = + b + + [] + let inline minBy ([] projection) (array: _[]) = + + array + |> reduceBy (fun x -> struct (projection x, x)) (fun a b -> if vFst a < vFst b then a else b) + |> vSnd + + [] + let inline min (array: _[]) = + array |> reduce (fun a b -> if a < b then a else b) + + [] + let inline sumBy ([] projection: 'T -> ^U) (array: 'T[]) : ^U = + if array.Length = 0 then + LanguagePrimitives.GenericZero + else + array |> reduceBy projection Operators.Checked.(+) + + [] + let inline sum (array: ^T[]) : ^T = + array |> sumBy id + + [] + let inline maxBy projection (array: _[]) = + + array + |> reduceBy (fun x -> struct (projection x, x)) (fun a b -> if vFst a > vFst b then a else b) + |> vSnd + + [] + let inline max (array: _[]) = + array |> reduce (fun a b -> if a > b then a else b) + + [] + let inline averageBy ([] projection: 'T -> ^U) (array: 'T[]) : ^U = + let sum = array |> reduceBy projection Operators.Checked.(+) + LanguagePrimitives.DivideByInt sum (array.Length) + + [] + let inline average (array: 'T[]) = + array |> averageBy id + [] let zip (array1: _[]) (array2: _[]) = checkNonNull "array1" array1 diff --git a/src/FSharp.Core/array.fsi b/src/FSharp.Core/array.fsi index ec0d228a365..3cd6996b132 100644 --- a/src/FSharp.Core/array.fsi +++ b/src/FSharp.Core/array.fsi @@ -3252,6 +3252,301 @@ module Array = [] val tryPick: chooser: ('T -> 'U option) -> array: 'T[] -> 'U option + /// Applies a function to each element of the array in parallel, threading an accumulator argument + /// through the computation for each thread involved in the computation. After processing entire input, results from all threads are reduced together. + /// Raises ArgumentException if the array is empty. + /// The order of processing is not guaranteed. For that reason, the 'reduce' function argument should be commutative. + /// (That is, changing the order of execution must not affect the result) + /// Also, compared to the non-parallel version of Array.reduce, the 'reduce' function may be invoked more times due to the resulting reduction from participating threads. + /// + /// The function to reduce a pair of elements to a single element. + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// Result of the reductions. + /// + /// + /// + /// let inputs = [| 1; 3; 4; 2 |] + /// + /// inputs |> Array.Parallel.reduce (fun a b -> a + b) + /// + /// Evaluates to 1 + 3 + 4 + 2. However, the system could have decided to compute (1+3) and (4+2) first, and then put them together. + /// + + [] + [] + val inline reduce: reduction: ('T -> 'T -> 'T) -> array: 'T[] -> 'T + + /// Applies a projection function to each element of the array in parallel, reducing elements in each thread with a dedicated 'reduction' function. + /// After processing entire input, results from all threads are reduced together. + /// Raises ArgumentException if the array is empty. + /// The order of processing is not guaranteed. For that reason, the 'reduction' function argument should be commutative. + /// (That is, changing the order of execution must not affect the result) + /// + /// The function to project from elements of the input array + /// The function to reduce a pair of projected elements to a single element. + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// The final result of the reductions. + /// + /// + /// + /// let inputs = [| "1"; "3"; "4"; "2" |] + /// + /// inputs |> Array.Parallel.reduceBy (fun x -> int x) (+) + /// + /// Evaluates to 1 + 3 + 4 + 2. However, the system could have decided to compute (1+3) and (4+2) first, and then put them together. + /// + + [] + [] + val reduceBy: projection: ('T -> 'U) -> reduction: ('U -> 'U -> 'U) -> array: 'T[] -> 'U + + /// Returns the greatest of all elements of the array, compared via Operators.max. + /// + /// Throws ArgumentException for empty arrays. + /// + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// The maximum element. + /// + /// + /// + /// let inputs = [| 10; 12; 11 |] + /// + /// inputs |> Array.Parallel.max + /// + /// Evaluates to 12 + /// + /// + /// + /// + /// let inputs: int[]= [| |] + /// + /// inputs |> Array.Parallel.max + /// + /// Throws System.ArgumentException. + /// + [] + [] + val inline max: array: 'T[] -> 'T when 'T: comparison + + /// Returns the greatest of all elements of the array, compared via Operators.max on the function result. + /// + /// Throws ArgumentException for empty arrays. + /// + /// The function to transform the elements into a type supporting comparison. + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// The maximum element. + /// + /// + /// + /// let inputs = [| "aaa"; "b"; "cccc" |] + /// + /// inputs |> Array.Parallel.maxBy (fun s -> s.Length) + /// + /// Evaluates to "cccc" + /// + /// + /// + /// + /// let inputs: string[]= [| |] + /// + /// inputs |> Array.Parallel.maxBy (fun s -> s.Length) + /// + /// Throws System.ArgumentException. + /// + [] + [] + val inline maxBy: projection: ('T -> 'U) -> array: 'T[] -> 'T when 'U: comparison + + /// Returns the smallest of all elements of the array, compared via Operators.min. + /// + /// Throws ArgumentException for empty arrays + /// + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// The minimum element. + /// + /// + /// + /// let inputs = [| 10; 12; 11 |] + /// + /// inputs |> Array.Parallel.min + /// + /// Evaluates to 10 + /// + /// + /// + /// + /// let inputs: int[]= [| |] + /// + /// inputs |> Array.Parallel.min + /// + /// Throws System.ArgumentException. + /// + [] + [] + val inline min: array: 'T[] -> 'T when 'T: comparison + + /// Returns the lowest of all elements of the array, compared via Operators.min on the function result. + /// + /// Throws ArgumentException for empty arrays. + /// + /// The function to transform the elements into a type supporting comparison. + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// The minimum element. + /// + /// + /// + /// let inputs = [| "aaa"; "b"; "cccc" |] + /// + /// inputs |> Array.Parallel.minBy (fun s -> s.Length) + /// + /// Evaluates to "b" + /// + /// + /// + /// + /// let inputs: string[]= [| |] + /// + /// inputs |> Array.Parallel.minBy (fun s -> s.Length) + /// + /// Throws System.ArgumentException. + /// + [] + [] + val inline minBy: projection: ('T -> 'U) -> array: 'T[] -> 'T when 'U: comparison + + /// Returns the sum of the elements in the array. + /// + /// The input array. + /// + /// The resulting sum. + /// + /// Thrown when the input array is null. + /// + /// + /// + /// let input = [| 1; 5; 3; 2 |] + /// + /// input |> Array.Parallel.sum + /// + /// Evaluates to 11. + /// + [] + [] + val inline sum: array: ^T[] -> ^T when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member Zero: ^T) + + /// Returns the sum of the results generated by applying the function to each element of the array. + /// + /// The function to transform the array elements into the type to be summed. + /// The input array. + /// + /// The resulting sum. + /// + /// Thrown when the input array is null. + /// + /// + /// + /// let input = [| "aa"; "bbb"; "cc" |] + /// + /// input |> Array.Parallel.sumBy (fun s -> s.Length) + /// + /// Evaluates to 7. + /// + [] + [] + val inline sumBy: + projection: ('T -> ^U) -> array: 'T[] -> ^U + when ^U: (static member (+): ^U * ^U -> ^U) and ^U: (static member Zero: ^U) + + /// Returns the average of the elements in the array. + /// + /// The input array. + /// + /// Thrown when array is empty. + /// Thrown when the input array is null. + /// + /// The average of the elements in the array. + /// + /// + /// + /// [| 1.0; 2.0; 6.0 |] |> Array.Parallel.average + /// + /// Evaluates to 3.0 + /// + /// + /// + /// + /// [| |] |> Array.Parallel.average + /// + /// Throws ArgumentException + /// + [] + [] + val inline average: + array: ^T[] -> ^T + when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member DivideByInt: ^T * int -> ^T) + + /// Returns the average of the elements generated by applying the function to each element of the array. + /// + /// The function to transform the array elements before averaging. + /// The input array. + /// + /// Thrown when array is empty. + /// + /// The computed average. + /// + /// Thrown when the input array is null. + /// + /// + /// + /// type Foo = { Bar: float } + /// + /// let input = [| {Bar = 2.0}; {Bar = 4.0} |] + /// + /// input |> Array.Parallel.averageBy (fun foo -> foo.Bar) + /// + /// Evaluates to 3.0 + /// + /// + /// + /// + /// type Foo = { Bar: float } + /// + /// let input : Foo[] = [| |] + /// + /// input |> Array.Parallel.averageBy (fun foo -> foo.Bar) + /// + /// Throws ArgumentException + /// + [] + [] + val inline averageBy: + projection: ('T -> ^U) -> array: 'T[] -> ^U + when ^U: (static member (+): ^U * ^U -> ^U) and ^U: (static member DivideByInt: ^U * int -> ^U) + /// Apply the given function to each element of the array. Return /// the array comprised of the results x for each element where /// the function returns Some(x). diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl index 8d196f405f3..e373ae3440b 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl @@ -48,6 +48,20 @@ Microsoft.FSharp.Collections.ArrayModule+Parallel: Microsoft.FSharp.Core.FSharpO Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[TKey,T[]][] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T[],T[]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Max[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Min[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult ReduceBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult[]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] MapIndexed[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]], T[]) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl index 8e493cc60ad..e314c7263a2 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl @@ -48,6 +48,20 @@ Microsoft.FSharp.Collections.ArrayModule+Parallel: Microsoft.FSharp.Core.FSharpO Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[TKey,T[]][] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T[],T[]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Max[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Min[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult ReduceBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult[]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] MapIndexed[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]], T[]) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl index 2577f674bad..29f826a24ba 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl @@ -48,6 +48,20 @@ Microsoft.FSharp.Collections.ArrayModule+Parallel: Microsoft.FSharp.Core.FSharpO Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[TKey,T[]][] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T[],T[]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Max[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Min[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult ReduceBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult[]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] MapIndexed[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]], T[]) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl index 55ebd5ff7bb..5114bd40b1d 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl @@ -48,6 +48,20 @@ Microsoft.FSharp.Collections.ArrayModule+Parallel: Microsoft.FSharp.Core.FSharpO Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[TKey,T[]][] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T[],T[]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Max[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Min[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult ReduceBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult[]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] MapIndexed[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]], T[]) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs index a402c396765..ec30e724bbb 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs @@ -443,9 +443,30 @@ type ArrayModule2() = // null array let nullArr = null:string[] CheckThrowsArgumentNullException (fun () -> Array.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) nullArr |> ignore) - - () + [] + member this.ParallelReduce() = + let assertSameBehavior reduction arr = + Assert.AreEqual(Array.reduce reduction arr, Array.Parallel.reduce reduction arr) + + [|5;4;3;2;1|] |> assertSameBehavior (fun x y -> x+y) + [|"A"; "B"; "C" ; "D" |] |> assertSameBehavior (fun x y -> if x < y then x else y) + + CheckThrowsArgumentException (fun () -> Array.Parallel.reduce (fun x y -> x/y) [||] |> ignore) + let nullArr = null:string[] + CheckThrowsArgumentNullException (fun () -> Array.Parallel.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) nullArr |> ignore) + + [] + member this.ParallelReduceBy() = + let assertSameBehavior projection reduction arr = + Assert.AreEqual(arr |> Array.map projection |> Array.reduce reduction, Array.Parallel.reduceBy projection reduction arr) + + [|5;4;3;2;1|] |> assertSameBehavior (fun x -> x * 2)(fun x y -> x+y) + [|"ABCD"; "B"; "C" ; "D" |] |> assertSameBehavior (fun x -> x.Length) (Operators.Checked.(+)) + + CheckThrowsArgumentException (fun () -> Array.Parallel.reduceBy id (fun x y -> x/y) [||] |> ignore) + let nullArr = null:string[] + CheckThrowsArgumentNullException (fun () -> Array.Parallel.reduceBy id (fun (x:string) (y:string) -> x.Remove(0,y.Length)) nullArr |> ignore) [] member this.ReduceBack() = @@ -1014,6 +1035,76 @@ type ArrayModule2() = CheckThrowsArgumentNullException (fun () -> Array.sumBy float32 nullArr |> ignore) () + member private _.TestOperation opName (actual:'T) (expected:'T) = + Assert.AreEqual(expected, actual, sprintf "%s: should be %A but is %A" opName expected actual) + + [] + member this.ParallelSum() = + this.TestOperation "sum empty" (Array.Parallel.sum [||]) (0) + this.TestOperation "sum single" (Array.Parallel.sum [|42|]) (42) + this.TestOperation "sum two" (Array.Parallel.sum [|42;-21|]) (21) + this.TestOperation "sum many" (Array.Parallel.sum [|1..1000|]) ((1000*1001) / 2) + this.TestOperation "sum floats" (Array.Parallel.sum [|1.;2.;3.|]) (6.) + this.TestOperation "sum infinity" (Array.Parallel.sum [|1.;2.;infinity;3.|]) (infinity) + this.TestOperation "sum nan" (Array.Parallel.sum [|infinity;nan|] |> Double.IsNaN) (true) + + [] + member this.ParallelSumBy() = + this.TestOperation "sum_by empty" (Array.Parallel.sumBy int [||]) (0) + this.TestOperation "sum_by single" (Array.Parallel.sumBy int [|42|]) (42) + this.TestOperation "sum_by two" (Array.Parallel.sumBy int [|42;-21|]) (21) + this.TestOperation "sum_by many" (Array.Parallel.sumBy int [|1..1000|]) ((1000*1001) / 2) + this.TestOperation "sum_by floats" (Array.Parallel.sumBy float [|1.;2.;3.|]) (6.) + this.TestOperation "sum_by infinity" (Array.Parallel.sumBy float [|1.;2.;infinity;3.|]) (infinity) + this.TestOperation "sum_by abs" (Array.Parallel.sumBy abs [|1; -2; 3; -4|]) (10) + this.TestOperation "sum_by string.Length" (Array.Parallel.sumBy String.length [|"abcd";"efg";"hi";"j";""|]) (10) + + [] + member this.ParallelAverage() = + CheckThrowsArgumentException (fun () -> Array.Parallel.average [||] |> ignore) + this.TestOperation "average of 0" (Array.Parallel.average [|0.|]) (0.) + this.TestOperation "average of single" (Array.Parallel.average [|4.|]) (4.) + this.TestOperation "average of two" (Array.Parallel.average [|4.;6.|]) (5.) + + [] + member this.ParallelAverageBy() = + CheckThrowsArgumentException (fun () -> Array.Parallel.averageBy float [||] |> ignore) + this.TestOperation "average_by of 0" (Array.Parallel.averageBy id [|0.|]) (0.) + this.TestOperation "average_by of single" (Array.Parallel.averageBy id [|4.|]) (4.) + this.TestOperation "average_by of two" (Array.Parallel.averageBy id [|4.;6.|]) (5.) + this.TestOperation "average_by int>float" (Array.Parallel.averageBy float [|0..1000|]) (500.) + this.TestOperation "average_by string.Length" (Array.Parallel.averageBy (String.length >> float) [|"ab";"cdef"|]) (3.) + + [] + member this.ParallelMin() = + CheckThrowsArgumentException (fun () -> Array.Parallel.min [||] |> ignore) + this.TestOperation "min single" (Array.Parallel.min [|42|]) (42) + this.TestOperation "min many" (Array.Parallel.min [|1..100|]) (1) + this.TestOperation "min floats" (Array.Parallel.min [|1.0;-1.0;nan;infinity;-infinity|]) (-infinity) + + [] + member this.ParallelMax() = + CheckThrowsArgumentException (fun () -> Array.Parallel.max [||] |> ignore) + this.TestOperation "max single" (Array.Parallel.max [|42|]) (42) + this.TestOperation "max many" (Array.Parallel.max [|1..100|]) (100) + this.TestOperation "max floats" (Array.Parallel.max [|1.0;-1.0;nan;infinity;-infinity|]) (infinity) + + [] + member this.ParallelMinBy() = + CheckThrowsArgumentException (fun () -> Array.Parallel.minBy string [||] |> ignore) + this.TestOperation "minBy single" (Array.Parallel.minBy string [|42|]) (42) + this.TestOperation "minBy int->string" (Array.Parallel.minBy string [|5..25|]) (10) + this.TestOperation "minBy many" (Array.Parallel.minBy (fun x -> -x) [|1..100|]) (100) + this.TestOperation "minBy floats" (Array.Parallel.minBy (fun x -> 1./float x) [|1..100|]) (100) + + [] + member this.ParallelMaxBy() = + CheckThrowsArgumentException (fun () -> Array.Parallel.maxBy int [||] |> ignore) + this.TestOperation "maxBy single" (Array.Parallel.maxBy string [|42|]) (42) + this.TestOperation "maxBy many" (Array.Parallel.maxBy (fun x -> -x) [|1..100|]) (1) + this.TestOperation "maxBy floats" (Array.Parallel.maxBy (fun x -> 1./float x) [|1..100|]) (1) + + [] member this.Tl() = // integer array diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs index e22e3d019ba..7b0ac00e5db 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs @@ -44,12 +44,15 @@ let ``append is consistent`` () = smallerSizeCheck append smallerSizeCheck append +let inline roundResult res = res |> Result.map (fun (x:float) -> Math.Round(x,8)) + let averageFloat (xs : NormalFloat []) = let xs = xs |> Array.map float - let s = runAndCheckErrorType (fun () -> xs |> Seq.average) - let l = runAndCheckErrorType (fun () -> xs |> List.ofArray |> List.average) - let a = runAndCheckErrorType (fun () -> xs |> Array.average) - consistency "average" s l a + let s = runAndCheckErrorType (fun () -> xs |> Seq.average) |> roundResult + let l = runAndCheckErrorType (fun () -> xs |> List.ofArray |> List.average) |> roundResult + let a = runAndCheckErrorType (fun () -> xs |> Array.average) |> roundResult + let pa = runAndCheckErrorType (fun () -> xs |> Array.Parallel.average) |> roundResult + consistencyIncludingParallel "average" s l a pa [] let ``average is consistent`` () = @@ -58,10 +61,11 @@ let ``average is consistent`` () = let averageBy (xs : float []) f = let xs = xs |> Array.map float let f x = (f x : NormalFloat) |> float - let s = runAndCheckErrorType (fun () -> xs |> Seq.averageBy f) - let l = runAndCheckErrorType (fun () -> xs |> List.ofArray |> List.averageBy f) - let a = runAndCheckErrorType (fun () -> xs |> Array.averageBy f) - consistency "averageBy" s l a + let s = runAndCheckErrorType (fun () -> xs |> Seq.averageBy f) |> roundResult + let l = runAndCheckErrorType (fun () -> xs |> List.ofArray |> List.averageBy f) |> roundResult + let a = runAndCheckErrorType (fun () -> xs |> Array.averageBy f) |> roundResult + let pa = runAndCheckErrorType (fun () -> xs |> Array.Parallel.averageBy f) |> roundResult + consistencyIncludingParallel "averageBy" s l a pa [] @@ -85,7 +89,9 @@ let choose<'a when 'a : equality> (xs : 'a []) f = let s = xs |> Seq.choose f |> Seq.toArray let l = xs |> List.ofArray |> List.choose f |> List.toArray let a = xs |> Array.choose f - consistency "contains" s l a + let pa = xs |> Array.Parallel.choose f + + consistencyIncludingParallel "contains" s l a pa [] let ``choose is consistent`` () = @@ -116,7 +122,8 @@ let collect<'a> (xs : 'a []) f = let s = xs |> Seq.collect f |> Seq.toArray let l = xs |> List.ofArray |> List.collect (fun x -> f x |> List.ofArray) |> List.toArray let a = xs |> Array.collect f - consistency "collect" s l a + let pa = xs |> Array.Parallel.collect f + consistencyIncludingParallel "collect" s l a pa @@ -705,7 +712,8 @@ let max<'a when 'a : comparison> (xs : 'a []) = let s = runAndCheckIfAnyError (fun () -> xs |> Seq.max) let l = runAndCheckIfAnyError (fun () -> xs |> List.ofArray |> List.max) let a = runAndCheckIfAnyError (fun () -> xs |> Array.max) - consistency "max" s l a + let pa = runAndCheckIfAnyError (fun () -> xs |> Array.Parallel.max) + consistencyIncludingParallel "max" s l a pa [] let ``max is consistent`` () = @@ -717,7 +725,8 @@ let maxBy<'a when 'a : comparison> (xs : 'a []) f = let s = runAndCheckIfAnyError (fun () -> xs |> Seq.maxBy f) let l = runAndCheckIfAnyError (fun () -> xs |> List.ofArray |> List.maxBy f) let a = runAndCheckIfAnyError (fun () -> xs |> Array.maxBy f) - consistency "maxBy" s l a + let pa = runAndCheckIfAnyError (fun () -> xs |> Array.Parallel.maxBy f) + consistencyIncludingParallel "maxBy" s l a pa [] let ``maxBy is consistent`` () = @@ -729,7 +738,8 @@ let min<'a when 'a : comparison> (xs : 'a []) = let s = runAndCheckIfAnyError (fun () -> xs |> Seq.min) let l = runAndCheckIfAnyError (fun () -> xs |> List.ofArray |> List.min) let a = runAndCheckIfAnyError (fun () -> xs |> Array.min) - consistency "min" s l a + let pa = runAndCheckIfAnyError (fun () -> xs |> Array.Parallel.min) + consistencyIncludingParallel "min" s l a pa [] let ``min is consistent`` () = @@ -741,7 +751,8 @@ let minBy<'a when 'a : comparison> (xs : 'a []) f = let s = runAndCheckIfAnyError (fun () -> xs |> Seq.minBy f) let l = runAndCheckIfAnyError (fun () -> xs |> List.ofArray |> List.minBy f) let a = runAndCheckIfAnyError (fun () -> xs |> Array.minBy f) - consistency "minBy" s l a + let pa = runAndCheckIfAnyError (fun () -> xs |> Array.Parallel.minBy f) + consistencyIncludingParallel "minBy" s l a pa [] let ``minBy is consistent`` () = @@ -813,8 +824,8 @@ let ``pick is consistent`` () = let reduce<'a when 'a : equality> (xs : 'a []) f = let s = runAndCheckErrorType (fun () -> xs |> Seq.reduce f) let l = runAndCheckErrorType (fun () -> xs |> List.ofArray |> List.reduce f) - let a = runAndCheckErrorType (fun () -> xs |> Array.reduce f) - consistency "reduce" s l a + let a = runAndCheckErrorType (fun () -> xs |> Array.reduce f) + consistency "reduce" s l a [] let ``reduce is consistent`` () = @@ -1004,7 +1015,8 @@ let sum (xs : int []) = let s = run (fun () -> xs |> Seq.sum) let l = run (fun () -> xs |> Array.toList |> List.sum) let a = run (fun () -> xs |> Array.sum) - consistency "sum" s l a + let pa = run (fun () -> xs |> Array.Parallel.sum) + consistencyIncludingParallel "sum" s l a pa [] let ``sum is consistent`` () = @@ -1014,7 +1026,8 @@ let sumBy<'a> (xs : 'a []) (f:'a -> int) = let s = run (fun () -> xs |> Seq.sumBy f) let l = run (fun () -> xs |> Array.toList |> List.sumBy f) let a = run (fun () -> xs |> Array.sumBy f) - consistency "sumBy" s l a + let pa = run (fun () -> xs |> Array.Parallel.sumBy f) + consistencyIncludingParallel "sumBy" s l a pa [] let ``sumBy is consistent`` () = diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs index 53623f11548..00ae357fac6 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs @@ -377,7 +377,7 @@ type ListProperties () = let b = List.tryItem pos xs match a with - | Success a -> b.Value = a + | Ok a -> b.Value = a | _ -> b = None [] @@ -391,7 +391,7 @@ type ListProperties () = let b = List.tryPick f xs match a with - | Success a -> b.Value = a + | Ok a -> b.Value = a | _ -> b = None [] @@ -405,7 +405,7 @@ type ListProperties () = let b = List.tryLast xs match a with - | Success a -> b.Value = a + | Ok a -> b.Value = a | _ -> b = None [] @@ -503,7 +503,7 @@ type ListProperties () = match run (fun () -> xs |> List.indexed |> List.permute permutation) with - | Success s -> + | Ok s -> let originals = s |> List.map fst let rs = s |> List.map snd for o in originals do @@ -718,7 +718,7 @@ type ListProperties () = let a = run (fun () -> xs |> List.findIndex predicate) let b = run (fun () -> xs |> List.rev |> List.findIndexBack predicate) match a,b with - | Success a, Success b -> a = (xs.Length - b - 1) + | Ok a, Ok b -> a = (xs.Length - b - 1) | _ -> a = b [] diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Utils.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Utils.fs index 7d55fdcb142..ce2a299a3f1 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Utils.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Utils.fs @@ -4,29 +4,24 @@ module FSharp.Core.UnitTests.Collections.Utils open Xunit -type Result<'a> = -| Success of 'a -| Error of string - let run f = try - Success(f()) + Ok(f()) with | exn -> Error(exn.Message) let runAndCheckErrorType f = try - Success(f()) + Ok(f()) with | exn -> Error(exn.GetType().ToString()) let runAndCheckIfAnyError f = try - Success(f()) + Ok(f()) with | exn -> Error("") - let isStable sorted = sorted |> Seq.pairwise |> Seq.forall (fun ((ia, a),(ib, b)) -> if a = b then ia < ib else true) let isSorted sorted = sorted |> Seq.pairwise |> Seq.forall (fun (a,b) -> a <= b) From a766f25ccc9eb7681eba223d59668874dea58c70 Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Thu, 20 Apr 2023 11:31:53 +0200 Subject: [PATCH 4/7] Include end in nested sig module range. (#15117) --- src/Compiler/pars.fsy | 14 ++++--- .../NestedModuleWithBeginEndAndDecls.fsi | 7 ++++ .../NestedModuleWithBeginEndAndDecls.fsi.bsl | 40 +++++++++++++++++++ .../NestedModule/RangeOfBeginEnd.fsi | 4 ++ .../NestedModule/RangeOfBeginEnd.fsi.bsl | 16 ++++++++ 5 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 tests/service/data/SyntaxTree/NestedModule/NestedModuleWithBeginEndAndDecls.fsi create mode 100644 tests/service/data/SyntaxTree/NestedModule/NestedModuleWithBeginEndAndDecls.fsi.bsl create mode 100644 tests/service/data/SyntaxTree/NestedModule/RangeOfBeginEnd.fsi create mode 100644 tests/service/data/SyntaxTree/NestedModule/RangeOfBeginEnd.fsi.bsl diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 01350198cdd..111f914dd72 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -662,11 +662,13 @@ moduleSpfn: if isRec then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsInvalidUseOfRec()) let info = SynComponentInfo($1 @ attribs2, None, [], path, xmlDoc, false, vis, rhs parseState 3) if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) - let m = (rhs2 parseState 1 4, $5) + let decls, mOptEnd = $5 + let m = (rhs2 parseState 1 4, decls) ||> unionRangeWithListBy (fun (d: SynModuleSigDecl) -> d.Range) |> unionRangeWithXmlDoc xmlDoc + let m = match mOptEnd with | None -> m | Some mEnd -> unionRanges m mEnd let trivia: SynModuleSigDeclNestedModuleTrivia = { ModuleKeyword = Some mModule; EqualsRange = $4 } - SynModuleSigDecl.NestedModule(info, isRec, $5, m, trivia) } + SynModuleSigDecl.NestedModule(info, isRec, decls, m, trivia) } | opt_attributes opt_access moduleIntro error { let mModule, isRec, path, vis, attribs2 = $3 @@ -743,15 +745,17 @@ moduleSpecBlock: /* #light-syntax, with no sig/end or begin/end */ | OBLOCKBEGIN moduleSpfns oblockend - { $2 } + { $2, None } /* #light-syntax, with sig/end or begin/end */ | OBLOCKBEGIN sigOrBegin moduleSpfnsPossiblyEmpty END oblockend - { $3 } + { let mEnd = rhs parseState 4 + $3, Some mEnd } /* non-#light-syntax, with sig/end or begin/end */ | sigOrBegin moduleSpfnsPossiblyEmpty END - { $2 } + { let mEnd = rhs parseState 3 + $2, Some mEnd } tyconSpfnList: diff --git a/tests/service/data/SyntaxTree/NestedModule/NestedModuleWithBeginEndAndDecls.fsi b/tests/service/data/SyntaxTree/NestedModule/NestedModuleWithBeginEndAndDecls.fsi new file mode 100644 index 00000000000..0a647263162 --- /dev/null +++ b/tests/service/data/SyntaxTree/NestedModule/NestedModuleWithBeginEndAndDecls.fsi @@ -0,0 +1,7 @@ +namespace X + +module Y = + begin + val a: int + type B = string + end diff --git a/tests/service/data/SyntaxTree/NestedModule/NestedModuleWithBeginEndAndDecls.fsi.bsl b/tests/service/data/SyntaxTree/NestedModule/NestedModuleWithBeginEndAndDecls.fsi.bsl new file mode 100644 index 00000000000..63876c52c8d --- /dev/null +++ b/tests/service/data/SyntaxTree/NestedModule/NestedModuleWithBeginEndAndDecls.fsi.bsl @@ -0,0 +1,40 @@ +SigFile + (ParsedSigFileInput + ("/root/NestedModule/NestedModuleWithBeginEndAndDecls.fsi", + QualifiedNameOfFile NestedModuleWithBeginEndAndDecls, [], [], + [SynModuleOrNamespaceSig + ([X], false, DeclaredNamespace, + [NestedModule + (SynComponentInfo + ([], None, [], [Y], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), false, + None, (3,0--3,8)), false, + [Val + (SynValSig + ([], SynIdent (a, None), SynValTyparDecls (None, true), + LongIdent (SynLongIdent ([int], [], [None])), + SynValInfo ([], SynArgInfo ([], false, None)), false, false, + PreXmlDoc ((5,8), FSharp.Compiler.Xml.XmlDocCollector), + None, None, (5,8--5,18), { LeadingKeyword = Val (5,8--5,11) + InlineKeyword = None + WithKeyword = None + EqualsRange = None }), + (5,8--5,18)); + Types + ([SynTypeDefnSig + (SynComponentInfo + ([], None, [], [B], + PreXmlDoc ((6,8), FSharp.Compiler.Xml.XmlDocCollector), + false, None, (6,13--6,14)), + Simple + (TypeAbbrev + (Ok, LongIdent (SynLongIdent ([string], [], [None])), + (6,17--6,23)), (6,17--6,23)), [], (6,13--6,23), + { LeadingKeyword = Type (6,8--6,12) + EqualsRange = Some (6,15--6,16) + WithKeyword = None })], (6,8--6,23))], (3,0--7,7), + { ModuleKeyword = Some (3,0--3,6) + EqualsRange = Some (3,9--3,10) })], PreXmlDocEmpty, [], None, + (1,0--7,7), { LeadingKeyword = Namespace (1,0--1,9) })], + { ConditionalDirectives = [] + CodeComments = [] }, set [])) diff --git a/tests/service/data/SyntaxTree/NestedModule/RangeOfBeginEnd.fsi b/tests/service/data/SyntaxTree/NestedModule/RangeOfBeginEnd.fsi new file mode 100644 index 00000000000..ce52cae2fb6 --- /dev/null +++ b/tests/service/data/SyntaxTree/NestedModule/RangeOfBeginEnd.fsi @@ -0,0 +1,4 @@ +namespace X + +module Y = + begin end diff --git a/tests/service/data/SyntaxTree/NestedModule/RangeOfBeginEnd.fsi.bsl b/tests/service/data/SyntaxTree/NestedModule/RangeOfBeginEnd.fsi.bsl new file mode 100644 index 00000000000..33815671eb9 --- /dev/null +++ b/tests/service/data/SyntaxTree/NestedModule/RangeOfBeginEnd.fsi.bsl @@ -0,0 +1,16 @@ +SigFile + (ParsedSigFileInput + ("/root/NestedModule/RangeOfBeginEnd.fsi", + QualifiedNameOfFile RangeOfBeginEnd, [], [], + [SynModuleOrNamespaceSig + ([X], false, DeclaredNamespace, + [NestedModule + (SynComponentInfo + ([], None, [], [Y], + PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector), false, + None, (3,0--3,8)), false, [], (3,0--4,13), + { ModuleKeyword = Some (3,0--3,6) + EqualsRange = Some (3,9--3,10) })], PreXmlDocEmpty, [], None, + (1,0--4,13), { LeadingKeyword = Namespace (1,0--1,9) })], + { ConditionalDirectives = [] + CodeComments = [] }, set [])) From ef89c6922f20c2982ea84f0474a1228d71f5677b Mon Sep 17 00:00:00 2001 From: Petr Date: Thu, 20 Apr 2023 12:31:03 +0200 Subject: [PATCH 5/7] Fixing hints for custom ops (#15119) --- .../Hints/InlineParameterNameHints.fs | 9 ++++--- .../Hints/InlineParameterNameHintTests.fs | 25 +++++++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs index c4da0889448..35601c2799b 100644 --- a/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs +++ b/vsintegration/src/FSharp.Editor/Hints/InlineParameterNameHints.fs @@ -54,6 +54,9 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = >> Seq.map (fun location -> location.ArgumentRange) >> Seq.contains range + let isCustomOperation (symbol: FSharpMemberOrFunctionOrValue) = + symbol.HasAttribute() + let getSourceTextAtRange (sourceText: SourceText) (range: range) = (RoslynHelpers.FSharpRangeToTextSpan(sourceText, range) |> sourceText.GetSubText) .ToString() @@ -65,11 +68,9 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = symbol.DeclaringEntity |> Option.exists (fun entity -> entity.CompiledName <> "Operators") - let isNotCustomOperation = not <| symbol.HasAttribute() - (symbol.IsFunction && isNotBuiltInOperator) // arguably, hints for those would be rather useless || symbol.IsConstructor - || (symbol.IsMethod && isNotCustomOperation) + || symbol.IsMethod else false @@ -100,8 +101,10 @@ type InlineParameterNameHints(parseResults: FSharpParseFileResults) = |> Seq.filter (fun range -> argumentLocations |> (not << isNamedArgument range)) let argumentNames = Seq.map (getSourceTextAtRange sourceText) ranges + let skipped = if symbol |> isCustomOperation then 1 else 0 parameters + |> Seq.skip skipped |> Seq.zip ranges // Seq.zip is important as List.zip requires equal lengths |> Seq.where (snd >> parameterNameExists) |> Seq.zip argumentNames diff --git a/vsintegration/tests/FSharp.Editor.Tests/Hints/InlineParameterNameHintTests.fs b/vsintegration/tests/FSharp.Editor.Tests/Hints/InlineParameterNameHintTests.fs index 46805aea480..7d58b05bd81 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/Hints/InlineParameterNameHintTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/Hints/InlineParameterNameHintTests.fs @@ -481,7 +481,7 @@ let test sequences = Assert.Equal(expected, actual) [] - let ``Hints are not shown when CustomOperation attribute is detected`` () = + let ``Hints are shown correctly for custom operations`` () = let code = """ let q = query { for x in { 1 .. 10 } do select x } @@ -489,9 +489,30 @@ let q = query { for x in { 1 .. 10 } do select x } let document = getFsDocument code + let expected = + [ + { + Content = "projection = " + Location = (1, 48) + } + ] + + let actual = getParameterNameHints document + + Assert.Equal(expected, actual) + + [] + let ``Hints are not shown for custom operations with only 1 parameter`` () = + let code = + """ +let q = query { for _ in { 1 .. 10 } do count } +""" + + let document = getFsDocument code + let actual = getParameterNameHints document - Assert.Empty actual + Assert.Empty(actual) [] let ``Hints are not shown when parameter names coincide with variable names`` () = From 58cc1a45318b76d1627523ec1f724fa8ca318c17 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Thu, 20 Apr 2023 14:53:26 +0200 Subject: [PATCH 6/7] Fix bug in return type hints (#15124) --- src/Compiler/Service/FSharpParseFileResults.fs | 2 +- .../Hints/InlineReturnTypeHintTests.fs | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Compiler/Service/FSharpParseFileResults.fs b/src/Compiler/Service/FSharpParseFileResults.fs index 3589c79f0d8..62cd5b5319d 100644 --- a/src/Compiler/Service/FSharpParseFileResults.fs +++ b/src/Compiler/Service/FSharpParseFileResults.fs @@ -412,7 +412,7 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | SynBinding(expr = SynExpr.Lambda _) when skipLambdas -> defaultTraverse binding // Skip manually type-annotated bindings - | SynBinding(returnInfo = Some (SynBindingReturnInfo(typeName = SynType.LongIdent _))) -> defaultTraverse binding + | SynBinding(returnInfo = Some (SynBindingReturnInfo _)) -> defaultTraverse binding // Let binding | SynBinding (trivia = { EqualsRange = Some equalsRange }; range = range) when range.Start = symbolUseStart -> diff --git a/vsintegration/tests/FSharp.Editor.Tests/Hints/InlineReturnTypeHintTests.fs b/vsintegration/tests/FSharp.Editor.Tests/Hints/InlineReturnTypeHintTests.fs index 48f838f9e8a..2f419d749be 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/Hints/InlineReturnTypeHintTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/Hints/InlineReturnTypeHintTests.fs @@ -109,9 +109,11 @@ let ``Hints are not shown for lambda bindings`` () = Assert.Empty result -[] -let ``Hints are not shown when there's type annotation`` () = - let code = "let func x : int = x" +[] +[] +[] +[ = [a]")>] +let ``Hints are not shown when there's type annotation`` code = let document = getFsDocument code From b1f22460c208bfc761754e88d26fed5307a3d5a0 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Fri, 21 Apr 2023 12:44:26 +0200 Subject: [PATCH 7/7] Remove unused setting (#15128) --- .../LanguageServicePerformanceOptionControl.xaml | 3 --- vsintegration/src/FSharp.UIResources/Strings.Designer.cs | 9 --------- vsintegration/src/FSharp.UIResources/Strings.resx | 3 --- vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf | 5 ----- vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf | 5 ----- vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf | 5 ----- vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf | 5 ----- vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf | 5 ----- vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf | 5 ----- vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf | 5 ----- vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf | 5 ----- .../src/FSharp.UIResources/xlf/Strings.pt-BR.xlf | 5 ----- vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf | 5 ----- vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf | 5 ----- .../src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf | 5 ----- .../src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf | 5 ----- 16 files changed, 80 deletions(-) diff --git a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml index 4642e2f9c10..eb3573f9879 100644 --- a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml +++ b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml @@ -58,9 +58,6 @@ - diff --git a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs index 1708adc1c27..05c26ae57a3 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs +++ b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs @@ -141,15 +141,6 @@ public static string Enable_Live_Buffers { } } - /// - /// Looks up a localized string similar to Enable parallel type checking with signature files. - /// - public static string Enable_Parallel_Checking_With_Signature_Files { - get { - return ResourceManager.GetString("Enable_Parallel_Checking_With_Signature_Files", resourceCulture); - } - } - /// /// Looks up a localized string similar to Enable parallel reference resolution. /// diff --git a/vsintegration/src/FSharp.UIResources/Strings.resx b/vsintegration/src/FSharp.UIResources/Strings.resx index f7f87534ac6..98d089b053b 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.resx +++ b/vsintegration/src/FSharp.UIResources/Strings.resx @@ -219,9 +219,6 @@ Parallelization (requires restart) - - Enable parallel type checking with signature files - Enable parallel reference resolution diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf index 5035800a03b..8d56d2adbdd 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf @@ -52,11 +52,6 @@ Diagnostika - - Enable parallel type checking with signature files - Povolit paralelní kontrolu typů pomocí souborů podpisu - - Enable parallel reference resolution Povolit paralelní referenční rozlišení diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf index 0ca429bced4..ea47f390c09 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf @@ -52,11 +52,6 @@ Diagnose - - Enable parallel type checking with signature files - Parallele Typüberprüfung mit Signaturdateien aktivieren - - Enable parallel reference resolution Parallele Verweisauflösung aktivieren diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf index dea7e11508b..d58237d68ba 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf @@ -52,11 +52,6 @@ Diagnóstico - - Enable parallel type checking with signature files - Habilitar la comprobación de tipos paralelos con archivos de firma - - Enable parallel reference resolution Habilitar resolución de referencias paralelas diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf index 056366ae465..30ee652da68 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf @@ -52,11 +52,6 @@ Diagnostics - - Enable parallel type checking with signature files - Activer la vérification de type parallèle avec les fichiers de signature - - Enable parallel reference resolution Activer la résolution de référence parallèle diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf index 34169833d7c..6b4009249b8 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf @@ -52,11 +52,6 @@ Diagnostica - - Enable parallel type checking with signature files - Abilitare il controllo dei tipi paralleli con i file di firma - - Enable parallel reference resolution Abilitare risoluzione riferimenti paralleli diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf index c2997864851..074852e1f72 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf @@ -52,11 +52,6 @@ 診断 - - Enable parallel type checking with signature files - 署名ファイルを使用して並列型チェックを有効にする - - Enable parallel reference resolution 並列参照解決を有効にする diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf index 16cce4abb6d..369dc3d81cc 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf @@ -52,11 +52,6 @@ 진단 - - Enable parallel type checking with signature files - 서명 파일로 병렬 유형 검사 사용 - - Enable parallel reference resolution 병렬 참조 해상도 사용 diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf index 464a45a0790..8f85bfb4f67 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf @@ -52,11 +52,6 @@ Diagnostyka - - Enable parallel type checking with signature files - Włącz równoległe sprawdzanie typów za pomocą plików podpisu - - Enable parallel reference resolution Włącz równoległe rozpoznawanie odwołań diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf index 1a70eb3c62f..257b0f3f57a 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf @@ -52,11 +52,6 @@ Diagnóstico - - Enable parallel type checking with signature files - Habilitar a verificação de tipo paralelo com arquivos de assinatura - - Enable parallel reference resolution Habilitar a resolução de referência paralela diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf index bfbddfc12e5..ed978ec293a 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf @@ -52,11 +52,6 @@ Диагностика - - Enable parallel type checking with signature files - Включить параллельную проверку типа с файлами подписей - - Enable parallel reference resolution Включить параллельное разрешение ссылок diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf index 6f590b99b0f..181076a632d 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf @@ -52,11 +52,6 @@ Tanılama - - Enable parallel type checking with signature files - İmza dosyalarıyla paralel tür denetlemeyi etkinleştir - - Enable parallel reference resolution Paralel başvuru çözümlemeyi etkinleştir diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf index 13caff6cc04..4fc3ff63c93 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf @@ -52,11 +52,6 @@ 诊断 - - Enable parallel type checking with signature files - 使用签名文件启用并行类型检查 - - Enable parallel reference resolution 启用并行引用解析 diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf index 052b9037fbb..1b0248ea005 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf @@ -52,11 +52,6 @@ 診斷 - - Enable parallel type checking with signature files - 啟用簽章檔案的平行類型檢查 - - Enable parallel reference resolution 啟用平行參考解析