From ee0f8e40ea25af458b9cb063456191609f4986f1 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Thu, 3 Aug 2023 10:00:01 +0200 Subject: [PATCH 1/3] Better error message when using wrong anon record (#15732) * Better error message when using wrong anon record --- src/Compiler/Checking/ConstraintSolver.fs | 26 ++++++++- src/Compiler/FSComp.txt | 9 ++- src/Compiler/xlf/FSComp.txt.cs.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.de.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.es.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.fr.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.it.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.ja.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.ko.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.pl.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.ru.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.tr.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 39 +++++++++---- src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 39 +++++++++---- .../Types/RecordTypes/AnonymousRecords.fs | 56 ++++++++++++++++++- tests/fsharp/typecheck/sigs/neg113.bsl | 2 +- tests/fsharp/typecheck/sigs/neg113.vsbsl | 2 +- tests/fsharp/typecheck/sigs/neg_anon_1.bsl | 2 +- 19 files changed, 438 insertions(+), 166 deletions(-) diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index f74e7509df9..fa20b108362 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1078,7 +1078,9 @@ and SolveAnonInfoEqualsAnonInfo (csenv: ConstraintSolverEnv) m2 (anonInfo1: Anon elif Set.intersect first second <> Set.empty then Overlap(firstOnly, secondOnly) else - CompletelyDifferent(Seq.toList first) + let first = Set.toList first + let second = Set.toList second + CompletelyDifferent(first, second) let message = match anonInfo1.SortedNames, anonInfo2.SortedNames with @@ -1087,6 +1089,7 @@ and SolveAnonInfoEqualsAnonInfo (csenv: ConstraintSolverEnv) m2 (anonInfo1: Anon | [missingField] -> FSComp.SR.tcAnonRecdSingleFieldNameSubset(string missingField) | _ -> + let missingFields = missingFields |> List.map(sprintf "'%s'") let missingFields = String.concat ", " missingFields FSComp.SR.tcAnonRecdMultipleFieldsNameSubset(string missingFields) | Superset extraFields -> @@ -1094,12 +1097,31 @@ and SolveAnonInfoEqualsAnonInfo (csenv: ConstraintSolverEnv) m2 (anonInfo1: Anon | [extraField] -> FSComp.SR.tcAnonRecdSingleFieldNameSuperset(string extraField) | _ -> + let extraFields = extraFields |> List.map(sprintf "'%s'") let extraFields = String.concat ", " extraFields FSComp.SR.tcAnonRecdMultipleFieldsNameSuperset(string extraFields) | Overlap (missingFields, extraFields) -> FSComp.SR.tcAnonRecdFieldNameMismatch(string missingFields, string extraFields) | CompletelyDifferent missingFields -> - FSComp.SR.tcAnonRecdFieldNameDifferent(string missingFields) + let missingFields, usedFields = missingFields + match missingFields, usedFields with + | [ missingField ], [ usedField ] -> + FSComp.SR.tcAnonRecdSingleFieldNameSingleDifferent(missingField, usedField) + | [ missingField ], usedFields -> + let usedFields = usedFields |> List.map(sprintf "'%s'") + let usedFields = String.concat ", " usedFields + FSComp.SR.tcAnonRecdSingleFieldNameMultipleDifferent(missingField, usedFields) + | missingFields, [ usedField ] -> + let missingFields = missingFields |> List.map(sprintf "'%s'") + let missingFields = String.concat ", " missingFields + FSComp.SR.tcAnonRecdMultipleFieldNameSingleDifferent(missingFields, usedField) + + | missingFields, usedFields -> + let missingFields = missingFields |> List.map(sprintf "'%s'") + let missingFields = String.concat ", " missingFields + let usedFields = usedFields |> List.map(sprintf "'%s'") + let usedFields = String.concat ", " usedFields + FSComp.SR.tcAnonRecdMultipleFieldNameMultipleDifferent(missingFields, usedFields) ErrorD (ConstraintSolverError(message, csenv.m,m2)) else diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 4c205650dbf..dfbda7e7b67 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1396,10 +1396,13 @@ tcAnonRecdInvalid,"Invalid Anonymous Record type declaration." tcAnonRecdCcuMismatch,"Two anonymous record types are from different assemblies '%s' and '%s'" tcAnonRecdFieldNameMismatch,"This anonymous record does not exactly match the expected shape. Add the missing fields %s and remove the extra fields %s." tcAnonRecdSingleFieldNameSubset,"This anonymous record is missing field '%s'." -tcAnonRecdMultipleFieldsNameSubset,"This anonymous record is missing fields '%s'." +tcAnonRecdMultipleFieldsNameSubset,"This anonymous record is missing fields %s." tcAnonRecdSingleFieldNameSuperset,"This anonymous record has an extra field. Remove field '%s'." -tcAnonRecdMultipleFieldsNameSuperset,"This anonymous record has extra fields. Remove fields '%s'." -tcAnonRecdFieldNameDifferent,"This is the wrong anonymous record. It should have the fields %s." +tcAnonRecdMultipleFieldsNameSuperset,"This anonymous record has extra fields. Remove fields %s." +tcAnonRecdSingleFieldNameSingleDifferent,"This anonymous record should have field '%s' but here has field '%s'." +tcAnonRecdSingleFieldNameMultipleDifferent,"This anonymous record should have field '%s' but here has fields %s." +tcAnonRecdMultipleFieldNameSingleDifferent,"This anonymous record should have fields %s; but here has field '%s'." +tcAnonRecdMultipleFieldNameMultipleDifferent,"This anonymous record should have fields %s; but here has fields %s." keywordDescriptionAbstract,"Indicates a method that either has no implementation in the type in which it is declared or that is virtual and has a default implementation." keywordDescriptionAnd,"Used in mutually recursive bindings, in property declarations, and with multiple constraints on generic parameters." keywordDescriptionAs,"Used to give the current class object an object name. Also used to give a name to a whole pattern within a pattern match." diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index bd2593763cb..2ff15cd7a6b 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -1032,9 +1032,9 @@ Pole {0} se v tomto výrazu záznamu vyskytuje vícekrát. - - This is the wrong anonymous record. It should have the fields {0}. - Toto je nesprávný anonymní záznam. Měl by mít pole {0}. + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ Neplatná deklarace typu anonymního záznamu + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ Dva typy anonymních záznamů jsou z různých sestavení: {0} a {1}. - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - Tento anonymní záznam neodpovídá přesně očekávanému tvaru. Přidejte chybějící pole {0} a odeberte nadbytečná pole {1}. - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. Nejde volat metodu rozšíření byref {0}. První parametr vyžaduje, aby hodnota byla měnitelná nebo typu byref, která není jen pro čtení. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 4110ca32276..08236b18246 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -1032,9 +1032,9 @@ Das Feld "{0}" ist in diesem Datensatzausdruck mehrmals vorhanden. - - This is the wrong anonymous record. It should have the fields {0}. - Dies ist der falsche anonyme Datensatz. Er muss folgende Felder umfassen: {0}. + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ Ungültige Deklaration für anonymen Datensatztyp. + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ Zwei anonyme Datensatztypen stammen aus verschiedenen Assemblys: "{0}" und "{1}". - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - Dieser anonyme Datensatz stimmt nicht genau mit der erwarteten Form überein. Fügen Sie die fehlenden Felder ({0}) hinzu, und entfernen Sie die zusätzlichen Felder ({1}). - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. Die ByRef-Erweiterungsmethode "{0}" kann nicht aufgerufen werden. Für den ersten Parameter muss der Wert änderbar sein oder einem nicht schreibgeschützten ByRef-Typ entsprechen. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index ed8fb113da1..fd837db386c 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -1032,9 +1032,9 @@ El campo "{0}" aparece varias veces en esta expresión de registro. - - This is the wrong anonymous record. It should have the fields {0}. - Este es un registro anónimo incorrecto. Debe tener los campos {0}. + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ Declaración de tipo de registro anónimo no válido. + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ Dos tipos de registro anónimos provienen de diferentes ensamblados "{0}" y "{1}" - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - Este registro anónimo no coincide exactamente con la forma esperada. Agregue los campos que faltan {0} y quite los campos adicionales {1}. - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. No se puede llamar al método de extensión de byref "{0}". El primer parámetro requiere que el valor sea mutable o un tipo de byref que no sea de solo lectura. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index bfc9572c277..1587b7f10e0 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -1032,9 +1032,9 @@ Le champ «{0}» apparaît plusieurs fois dans cette expression d’enregistrement. - - This is the wrong anonymous record. It should have the fields {0}. - Il s'agit de l'enregistrement anonyme incorrect. Il doit contenir les champs {0}. + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ Déclaration de type d'enregistrement anonyme non valide. + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ Deux types d'enregistrement anonyme proviennent d'assemblys différents '{0}' et '{1}' - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - Cet enregistrement anonyme ne correspond pas exactement à la forme attendue. Ajoutez les champs manquants {0} et supprimez les champs supplémentaires {1}. - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. Impossible d’appeler la méthode d’extension byref « {0} ». Le premier paramètre nécessite que la valeur soit mutable ou un type byref autre qu'en lecture seule. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index d4e7b1fc917..bb92fad9b00 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -1032,9 +1032,9 @@ Il campo '{0}' viene visualizzato più volte in questa espressione di record. - - This is the wrong anonymous record. It should have the fields {0}. - Si tratta del record anonimo errato. Deve includere i campi {0}. + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ La dichiarazione di tipo Record anonimo non è valida. + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ Due tipi di record anonimo provengono da assembly diversi, '{0}' e '{1}' - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - Questo record anonimo non corrisponde esattamente alla forma prevista. Aggiungere i campi mancanti {0} e rimuovere i campi aggiuntivi {1}. - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. Non è possibile chiamare il metodo di estensione byref '{0}. Il valore del primo parametro deve essere modificabile oppure un tipo byref non di sola lettura. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 37e47f6da0a..c59b5a2abf4 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -1032,9 +1032,9 @@ このレコード式に、フィールド '{0}' が複数回出現します。 - - This is the wrong anonymous record. It should have the fields {0}. - この匿名レコードは正しくありません。フィールド {0} を含んでいる必要があります。 + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ 匿名レコードの型宣言が無効です。 + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ 2 つの匿名レコードの種類は、'{0}' と '{1}' の異なるアセンブリからのものです - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - この匿名レコードは、予期された形状と完全には一致していません。不足しているフィールド {0} を追加し、不要なフィールド {1} を削除してください。 - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. byref 拡張メソッド '{0} を呼び出すことはできません。最初のパラメーターでは、値を変更可能な byref 型または読み取り専用以外の byref 型にする必要があります。 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 40751d29f73..782b1fe4b22 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -1032,9 +1032,9 @@ '{0}' 필드가 이 레코드 식에 여러 번 나타납니다. - - This is the wrong anonymous record. It should have the fields {0}. - 잘못된 익명 레코드입니다. {0} 필드가 있어야 합니다. + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ 익명 레코드 형식 선언이 잘못되었습니다. + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ 두 무명 레코드 형식은 서로 다른 어셈블리 '{0}' 및 '{1}'에서 가져왔습니다. - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - 이 익명 레코드는 필요한 도형과 정확하게 일치하지 않습니다. 누락된 필드 {0}을(를) 추가하고 추가 필드 {1}을(를) 제거하세요. - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. byref 확장 메서드 '{0}'을(를) 호출할 수 없습니다. 첫 번째 매개 변수는 변경할 수 있거나 읽기 전용이 아닌 byref 형식인 값이 필요합니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index c64f7c479b8..26e1c6498bc 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -1032,9 +1032,9 @@ Pole „{0}” występuje wielokrotnie w tym wyrażeniu rekordu. - - This is the wrong anonymous record. It should have the fields {0}. - To jest nieprawidłowy rekord anonimowy. Powinien zawierać pola {0}. + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ Nieprawidłowa deklaracja typu rekordu anonimowego. + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ Dwa typy rekordów anonimowych pochodzą z różnych zestawów: „{0}” i „{1}” - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - Ten rekord anonimowy nie jest dokładnie zgodny z oczekiwanym kształtem. Dodaj brakujące pola {0} i usuń dodatkowe pola {1}. - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. Nie można wywołać metody rozszerzenia byref „{0}”. Pierwszy parametr wymaga, aby wartość była typem byref zmiennym lub innym niż tylko do odczytu. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 1f2828362ef..afe6de384ca 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -1032,9 +1032,9 @@ O campo '{0}' aparece várias vezes nesta expressão de registro. - - This is the wrong anonymous record. It should have the fields {0}. - Este é o registro anônimo errado. Ele deve ter os campos {0}. + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ Declaração inválida de tipo de Registro Anônimo. + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ Dois tipos de registro anônimos são de diferentes assemblies '{0}' e '{1}' - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - Este registro anônimo não corresponde exatamente à forma esperada. Adicione os campos ausentes {0} e remova os campos extras {1}. - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. Não é possível chamar o método de extensão de byref '{0}. O primeiro parâmetro requer que o valor seja mutável ou não seja byref somente leitura. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index b648cf9f655..a6b7ccdcfd6 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -1032,9 +1032,9 @@ Поле "{0}" появляется несколько раз в данном выражении записи. - - This is the wrong anonymous record. It should have the fields {0}. - Неправильная анонимная запись. Она должна содержать поля {0}. + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ Недопустимое объявление типа анонимной записи. + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ Два типа анонимных записей принадлежат различным сборкам '{0}' и '{1}' - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - Эта анонимная запись не соответствует ожидаемой форме. Добавьте недостающие поля {0} и удалите лишние поля {1}. - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. Не удается вызвать метод расширения byref "{0}". В качестве первого параметра необходимо указать изменяемое значение или значение типа byref, доступное не только для чтения. diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 6ca7fdeee95..f2b50c00ba5 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -1032,9 +1032,9 @@ '{0}' alanı bu kayıt ifadesinde birden fazla yerde görünüyor. - - This is the wrong anonymous record. It should have the fields {0}. - Bu anonim kayıt yanlış. Kayıt, {0} alanlarını içermelidir. + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ Anonim Kayıt türü bildirimi geçersiz. + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ İki anonim kayıt türü, birbirinden farklı olan '{0}' ve '{1}' derlemelerinden - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - Bu anonim kayıt, beklenen şekille tam olarak eşleşmiyor. Eksik {0} alanlarını ekleyin ve ek {1} alanlarını kaldırın. - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. '{0}' byref genişletme metodu çağrılamıyor. İlk parametre, değerin değişebilir olmasını veya salt okunur olmayan bir byref türünde olmasını gerektiriyor. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 859302398f9..1f63fdbae98 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -1032,9 +1032,9 @@ 字段“{0}”在此记录表达式中多次出现。 - - This is the wrong anonymous record. It should have the fields {0}. - 此匿名记录不正确。它应具有字段 {0}。 + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ 匿名记录类型声明无效。 + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ 两个匿名记录类型来自不同的程序集“{0}”和“{1}” - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - 此匿名记录与预期的形状不完全匹配。请添加缺少的字段 {0} 并删除额外的字段 {1}。 - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. 无法调用 byref 扩展方法 "{0}"。第一个参数要求该值是可变的或非只读的 byref 类型。 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 5f0596a3035..5771d206cfd 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -1032,9 +1032,9 @@ 欄位 '{0}' 在這個記錄運算式中出現多次。 - - This is the wrong anonymous record. It should have the fields {0}. - 此為錯誤的匿名記錄。其應有欄位 {0}。 + + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. + This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. @@ -1042,14 +1042,34 @@ 匿名記錄型別宣告無效。 + + This anonymous record should have fields {0}; but here has fields {1}. + This anonymous record should have fields {0}; but here has fields {1}. + + + + This anonymous record should have fields {0}; but here has field '{1}'. + This anonymous record should have fields {0}; but here has field '{1}'. + + - This anonymous record is missing fields '{0}'. - This anonymous record is missing fields '{0}'. + This anonymous record is missing fields {0}. + This anonymous record is missing fields {0}. - This anonymous record has extra fields. Remove fields '{0}'. - This anonymous record has extra fields. Remove fields '{0}'. + This anonymous record has extra fields. Remove fields {0}. + This anonymous record has extra fields. Remove fields {0}. + + + + This anonymous record should have field '{0}' but here has fields {1}. + This anonymous record should have field '{0}' but here has fields {1}. + + + + This anonymous record should have field '{0}' but here has field '{1}'. + This anonymous record should have field '{0}' but here has field '{1}'. @@ -8397,11 +8417,6 @@ 有兩個匿名的記錄類型來自不同的組件 '{0}' 和 '{1}' - - This anonymous record does not exactly match the expected shape. Add the missing fields {0} and remove the extra fields {1}. - 此匿名記錄與預期的圖形未完全相符。請新增缺少的欄位 {0},並移除額外的欄位 {1}。 - - Cannot call the byref extension method '{0}. The first parameter requires the value to be mutable or a non-readonly byref type. 無法呼叫 byref 擴充方法 '{0}。第一個參數需要值可變動,或為非唯讀 byref 類型。 diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs index faa24a3e17a..b5074a29007 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs @@ -39,7 +39,7 @@ let x () : {| A: int; B: string; C: int |} = {| A = 123 |} |> compile |> shouldFail |> withDiagnostics [ - (Error 1, Line 2, Col 48, Line 2, Col 61, "This anonymous record is missing fields 'B, C'.") + (Error 1, Line 2, Col 48, Line 2, Col 61, "This anonymous record is missing fields 'B', 'C'.") ] [] @@ -61,8 +61,60 @@ let x () : {| A: int |} = {| A = 123 ; B = ""; C = 1 |} |> compile |> shouldFail |> withDiagnostics [ - (Error 1, Line 2, Col 29, Line 2, Col 58, "This anonymous record has extra fields. Remove fields 'B, C'.") + (Error 1, Line 2, Col 29, Line 2, Col 58, "This anonymous record has extra fields. Remove fields 'B', 'C'.") ] + + [] + let ``Using the wrong anon record with single field`` () = + Fsx """ +let x() = ({| b = 2 |} = {| a = 2 |} ) +""" + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 2, Col 26, Line 2, Col 37, "This anonymous record should have field 'b' but here has field 'a'.") + ] + + [] + let ``Using the wrong anon record with single field 2`` () = + Fsx """ +let x() = ({| b = 2 |} = {| a = 2; c = "" |} ) +""" + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 2, Col 26, Line 2, Col 45, "This anonymous record should have field 'b' but here has fields 'a', 'c'.") + ] + + [] + let ``Using the wrong anon record with multiple fields`` () = + Fsx """ +let x() = ({| b = 2; c = 3 |} = {| a = 2 |} ) +""" + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 2, Col 33, Line 2, Col 44, "This anonymous record should have fields 'b', 'c'; but here has field 'a'.") + ] + + [] + let ``Using the wrong anon record with multiple fields 2`` () = + Fsx """ +let x() = ({| b = 2; c = 3 |} = {| a = 2; d = "" |} ) +""" + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 2, Col 33, Line 2, Col 52, "This anonymous record should have fields 'b', 'c'; but here has fields 'a', 'd'.") + ] + + [] + let ``Two anon records with no fields`` () = + Fsx """ +let x() = ({||} = {||}) +""" + |> compile + |> shouldSucceed [] let ``Anonymous Records with duplicate labels - Copy and update expression`` () = diff --git a/tests/fsharp/typecheck/sigs/neg113.bsl b/tests/fsharp/typecheck/sigs/neg113.bsl index c61b8907b47..c9e74bcc6ec 100644 --- a/tests/fsharp/typecheck/sigs/neg113.bsl +++ b/tests/fsharp/typecheck/sigs/neg113.bsl @@ -1,7 +1,7 @@ neg113.fs(5,50,5,61): typecheck error FS0001: This anonymous record is missing field 'b'. -neg113.fs(7,41,7,52): typecheck error FS0001: This is the wrong anonymous record. It should have the fields [b]. +neg113.fs(7,41,7,52): typecheck error FS0001: This anonymous record should have field 'b' but here has field 'a'. neg113.fs(10,27,10,55): typecheck error FS0059: The type '{| a: int |}' does not have any proper subtypes and need not be used as the target of a static coercion diff --git a/tests/fsharp/typecheck/sigs/neg113.vsbsl b/tests/fsharp/typecheck/sigs/neg113.vsbsl index c61b8907b47..c9e74bcc6ec 100644 --- a/tests/fsharp/typecheck/sigs/neg113.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg113.vsbsl @@ -1,7 +1,7 @@ neg113.fs(5,50,5,61): typecheck error FS0001: This anonymous record is missing field 'b'. -neg113.fs(7,41,7,52): typecheck error FS0001: This is the wrong anonymous record. It should have the fields [b]. +neg113.fs(7,41,7,52): typecheck error FS0001: This anonymous record should have field 'b' but here has field 'a'. neg113.fs(10,27,10,55): typecheck error FS0059: The type '{| a: int |}' does not have any proper subtypes and need not be used as the target of a static coercion diff --git a/tests/fsharp/typecheck/sigs/neg_anon_1.bsl b/tests/fsharp/typecheck/sigs/neg_anon_1.bsl index 5f4522e7c1d..1edbabacd8c 100644 --- a/tests/fsharp/typecheck/sigs/neg_anon_1.bsl +++ b/tests/fsharp/typecheck/sigs/neg_anon_1.bsl @@ -1,7 +1,7 @@ neg_anon_1.fs(5,50,5,61): typecheck error FS0001: This anonymous record is missing field 'b'. -neg_anon_1.fs(7,41,7,52): typecheck error FS0001: This is the wrong anonymous record. It should have the fields [b]. +neg_anon_1.fs(7,41,7,52): typecheck error FS0001: This anonymous record should have field 'b' but here has field 'a'. neg_anon_1.fs(10,27,10,55): typecheck error FS0059: The type '{| a: int |}' does not have any proper subtypes and need not be used as the target of a static coercion From e5149853a0d07b44b4f4859bcd0676926822a045 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 3 Aug 2023 15:57:19 +0200 Subject: [PATCH 2/3] [main] Update dependencies from dotnet/arcade (#15742) Microsoft.DotNet.Arcade.Sdk From Version 8.0.0-beta.23401.3 -> To Version 8.0.0-beta.23402.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 6f7852b6e4d..378936e25c5 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -29,9 +29,9 @@ - + https://github.com/dotnet/arcade - f99e2f9b8aca08b8fa0877e78a448c0c0b74236d + 3addc5d978d01e864792d2c6bce0b50ec105f857 diff --git a/global.json b/global.json index b87969ef65e..3dd03b54fe8 100644 --- a/global.json +++ b/global.json @@ -18,7 +18,7 @@ "perl": "5.32.1.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23401.3", + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23402.2", "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23255.2" } } From 015a5c0a94686be97cd80ff96708db8b8ffc21db Mon Sep 17 00:00:00 2001 From: Petr Date: Thu, 3 Aug 2023 16:31:56 +0200 Subject: [PATCH 3/3] New code fix: change equals in record field definition to colon (#15456) * add tests * stub for the code fix * up * test passes * Negative test * More granular logic * baselines * anon records * Update ChangeEqualsInFieldTypeToColon.fs * Update ChangeEqualsInFieldTypeToColon.fs * Update ChangeEqualsInFieldTypeToColon.fs * Update ChangeEqualsInFieldTypeToColon.fs * up * Update ChangeEqualsInFieldTypeToColon.fs * up * ftms --- .../Service/FSharpParseFileResults.fs | 21 +++++ .../Service/FSharpParseFileResults.fsi | 3 + ...ervice.SurfaceArea.netstandard20.debug.bsl | 1 + ...vice.SurfaceArea.netstandard20.release.bsl | 1 + .../ChangeEqualsInFieldTypeToColon.fs | 64 ++++++++++++++ .../src/FSharp.Editor/Common/Constants.fs | 3 + .../src/FSharp.Editor/FSharp.Editor.fsproj | 1 + .../src/FSharp.Editor/FSharp.Editor.resx | 6 ++ .../FSharp.Editor/xlf/FSharp.Editor.cs.xlf | 10 +++ .../FSharp.Editor/xlf/FSharp.Editor.de.xlf | 10 +++ .../FSharp.Editor/xlf/FSharp.Editor.es.xlf | 10 +++ .../FSharp.Editor/xlf/FSharp.Editor.fr.xlf | 10 +++ .../FSharp.Editor/xlf/FSharp.Editor.it.xlf | 10 +++ .../FSharp.Editor/xlf/FSharp.Editor.ja.xlf | 10 +++ .../FSharp.Editor/xlf/FSharp.Editor.ko.xlf | 10 +++ .../FSharp.Editor/xlf/FSharp.Editor.pl.xlf | 10 +++ .../FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf | 10 +++ .../FSharp.Editor/xlf/FSharp.Editor.ru.xlf | 10 +++ .../FSharp.Editor/xlf/FSharp.Editor.tr.xlf | 10 +++ .../xlf/FSharp.Editor.zh-Hans.xlf | 10 +++ .../xlf/FSharp.Editor.zh-Hant.xlf | 10 +++ .../ChangeEqualsInFieldTypeToColonTests.fs | 87 +++++++++++++++++++ .../FSharp.Editor.Tests.fsproj | 1 + 23 files changed, 318 insertions(+) create mode 100644 vsintegration/src/FSharp.Editor/CodeFixes/ChangeEqualsInFieldTypeToColon.fs create mode 100644 vsintegration/tests/FSharp.Editor.Tests/CodeFixes/ChangeEqualsInFieldTypeToColonTests.fs diff --git a/src/Compiler/Service/FSharpParseFileResults.fs b/src/Compiler/Service/FSharpParseFileResults.fs index bfc1fe07aff..7456eeb3514 100644 --- a/src/Compiler/Service/FSharpParseFileResults.fs +++ b/src/Compiler/Service/FSharpParseFileResults.fs @@ -543,6 +543,27 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, let result = SyntaxTraversal.Traverse(pos, input, visitor) result.IsSome + member _.IsPositionWithinRecordDefinition pos = + let isWithin left right middle = + Position.posGt right left && Position.posLt middle right + + let visitor = + { new SyntaxVisitorBase<_>() with + override _.VisitRecordDefn(_, _, range) = + if pos |> isWithin range.Start range.End then + Some true + else + None + + override _.VisitTypeAbbrev(_, synType, range) = + match synType with + | SynType.AnonRecd _ when pos |> isWithin range.Start range.End -> Some true + | _ -> None + } + + let result = SyntaxTraversal.Traverse(pos, input, visitor) + result.IsSome + /// Get declared items and the selected item at the specified location member _.GetNavigationItemsImpl() = DiagnosticsScope.Protect diff --git a/src/Compiler/Service/FSharpParseFileResults.fsi b/src/Compiler/Service/FSharpParseFileResults.fsi index 7ee4b8ba51f..e892c78aa89 100644 --- a/src/Compiler/Service/FSharpParseFileResults.fsi +++ b/src/Compiler/Service/FSharpParseFileResults.fsi @@ -74,6 +74,9 @@ type public FSharpParseFileResults = /// Determines if the binding at the given position is bound to a lambda expression member IsBindingALambdaAtPosition: pos -> bool + /// Determines if the given position is bound to a record definition + member IsPositionWithinRecordDefinition: pos -> bool + /// Name of the file for which this information were created member FileName: string diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index c5e46327d72..384a2dd66fc 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -2076,6 +2076,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearLanguageServiceRootCachesA FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateAll() FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateConfiguration(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsBindingALambdaAtPosition(FSharp.Compiler.Text.Position) +FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPositionWithinRecordDefinition(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPosContainedInApplication(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPositionContainedInACurriedParameter(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPositionWithinTypeDefinition(FSharp.Compiler.Text.Position) diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index c5e46327d72..384a2dd66fc 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -2076,6 +2076,7 @@ FSharp.Compiler.CodeAnalysis.FSharpChecker: Void ClearLanguageServiceRootCachesA FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateAll() FSharp.Compiler.CodeAnalysis.FSharpChecker: Void InvalidateConfiguration(FSharp.Compiler.CodeAnalysis.FSharpProjectOptions, Microsoft.FSharp.Core.FSharpOption`1[System.String]) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsBindingALambdaAtPosition(FSharp.Compiler.Text.Position) +FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPositionWithinRecordDefinition(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPosContainedInApplication(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPositionContainedInACurriedParameter(FSharp.Compiler.Text.Position) FSharp.Compiler.CodeAnalysis.FSharpParseFileResults: Boolean IsPositionWithinTypeDefinition(FSharp.Compiler.Text.Position) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/ChangeEqualsInFieldTypeToColon.fs b/vsintegration/src/FSharp.Editor/CodeFixes/ChangeEqualsInFieldTypeToColon.fs new file mode 100644 index 00000000000..9dc3feed115 --- /dev/null +++ b/vsintegration/src/FSharp.Editor/CodeFixes/ChangeEqualsInFieldTypeToColon.fs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.VisualStudio.FSharp.Editor + +open System.Collections.Immutable +open System.Threading.Tasks + +open Microsoft.CodeAnalysis +open Microsoft.CodeAnalysis.Text +open Microsoft.CodeAnalysis.CodeFixes + +open FSharp.Compiler.Text + +open CancellableTasks + +[] +type internal ChangeEqualsInFieldTypeToColonCodeFixProvider() = + inherit CodeFixProvider() + + static let errorMessage = SR.UnexpectedEqualsInFieldExpectedColon() + + let isInRecord (document: Document) (range: range) = + cancellableTask { + let! parseResults = document.GetFSharpParseResultsAsync(nameof ChangeEqualsInFieldTypeToColonCodeFixProvider) + + return parseResults.IsPositionWithinRecordDefinition(range.Start) + } + + override _.FixableDiagnosticIds = ImmutableArray.Create "FS0010" + + override this.RegisterCodeFixesAsync context = + // This is a performance shortcut. + // Since FS0010 fires all too often, we're just stopping any processing if it's a different error message. + // The code fix logic itself still has this logic and implements it more reliably. + if context.Diagnostics[ 0 ].GetMessage() = errorMessage then + context.RegisterFsharpFix this + else + Task.CompletedTask + + interface IFSharpCodeFixProvider with + member _.GetCodeFixIfAppliesAsync context = + cancellableTask { + let! spanText = context.GetSquigglyTextAsync() + + if spanText <> "=" then + return ValueNone + + else + let! errorRange = context.GetErrorRangeAsync() + let! isInRecord = errorRange |> isInRecord context.Document + + if not isInRecord then + return ValueNone + + else + let codeFix = + { + Name = CodeFix.ChangeEqualsInFieldTypeToColon + Message = SR.ChangeEqualsInFieldTypeToColon() + Changes = [ TextChange(TextSpan(context.Span.Start, context.Span.Length), ":") ] + } + + return (ValueSome codeFix) + } diff --git a/vsintegration/src/FSharp.Editor/Common/Constants.fs b/vsintegration/src/FSharp.Editor/Common/Constants.fs index 5e24d8a86b7..d59b241b44e 100644 --- a/vsintegration/src/FSharp.Editor/Common/Constants.fs +++ b/vsintegration/src/FSharp.Editor/Common/Constants.fs @@ -132,6 +132,9 @@ module internal CodeFix = [] let ChangeToUpcast = "ChangeToUpcast" + [] + let ChangeEqualsInFieldTypeToColon = "ChangeEqualsInFieldTypeToColon" + [] let UseMutationWhenValueIsMutable = "UseMutationWhenValueIsMutable" diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index cccf45b0e33..b73a33b690d 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -103,6 +103,7 @@ + diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.resx b/vsintegration/src/FSharp.Editor/FSharp.Editor.resx index 7faf42e190f..251cd02d780 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.resx +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.resx @@ -280,6 +280,12 @@ Use live (unsaved) buffers for checking Use ':>' operator + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + + Use ':' for type in field declaration + Add missing '=' to type definition diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf index aa400d2f560..fa6aa6fd4cc 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ Přerušované podtržení; Odeberte nepoužité otevřené deklarace. + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. Otevřenou deklaraci nelze odebrat. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf index c8e43ea2004..e3cc881854d 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ Strich unterstrichen; Nicht verwendete open-Deklarationen entfernen + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. Open-Deklaration kann nicht entfernt werden. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf index e7a15db6632..83074b9f703 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -263,6 +268,11 @@ Subrayado de guion; Quitar declaraciones abiertas no usadas + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. Las declaraciones abiertas se pueden quitar. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf index 33c60f49f00..1aea7681a66 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ Soulignement en tirets ; Supprimer les déclarations open inutilisées + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. La déclaration open peut être supprimée. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf index 0ae400abfa6..4b74d02fdf8 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ Sottolineatura a trattini; Rimuovi dichiarazioni OPEN inutilizzate + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. La dichiarazione OPEN può essere rimossa. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf index 5906f7efc57..4cfbba3fb49 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ F# 構文規則に準拠するよう、改行を追加して指定された幅 未使用の Open 宣言を削除する + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. Open 宣言は削除できます。 diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf index 7ee219bbc77..6eb8c0f3ec1 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ F# 구문 규칙에 맞는 줄바꿈을 추가하여 지정된 너비에 서명 사용하지 않는 열려 있는 선언 제거 + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. 열려 있는 선언을 제거할 수 있습니다. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf index 6c4a1c54f12..f4d5ad66fa9 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ Podkreślenie kreską; Usuń nieużywane otwarte deklaracje + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. Otwarte deklaracje można usuwać. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf index f4371880eed..34d03fefbe9 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ Traço sublinhado; Remover declarações abertas não usadas + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. A declaração aberta pode ser removida. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf index 110c6b15ff7..97331156092 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ Dash underline; Удалить неиспользуемые открытые объявления + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. Открытое объявление можно удалить. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf index f7900271f5c..52608a483ae 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ Tire alt çizgisi; Kullanılmayan açık bildirimleri kaldır + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. Açık bildirim kaldırılabilir. diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf index 26f84c9b289..207e0a9470b 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ Dash underline; 删除未使用的 open 声明 + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. 可删除 open 声明。 diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf index e3f2ede726d..d6cd3abe0e2 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf @@ -50,6 +50,11 @@ Live Buffers; Use live (unsaved) buffers for checking + + Use ':' for type in field declaration + Use ':' for type in field declaration + + Simplify names (remove unnecessary qualifiers); Always place open statements at the top level; @@ -261,6 +266,11 @@ Dash underline; 移除未使用的公開宣告 + + Unexpected symbol '=' in field declaration. Expected ':' or other token. + Unexpected symbol '=' in field declaration. Expected ':' or other token. + + Open declaration can be removed. 可以移除公開宣告。 diff --git a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/ChangeEqualsInFieldTypeToColonTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/ChangeEqualsInFieldTypeToColonTests.fs new file mode 100644 index 00000000000..942fa866d2b --- /dev/null +++ b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/ChangeEqualsInFieldTypeToColonTests.fs @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module FSharp.Editor.Tests.CodeFixes.ChangeEqualsInFieldTypeToColonTests + +open Microsoft.VisualStudio.FSharp.Editor +open Xunit + +open CodeFixTestFramework + +let private codeFix = ChangeEqualsInFieldTypeToColonCodeFixProvider() + +[] +let ``Fixes FS0010 for = in record definitions`` () = + let code = + """ +type Band = { Name = string } +""" + + let expected = + Some + { + Message = "Use ':' for type in field declaration" + FixedCode = + """ +type Band = { Name : string } +""" + } + + let actual = codeFix |> tryFix code Auto + + Assert.Equal(expected, actual) + +[] +let ``Fixes FS0010 for = in anonymous record definitions`` () = + let code = + """ +type Band = {| Name = string |} +""" + + let expected = + Some + { + Message = "Use ':' for type in field declaration" + FixedCode = + """ +type Band = {| Name : string |} +""" + } + + let actual = codeFix |> tryFix code Auto + + Assert.Equal(expected, actual) + +[] +[] +[] +let ``Doesn't fix FS0010 for random unexpected symbols`` code = + let expected = None + + let actual = codeFix |> tryFix code Auto + + Assert.Equal(expected, actual) + +[] +[] +[] +[] +let ``Doesn't fix FS0010 for = in places other than within record field definitions`` code = + let expected = None + + let actual = codeFix |> tryFix code Auto + + Assert.Equal(expected, actual) diff --git a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj index 5558e1f05d0..f9aaae94fa5 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj +++ b/vsintegration/tests/FSharp.Editor.Tests/FSharp.Editor.Tests.fsproj @@ -55,6 +55,7 @@ +