From 0e8f267ff6ec8c09087c1dd5c5e1135215831661 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Mon, 26 Sep 2022 08:55:09 +0200 Subject: [PATCH 01/32] Remove check for jagged arrays and add unit tests (#13974) Jagged arrays should not be rendered as "array{n}d<_>", that was a mistake leading to conflict with multidimensional arrays. This PR reverts this and also adds test to check regression of this feature. --- src/Compiler/Checking/NicePrint.fs | 14 ------------- src/Compiler/TypedTree/TypedTreeOps.fs | 16 +------------- src/Compiler/TypedTree/TypedTreeOps.fsi | 3 --- .../Signatures/ArrayTests.fs | 21 +++++++++---------- 4 files changed, 11 insertions(+), 43 deletions(-) diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index dbbe333b9cd..b7b4cce955f 100644 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -875,16 +875,6 @@ module PrintTypes = | [] -> tcL | [arg] -> layoutTypeWithInfoAndPrec denv env 2 arg ^^ tcL | args -> bracketIfL (prec <= 1) (bracketL (layoutTypesWithInfoAndPrec denv env 2 (sepL (tagPunctuation ",")) args) --- tcL) - - and layoutTypeForGenericMultidimensionalArrays denv env prec tcref innerT level = - let innerLayout = layoutTypeWithInfoAndPrec denv env prec innerT - - let arrayLayout = - tagEntityRefName denv tcref $"array{level}d" - |> mkNav tcref.DefinitionRange - |> wordL - - innerLayout ^^ arrayLayout /// Layout a type, taking precedence into account to insert brackets where needed and layoutTypeWithInfoAndPrec denv env prec ty = @@ -906,10 +896,6 @@ module PrintTypes = // Always prefer 'float' to 'float<1>' | TType_app (tc, args, _) when tc.IsMeasureableReprTycon && List.forall (isDimensionless g) args -> layoutTypeWithInfoAndPrec denv env prec (reduceTyconRefMeasureableOrProvided g tc args) - - // Special case for nested array> shape - | TTypeMultiDimensionalArrayAsGeneric (tcref, innerT, level) -> - layoutTypeForGenericMultidimensionalArrays denv env prec tcref innerT level // Layout a type application | TType_ucase (UnionCaseRef(tc, _), args) diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index bc037c8af7e..c166230e718 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -10410,18 +10410,4 @@ let (|EmptyModuleOrNamespaces|_|) (moduleOrNamespaceContents: ModuleOrNamespaceC Some emptyModuleOrNamespaces else None - | _ -> None - -let (|TTypeMultiDimensionalArrayAsGeneric|_|) (t: TType) = - let rec (|Impl|_|) t = - match t with - | TType_app(tc, [Impl(outerTc, innerT, currentLevel)], _) when tc.DisplayNameCore = "array" -> - Some (outerTc, innerT, currentLevel + 1) - | TType_app(tc, [arg], _) when tc.DisplayNameCore = "array" -> - Some (tc, arg, 1) - | _ -> None - - match t with - | Impl (tc, arg, level) -> - if level > 2 then Some (tc, arg, level) else None - | _ -> None + | _ -> None \ No newline at end of file diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi index 403498c5417..00d838e04d4 100755 --- a/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -2687,6 +2687,3 @@ type TraitConstraintInfo with /// This will match anything that does not have any types or bindings. val (|EmptyModuleOrNamespaces|_|): moduleOrNamespaceContents: ModuleOrNamespaceContents -> (ModuleOrNamespace list) option - -/// Captures an application type with a multi-dimensional array as postfix. -val (|TTypeMultiDimensionalArrayAsGeneric|_|): t: TType -> (TyconRef * TType * int) option diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/ArrayTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/ArrayTests.fs index 2317005032f..da6c65b1c82 100644 --- a/tests/FSharp.Compiler.ComponentTests/Signatures/ArrayTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Signatures/ArrayTests.fs @@ -32,17 +32,16 @@ let ``4 dimensional array`` () = "val a: int array4d" [] -let ``5 till 32 dimensional array`` () = - [ 5 .. 32 ] - |> List.iter (fun idx -> - let arrayType = - [ 1 .. idx ] - |> List.fold (fun acc _ -> $"array<{acc}>") "int" - - assertSingleSignatureBinding - $"let a : {arrayType} = failwith \"todo\"" - $"val a: int array{idx}d" - ) +let ``jagged array 1`` () = + assertSingleSignatureBinding + "let a : array>>>> = failwith \"todo\"" + "val a: int array array array array array" + +[] +let ``jagged array 2`` () = + assertSingleSignatureBinding + "let a: int[][][][][] = failwith \"todo\"" + "val a: int array array array array array" [] let ``Use array2d syntax in implementation`` () = From 6b48ca6ac5b85567e7116a96dc5313d5620fb2c4 Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Mon, 26 Sep 2022 12:45:03 +0200 Subject: [PATCH 02/32] Delete bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 69 --------------------------- 1 file changed, 69 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml deleted file mode 100644 index f10d1a55e5a..00000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Bug report -description: Create a report to help us improve F# -title: "`Bug`: " -labels: [Needs Triage] -body: -- type: checkboxes - attributes: - label: Is there an existing issue for this? - description: Please search to see if an issue already exists for the bug you encountered. - options: - - label: I have searched the existing issues - required: true -- type: textarea - attributes: - label: Issue description - description: Please provide a succinct description of the issue you're experiencing. - validations: - required: true -- type: textarea - attributes: - label: Steps To Reproduce - description: Provide the steps required to reproduce the problem. - placeholder: | - 1. Step A - 2. Step B... - validations: - required: false -- type: textarea - attributes: - label: Expected Behavior - description: Provide a description of the expected behavior. - validations: - required: true -- type: textarea - attributes: - label: Actual Behavior - description: Provide a description of the actual behaviour observed. - validations: - required: true -- type: textarea - attributes: - label: Known workarounds - description: Provide a description of the actual behaviour observed. - validations: - required: false -- type: textarea - attributes: - label: Related information - description: | - Provide any related information (optional), examples: - - **OS**: Windows 11 - - **.NET Runtime Kind and version**: .NET Framework 4.8 and .NET 7 - - **Tooling**: Visual Studio 2022 - value: | - - OS: - - .NET Runtime Kind and version: - - Tooling: - render: markdown - validations: - required: false -- type: textarea - attributes: - label: Anything else? - description: | - Links? References? Anything that will give us more context about the issue you are encountering! - - Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. - validations: - required: false From 5395b5d3b448d59d31c210c3a2d8c9757048267a Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Mon, 26 Sep 2022 12:49:11 +0200 Subject: [PATCH 03/32] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 6c1de31c1b2..6a22a1cca73 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,7 +2,7 @@ name: Bug report about: Create a report to help us improve F# title: '' -labels: Bug +labels: [Bug, Needs-Triage] assignees: '' --- From 9714ceb164cf332681ea38266f378f4cfaf35964 Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Mon, 26 Sep 2022 12:50:22 +0200 Subject: [PATCH 04/32] Update feature_request.md --- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 1397683d28c..9902369d951 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: Feature request about: Suggest an idea for the F# tools or compiler title: '' -labels: Feature Request +labels: [Feature Request, Needs-Triage] assignees: '' --- From 8a62c6cf2f33ea476d3f7364ea9812a312ed00ca Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Mon, 26 Sep 2022 12:53:06 +0200 Subject: [PATCH 05/32] Create other_issue.md --- .github/ISSUE_TEMPLATE/other_issue.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/other_issue.md diff --git a/.github/ISSUE_TEMPLATE/other_issue.md b/.github/ISSUE_TEMPLATE/other_issue.md new file mode 100644 index 00000000000..9f737b857bc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/other_issue.md @@ -0,0 +1,10 @@ +--- +name: Other issue +about: Open an issue which does not belong to any categories above +title: '' +labels: [Needs-Triage] +assignees: '' + +--- + + From 8c7c39c5b68aae58d10d72a6c83658b40fbfaedf Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Mon, 26 Sep 2022 15:50:34 +0200 Subject: [PATCH 06/32] Update DEVGUIDE.md --- DEVGUIDE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DEVGUIDE.md b/DEVGUIDE.md index 2f7d899e329..da02c907c22 100644 --- a/DEVGUIDE.md +++ b/DEVGUIDE.md @@ -44,12 +44,12 @@ This will update your fork with the latest from `dotnet/fsharp` on your machine ## Developing on Windows -Install the latest released [Visual Studio](https://www.visualstudio.com/downloads/), as that is what the `main` branch's tools are synced with. Select the following workloads: +Install the latest released [Visual Studio](https://visualstudio.microsoft.com/vs/preview/) preview, as that is what the `main` branch's tools are synced with. Select the following workloads: * .NET desktop development (also check F# desktop support, as this will install some legacy templates) * Visual Studio extension development -You will also need the latest .NET 6 SDK installed from [here](https://dotnet.microsoft.com/download/dotnet/6.0). +You will also need the latest .NET 7 SDK installed from [here](https://dotnet.microsoft.com/download/dotnet/7.0). Building is simple: @@ -73,10 +73,10 @@ If you don't have everything installed yet, you'll get prompted by Visual Studio If you are just developing the core compiler and library then building ``FSharp.sln`` will be enough. -We recommend installing the latest released Visual Studio and using that if you are on Windows. However, if you prefer not to do that, you will need to install the following: +We recommend installing the latest Visual Studio preview and using that if you are on Windows. However, if you prefer not to do that, you will need to install the following: * [.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472) -* [.NET 6](https://dotnet.microsoft.com/download/dotnet/6.0) +* [.NET 7](https://dotnet.microsoft.com/download/dotnet/7.0) You'll need to pass an additional flag to the build script: From fcbc1ddffe650388202725bcd426672ecd7b3650 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Mon, 26 Sep 2022 19:48:45 +0200 Subject: [PATCH 07/32] Symbols: create constructor symbols for class constructor items (#13822) * Symbols API: do not provide vanilla symbols for class constructor * Fix * Formatting Co-authored-by: Vlad Zarytovskii Co-authored-by: Don Syme --- src/Compiler/Symbols/Symbols.fs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index ec343ad2a8d..9adb5ffb1f9 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -266,7 +266,10 @@ type FSharpSymbol(cenv: SymbolEnv, item: unit -> Item, access: FSharpSymbol -> C static member Create(cenv, item): FSharpSymbol = let dflt() = FSharpSymbol(cenv, (fun () -> item), (fun _ _ _ -> true)) - match item with + match item with + | Item.Value v when v.Deref.IsClassConstructor -> + FSharpMemberOrFunctionOrValue(cenv, C (FSMeth(cenv.g, generalizeTyconRef cenv.g v.DeclaringEntity |> snd, v, None)), item) :> _ + | Item.Value v -> FSharpMemberOrFunctionOrValue(cenv, V v, item) :> _ | Item.UnionCase (uinfo, _) -> FSharpUnionCase(cenv, uinfo.UnionCaseRef) :> _ | Item.ExnCase tcref -> FSharpEntity(cenv, tcref) :>_ @@ -632,8 +635,10 @@ type FSharpEntity(cenv: SymbolEnv, entity: EntityRef) = protect <| fun () -> ([ let entityTy = generalizedTyconRef cenv.g entity let createMember (minfo: MethInfo) = - if minfo.IsConstructor then FSharpMemberOrFunctionOrValue(cenv, C minfo, Item.CtorGroup (minfo.DisplayName, [minfo])) - else FSharpMemberOrFunctionOrValue(cenv, M minfo, Item.MethodGroup (minfo.DisplayName, [minfo], None)) + if minfo.IsConstructor || minfo.IsClassConstructor then + FSharpMemberOrFunctionOrValue(cenv, C minfo, Item.CtorGroup (minfo.DisplayName, [minfo])) + else + FSharpMemberOrFunctionOrValue(cenv, M minfo, Item.MethodGroup (minfo.DisplayName, [minfo], None)) if x.IsFSharpAbbreviation then () elif x.IsFSharp then From 58023aa4f8bf917fe3de8ef51c9e327e6c5701e6 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 27 Sep 2022 09:07:13 +0100 Subject: [PATCH 08/32] fix go-to-definition to symbols in large files (#13987) * fix go-to-definition to symbols in large files * fix go-to-definition to symbols in large files --- src/Compiler/Driver/CompilerImports.fs | 1 + src/Compiler/Utilities/illib.fs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Driver/CompilerImports.fs b/src/Compiler/Driver/CompilerImports.fs index 56513446bd3..a329635b609 100644 --- a/src/Compiler/Driver/CompilerImports.fs +++ b/src/Compiler/Driver/CompilerImports.fs @@ -2142,6 +2142,7 @@ and [] TcImports CheckDisposed() let tcConfig = tcConfigP.Get ctok + let runMethod = match tcConfig.parallelReferenceResolution with | ParallelReferenceResolution.On -> NodeCode.Parallel diff --git a/src/Compiler/Utilities/illib.fs b/src/Compiler/Utilities/illib.fs index 6eab1b08508..49cef8a36a9 100644 --- a/src/Compiler/Utilities/illib.fs +++ b/src/Compiler/Utilities/illib.fs @@ -610,7 +610,7 @@ module ResizeArray = // * doing a block copy using `List.CopyTo(index, array, index, count)` (requires more copies to do the mapping) // none are significantly better. for i in 0 .. takeCount - 1 do - holder[i] <- f items[i] + holder[i] <- f items[startIndex + i] yield holder |] From 4f7f156c96e37e2bc211ec9b9b109bbbfaa688b4 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 27 Sep 2022 12:18:49 +0200 Subject: [PATCH 09/32] Parser: recover on missing items in tuple patterns (#13985) --- src/Compiler/FSComp.txt | 2 + src/Compiler/SyntaxTree/SyntaxTreeOps.fs | 7 + src/Compiler/SyntaxTree/SyntaxTreeOps.fsi | 2 + src/Compiler/pars.fsy | 76 +++++++-- src/Compiler/xlf/FSComp.txt.cs.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.de.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.es.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.fr.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.it.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.ja.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.ko.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.pl.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.ru.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.tr.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 10 ++ src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 10 ++ tests/service/Common.fs | 7 +- tests/service/ParserTests.fs | 157 ++++++++++++++++-- tests/service/PatternMatchCompilationTests.fs | 5 + 20 files changed, 363 insertions(+), 23 deletions(-) diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 086d5279488..61054bba210 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1653,3 +1653,5 @@ reprStateMachineInvalidForm,"The state machine has an unexpected form" 3536,tcUsingInterfaceWithStaticAbstractMethodAsType,"'%s' is normally used as a type constraint in generic code, e.g. \"'T when ISomeInterface<'T>\" or \"let f (x: #ISomeInterface<_>)\". See https://aka.ms/fsharp-iwsams for guidance. You can disable this warning by using '#nowarn \"3536\"' or '--nowarn:3536'." 3537,tcTraitHasMultipleSupportTypes,"The trait '%s' invoked by this call has multiple support types. This invocation syntax is not permitted for such traits. See https://aka.ms/fsharp-srtp for guidance." 3545,tcMissingRequiredMembers,"The following required properties have to be initalized:%s" +3546,parsExpectingPatternInTuple,"Expecting pattern" +3547,parsExpectedPatternAfterToken,"Expected a pattern after this point" diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs index ef3673fa44f..aefc238d10e 100644 --- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs +++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs @@ -1031,6 +1031,13 @@ let rec normalizeTupleExpr exprs commas : SynExpr list * range list = innerExprs @ rest, innerCommas @ commas | _ -> exprs, commas +let rec normalizeTuplePat pats : SynPat list = + match pats with + | SynPat.Tuple (false, innerPats, _) :: rest -> + let innerExprs = normalizeTuplePat (List.rev innerPats) + innerExprs @ rest + | _ -> pats + /// Remove all members that were captures as SynMemberDefn.GetSetMember let rec desugarGetSetMembers (memberDefns: SynMemberDefns) = memberDefns diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi b/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi index 5af8180d05e..b78563d4bce 100644 --- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fsi @@ -350,6 +350,8 @@ val mkDynamicArgExpr: expr: SynExpr -> SynExpr val normalizeTupleExpr: exprs: SynExpr list -> commas: range list -> SynExpr list * range List +val normalizeTuplePat: pats: SynPat list -> SynPat list + val desugarGetSetMembers: memberDefns: SynMemberDefns -> SynMemberDefns val getTypeFromTuplePath: path: SynTupleTypeSegment list -> SynType list diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index d7bbdaaf68e..6e194678018 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -3126,8 +3126,10 @@ headBindingPattern: | headBindingPattern COLON_COLON headBindingPattern { SynPat.LongIdent (SynLongIdent(mkSynCaseName (rhs parseState 2) opNameCons, [], [ Some (IdentTrivia.OriginalNotation "::") ]), None, None, SynArgPats.Pats [SynPat.Tuple (false, [$1;$3], rhs2 parseState 1 3)], None, lhs parseState) } - | tuplePatternElements %prec pat_tuple - { SynPat.Tuple(false, List.rev $1, lhs parseState) } + | tuplePatternElements %prec pat_tuple + { let pats = normalizeTuplePat $1 + let m = (rhs parseState 1, pats) ||> unionRangeWithListBy (fun p -> p.Range) + SynPat.Tuple(false, List.rev pats, m) } | conjPatternElements %prec pat_conj { SynPat.Ands(List.rev $1, lhs parseState) } @@ -3135,12 +3137,37 @@ headBindingPattern: | constrPattern { $1 } -tuplePatternElements: - | tuplePatternElements COMMA headBindingPattern +tuplePatternElements: + | tuplePatternElements COMMA headBindingPattern { $3 :: $1 } - | headBindingPattern COMMA headBindingPattern - { $3 :: $1 :: [] } + | headBindingPattern COMMA headBindingPattern + { [$3; $1] } + + | tuplePatternElements COMMA ends_coming_soon_or_recover + { let commaRange = rhs parseState 2 + reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple ()) + let pat2 = SynPat.Wild(commaRange.EndRange) + pat2 :: $1 } + + | headBindingPattern COMMA ends_coming_soon_or_recover + { let commaRange = rhs parseState 2 + reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple ()) + let pat2 = SynPat.Wild(commaRange.EndRange) + [pat2; $1] } + + | COMMA headBindingPattern + { let commaRange = rhs parseState 1 + reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple ()) + let pat1 = SynPat.Wild(commaRange.StartRange) + [$2; pat1] } + + | COMMA ends_coming_soon_or_recover + { let commaRange = rhs parseState 1 + if not $2 then reportParseErrorAt commaRange (FSComp.SR.parsExpectedPatternAfterToken ()) + let pat1 = SynPat.Wild(commaRange.StartRange) + let pat2 = SynPat.Wild(commaRange.EndRange) + [pat2; pat1] } conjPatternElements: | conjPatternElements AMP headBindingPattern @@ -3351,8 +3378,10 @@ parenPattern: { let mBar = rhs parseState 2 SynPat.Or($1, $3, rhs2 parseState 1 3, { BarRange = mBar }) } - | tupleParenPatternElements - { SynPat.Tuple(false, List.rev $1, lhs parseState) } + | tupleParenPatternElements + { let pats = normalizeTuplePat $1 + let m = (rhs parseState 1, pats) ||> unionRangeWithListBy (fun p -> p.Range) + SynPat.Tuple(false, List.rev pats, m) } | conjParenPatternElements { SynPat.Ands(List.rev $1, rhs2 parseState 1 3) } @@ -3371,11 +3400,36 @@ parenPattern: | constrPattern { $1 } tupleParenPatternElements: - | tupleParenPatternElements COMMA parenPattern + | tupleParenPatternElements COMMA parenPattern { $3 :: $1 } - | parenPattern COMMA parenPattern - { $3 :: $1 :: [] } + | parenPattern COMMA parenPattern + { [$3; $1] } + + | tupleParenPatternElements COMMA ends_coming_soon_or_recover + { let commaRange = rhs parseState 2 + reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple()) + let pat2 = SynPat.Wild(commaRange.EndRange) + pat2 :: $1 } + + | parenPattern COMMA ends_coming_soon_or_recover + { let commaRange = rhs parseState 2 + reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple()) + let pat2 = SynPat.Wild(commaRange.EndRange) + [pat2; $1] } + + | COMMA parenPattern + { let commaRange = rhs parseState 1 + reportParseErrorAt commaRange (FSComp.SR.parsExpectingPatternInTuple()) + let pat1 = SynPat.Wild(commaRange.StartRange) + [$2; pat1] } + + | COMMA ends_coming_soon_or_recover + { let commaRange = rhs parseState 1 + if not $2 then reportParseErrorAt commaRange (FSComp.SR.parsExpectedPatternAfterToken ()) + let pat1 = SynPat.Wild(commaRange.StartRange) + let pat2 = SynPat.Wild(commaRange.EndRange) + [pat2; pat1] } conjParenPatternElements: | conjParenPatternElements AMP parenPattern diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index a9e1c015194..e0e999dc993 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -592,6 +592,16 @@ Neočekávaný token v definici typu. Za typem {0} se očekává =. + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 98d3cec79d8..9b090dcdb5c 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -592,6 +592,16 @@ Unerwartetes Token in Typdefinition. Nach Typ "{0}" wurde "=" erwartet. + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 9ea5c76f74c..a410c3381fd 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -592,6 +592,16 @@ Token inesperado en la definición de tipo. Se esperaba "=" después del tipo "{0}". + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 608877dac83..542a1f4fc33 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -592,6 +592,16 @@ Jeton inattendu dans la définition de type. Signe '=' attendu après le type '{0}'. + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index c616f13a22a..885462d4313 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -592,6 +592,16 @@ Token imprevisto nella definizione del tipo. Dopo il tipo '{0}' è previsto '='. + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 18b818fea07..e75546a4060 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -592,6 +592,16 @@ 型定義に予期しないトークンがあります。型 '{0}' の後には '=' が必要です。 + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index b361fa40679..0d61eacd4aa 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -592,6 +592,16 @@ 형식 정의에 예기치 않은 토큰이 있습니다. '{0}' 형식 뒤에 '='가 필요합니다. + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index e746b8f8732..32a58e4b23a 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -592,6 +592,16 @@ Nieoczekiwany token w definicji typu. Oczekiwano znaku „=” po typie „{0}”. + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 00ab6117c7a..41465827411 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -592,6 +592,16 @@ Token inesperado na definição de tipo. Esperava-se '=' após o tipo '{0}'. + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 8d68379843e..303abbe53e7 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -592,6 +592,16 @@ Неожиданный токен в определении типа. После типа "{0}" ожидается "=". + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 25de80c1025..d3e695d0686 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -592,6 +592,16 @@ Tür tanımında beklenmeyen belirteç var. '{0}' türünden sonra '=' bekleniyordu. + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index ab75c3f45f0..29db57871b0 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -592,6 +592,16 @@ 类型定义中出现意外标记。类型“{0}”后应为 "="。 + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 781002375e3..45bf1a52370 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -592,6 +592,16 @@ 型別定義中出現非預期的權杖。類型 '{0}' 之後應該要有 '='。 + + Expected a pattern after this point + Expected a pattern after this point + + + + Expecting pattern + Expecting pattern + + Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) Incomplete character literal (example: 'Q') or qualified type invocation (example: 'T.Name) diff --git a/tests/service/Common.fs b/tests/service/Common.fs index 7f2a8e56813..e19ed1f1c49 100644 --- a/tests/service/Common.fs +++ b/tests/service/Common.fs @@ -232,6 +232,11 @@ let getSingleParenInnerExpr expr = | SynModuleDecl.Expr(SynExpr.Paren(expr, _, _, _), _) -> expr | _ -> failwith "Unexpected tree" +let getLetDeclHeadPattern (moduleDecl: SynModuleDecl) = + match moduleDecl with + | SynModuleDecl.Let(_, [SynBinding(headPat = pat)], _) -> pat + | _ -> failwith "Unexpected tree" + let parseSourceCodeAndGetModule (source: string) = parseSourceCode ("test.fsx", source) |> getSingleModuleLikeDecl @@ -458,7 +463,7 @@ let coreLibAssemblyName = "mscorlib" #endif -let getRange (e: SynExpr) = e.Range +let inline getRange (node: ^T) = (^T: (member Range: range) node) let assertRange (expectedStartLine: int, expectedStartColumn: int) diff --git a/tests/service/ParserTests.fs b/tests/service/ParserTests.fs index b96083b77e7..cc4a9923ab7 100644 --- a/tests/service/ParserTests.fs +++ b/tests/service/ParserTests.fs @@ -131,9 +131,7 @@ match () with match getSingleExprInModule parseResults with | SynExpr.Match (clauses=[ SynMatchClause (pat=pat) ]) -> match pat with - | SynPat.Or - (SynPat.FromParseError (SynPat.Paren (SynPat.FromParseError (SynPat.Wild _, _), _), _), - SynPat.Named _, _, _) -> () + | SynPat.Paren(SynPat.Or(SynPat.Tuple(_, [SynPat.Named _; SynPat.Wild _], _), SynPat.Named _, _, _), _) -> () | _ -> failwith "Unexpected pattern" | _ -> failwith "Unexpected tree" @@ -185,7 +183,7 @@ let f (x, match getSingleDeclInModule parseResults with | SynModuleDecl.Let (_, [ SynBinding (headPat = SynPat.LongIdent (argPats = SynArgPats.Pats [ pat ])) ], _) -> match pat with - | SynPat.FromParseError (SynPat.Paren (SynPat.FromParseError (SynPat.Wild _, _), _), _) -> () + | SynPat.FromParseError (SynPat.Paren (SynPat.Tuple(_, [SynPat.Named _; SynPat.Wild _], _), _), _) -> () | _ -> failwith "Unexpected tree" | _ -> failwith "Unexpected tree" @@ -194,7 +192,11 @@ let assertIsBefore (f: _ -> range) (a, b) = let r2 = f b Position.posGeq r2.Start r1.End |> shouldEqual true -let checkExprOrder exprs = +let inline assertIsEmptyRange node = + let range = getRange node + Position.posEq range.Start range.End |> shouldEqual true + +let inline checkNodeOrder exprs = exprs |> List.pairwise |> List.iter (assertIsBefore getRange) @@ -220,7 +222,7 @@ let ``Expr - Tuple 01`` () = | [ SynExpr.Tuple(_, [SynExpr.ArbitraryAfterError _ as e11; SynExpr.ArbitraryAfterError _ as e12], c1, _) SynExpr.Tuple(_, [SynExpr.ArbitraryAfterError _ as e21; SynExpr.ArbitraryAfterError _ as e22; SynExpr.ArbitraryAfterError _ as e23], c2, _) SynExpr.Tuple(_, [SynExpr.ArbitraryAfterError _ as e31; SynExpr.ArbitraryAfterError _ as e32; SynExpr.ArbitraryAfterError _ as e33; SynExpr.ArbitraryAfterError _ as e34], c3, _) ] -> - [ e11; e12; e21; e22; e23; e31; e32; e33; e34 ] |> checkExprOrder + [ e11; e12; e21; e22; e23; e31; e32; e33; e34 ] |> checkNodeOrder [ c1, 1; c2, 2; c3, 3 ] |> checkRangeCountAndOrder | _ -> failwith "Unexpected tree" @@ -237,7 +239,7 @@ let ``Expr - Tuple 02`` () = | [ SynExpr.Tuple(_, [SynExpr.Const _ as e11; SynExpr.ArbitraryAfterError _ as e12], c1, _) SynExpr.Tuple(_, [SynExpr.ArbitraryAfterError _ as e21; SynExpr.Const _ as e22], c2, _) SynExpr.Tuple(_, [SynExpr.Const _ as e31; SynExpr.Const _ as e32], c3, _) ] -> - [ e11; e12; e21; e22; e31; e32 ] |> checkExprOrder + [ e11; e12; e21; e22; e31; e32 ] |> checkNodeOrder [ c1, 1; c2, 1; c3, 1 ] |> checkRangeCountAndOrder | _ -> failwith "Unexpected tree" @@ -269,7 +271,7 @@ let ``Expr - Tuple 03`` () = [ e11; e12; e13; e21; e22; e23; e31; e32; e33 e41; e42; e43; e51; e52; e53; e61; e62; e63 e71; e72; e73 ] - |> checkExprOrder + |> checkNodeOrder [ c1, 2; c2, 2; c3, 2 c4, 2; c5, 2; c6, 2 @@ -294,9 +296,7 @@ let ``Expr - Tuple 04`` () = SynExpr.ArbitraryAfterError _ as e6 SynExpr.Const _ as e7 SynExpr.ArbitraryAfterError _ as e8 ], c, _) ] -> - [ e1; e2; e3; e4; e5; e6; e7; e8 ] - |> checkExprOrder - + [ e1; e2; e3; e4; e5; e6; e7; e8 ] |> checkNodeOrder [ c, 7 ] |> checkRangeCountAndOrder | _ -> failwith "Unexpected tree" @@ -333,3 +333,138 @@ let x = 1, shouldEqual expr.Range.StartLine expr.Range.EndLine shouldEqual range.StartLine range.EndLine | _ -> failwith "Unexpected tree" + +[] +let ``Pattern - Head - Tuple 01`` () = + let parseResults = getParseResults """ +let , = () +let ,, = () +let ,,, = () +""" + let pats = getSingleModuleMemberDecls parseResults |> List.map getLetDeclHeadPattern + match pats with + | [ SynPat.Tuple(_, [SynPat.Wild _ as p11; SynPat.Wild _ as p12], _) + SynPat.Tuple(_, [SynPat.Wild _ as p21; SynPat.Wild _ as p22; SynPat.Wild _ as p23], _) + SynPat.Tuple(_, [SynPat.Wild _ as p31; SynPat.Wild _ as p32; SynPat.Wild _ as p33; SynPat.Wild _ as p34], _) ] -> + [ p11; p12; p21; p22; p23; p31; p32; p33; p34 ] |> checkNodeOrder + [ p11; p12; p21; p22; p23; p31; p32; p33; p34 ] |> List.iter assertIsEmptyRange + + | _ -> failwith "Unexpected tree" + +[] +let ``Pattern - Head - Tuple 02`` () = + let parseResults = getParseResults """ +let 1, = () +let ,1 = () +let 1,1 = () +""" + let pats = getSingleModuleMemberDecls parseResults |> List.map getLetDeclHeadPattern + match pats with + | [ SynPat.Tuple(_, [SynPat.Const _ as p11; SynPat.Wild _ as p12], _) + SynPat.Tuple(_, [SynPat.Wild _ as p21; SynPat.Const _ as p22], _) + SynPat.Tuple(_, [SynPat.Const _ as p31; SynPat.Const _ as p32], _) ] -> + [ p11; p12; p21; p22; p31; p32 ] |> checkNodeOrder + [ p12; p21 ] |> List.iter assertIsEmptyRange + + | _ -> failwith "Unexpected tree" + +[] +let ``Pattern - Head - Tuple 03`` () = + let parseResults = getParseResults """ +let 1,, = () +let ,1, = () +let ,,1 = () + +let 1,1, = () +let ,1,1 = () +let 1,,1 = () + +let 1,1,1 = () +""" + let pats = getSingleModuleMemberDecls parseResults |> List.map getLetDeclHeadPattern + match pats with + | [ SynPat.Tuple(_, [SynPat.Const _ as p11; SynPat.Wild _ as p12; SynPat.Wild _ as p13], _) + SynPat.Tuple(_, [SynPat.Wild _ as p21; SynPat.Const _ as p22; SynPat.Wild _ as p23], _) + SynPat.Tuple(_, [SynPat.Wild _ as p31; SynPat.Wild _ as p32; SynPat.Const _ as p33], _) + + SynPat.Tuple(_, [SynPat.Const _ as p41; SynPat.Const _ as p42; SynPat.Wild _ as p43], _) + SynPat.Tuple(_, [SynPat.Wild _ as p51; SynPat.Const _ as p52; SynPat.Const _ as p53], _) + SynPat.Tuple(_, [SynPat.Const _ as p61; SynPat.Wild _ as p62; SynPat.Const _ as p63], _) + + SynPat.Tuple(_, [SynPat.Const _ as p71; SynPat.Const _ as p72; SynPat.Const _ as p73], _) ] -> + [ p11; p12; p13; p21; p22; p23; p31; p32; p33 + p41; p42; p43; p51; p52; p53; p61; p62; p63 + p71; p72; p73 ] |> checkNodeOrder + [ p12; p13; p21; p23; p31; p32; p43; p51; p62 ] |> List.iter assertIsEmptyRange + + | _ -> failwith "Unexpected tree" + +let getParenPatInnerPattern pat = + match pat with + | SynPat.Paren(pat, _) -> pat + | _ -> failwith "Unexpected tree" + +[] +let ``Pattern - Paren - Tuple 01`` () = + let parseResults = getParseResults """ +let (,) = () +let (,,) = () +let (,,,) = () +""" + let pats = getSingleModuleMemberDecls parseResults |> List.map (getLetDeclHeadPattern >> getParenPatInnerPattern) + match pats with + | [ SynPat.Tuple(_, [SynPat.Wild _ as p11; SynPat.Wild _ as p12], _) + SynPat.Tuple(_, [SynPat.Wild _ as p21; SynPat.Wild _ as p22; SynPat.Wild _ as p23], _) + SynPat.Tuple(_, [SynPat.Wild _ as p31; SynPat.Wild _ as p32; SynPat.Wild _ as p33; SynPat.Wild _ as p34], _) ] -> + [ p11; p12; p21; p22; p23; p31; p32; p33; p34 ] |> checkNodeOrder + [ p11; p12; p21; p22; p23; p31; p32; p33; p34 ] |> List.iter assertIsEmptyRange + + | _ -> failwith "Unexpected tree" + +[] +let ``Pattern - Paren - Tuple 02`` () = + let parseResults = getParseResults """ +let (1,) = () +let (,1) = () +let (1,1) = () +""" + let pats = getSingleModuleMemberDecls parseResults |> List.map (getLetDeclHeadPattern >> getParenPatInnerPattern) + match pats with + | [ SynPat.Tuple(_, [SynPat.Const _ as p11; SynPat.Wild _ as p12], _) + SynPat.Tuple(_, [SynPat.Wild _ as p21; SynPat.Const _ as p22], _) + SynPat.Tuple(_, [SynPat.Const _ as p31; SynPat.Const _ as p32], _) ] -> + [ p11; p12; p21; p22; p31; p32 ] |> checkNodeOrder + [ p12; p21 ] |> List.iter assertIsEmptyRange + + | _ -> failwith "Unexpected tree" + +[] +let ``Pattern - Paren - Tuple 03`` () = + let parseResults = getParseResults """ +let (1,,) = () +let (,1,) = () +let (,,1) = () + +let (1,1,) = () +let (,1,1) = () +let (1,,1) = () + +let (1,1,1) = () +""" + let pats = getSingleModuleMemberDecls parseResults |> List.map (getLetDeclHeadPattern >> getParenPatInnerPattern) + match pats with + | [ SynPat.Tuple(_, [SynPat.Const _ as p11; SynPat.Wild _ as p12; SynPat.Wild _ as p13], _) + SynPat.Tuple(_, [SynPat.Wild _ as p21; SynPat.Const _ as p22; SynPat.Wild _ as p23], _) + SynPat.Tuple(_, [SynPat.Wild _ as p31; SynPat.Wild _ as p32; SynPat.Const _ as p33], _) + + SynPat.Tuple(_, [SynPat.Const _ as p41; SynPat.Const _ as p42; SynPat.Wild _ as p43], _) + SynPat.Tuple(_, [SynPat.Wild _ as p51; SynPat.Const _ as p52; SynPat.Const _ as p53], _) + SynPat.Tuple(_, [SynPat.Const _ as p61; SynPat.Wild _ as p62; SynPat.Const _ as p63], _) + + SynPat.Tuple(_, [SynPat.Const _ as p71; SynPat.Const _ as p72; SynPat.Const _ as p73], _) ] -> + [ p11; p12; p13; p21; p22; p23; p31; p32; p33 + p41; p42; p43; p51; p52; p53; p61; p62; p63 + p71; p72; p73 ] |> checkNodeOrder + [ p12; p13; p21; p23; p31; p32; p43; p51; p62 ] |> List.iter assertIsEmptyRange + + | _ -> failwith "Unexpected tree" diff --git a/tests/service/PatternMatchCompilationTests.fs b/tests/service/PatternMatchCompilationTests.fs index 4e56b7672e2..8654a59caf3 100644 --- a/tests/service/PatternMatchCompilationTests.fs +++ b/tests/service/PatternMatchCompilationTests.fs @@ -781,6 +781,7 @@ let z as = """ dumpDiagnostics checkResults |> shouldEqual [ "(10,7--10,9): Unexpected keyword 'as' in binding" + "(10,5--10,6): Expecting pattern" "(11,10--11,12): Unexpected keyword 'as' in binding. Expected '=' or other token." "(12,9--12,11): Unexpected keyword 'as' in binding" "(13,8--13,10): Unexpected keyword 'as' in binding" @@ -801,6 +802,7 @@ let z as = "(6,4--6,10): This runtime coercion or type test from type 'a to int involves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed." "(8,29--8,30): This expression was expected to have type 'unit' but here has type 'int'" "(9,26--9,27): This expression was expected to have type 'unit' but here has type 'int'" + "(10,14--10,15): This expression was expected to have type ''a * 'b' but here has type 'int'" "(15,4--15,5): The pattern discriminator 'r' is not defined." "(15,4--15,12): Incomplete pattern matches on this expression." ] @@ -1182,6 +1184,7 @@ let as :? z = """ dumpDiagnostics checkResults |> shouldEqual [ "(10,7--10,9): Unexpected keyword 'as' in binding" + "(10,5--10,6): Expecting pattern" "(11,10--11,12): Unexpected keyword 'as' in binding. Expected '=' or other token." "(12,9--12,11): Unexpected keyword 'as' in binding" "(13,8--13,10): Unexpected keyword 'as' in binding" @@ -1209,6 +1212,8 @@ let as :? z = "(8,25--8,29): The type 'unit' does not have any proper subtypes and cannot be used as the source of a type test or runtime coercion." "(9,25--9,26): The type 'g' is not defined." "(9,22--9,26): The type 'unit' does not have any proper subtypes and cannot be used as the source of a type test or runtime coercion." + "(10,13--10,14): The type 'i' is not defined." + "(10,10--10,14): The type ''a * 'b' does not have any proper subtypes and cannot be used as the source of a type test or runtime coercion." "(16,4--16,5): The pattern discriminator 't' is not defined." "(16,14--16,15): The type 'u' is not defined." "(16,11--16,15): This runtime coercion or type test from type 'a to 'b involves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed." From 108ca7d2f39fc8faa0392a61f4bff96c03072b58 Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Thu, 29 Sep 2022 05:58:57 -0500 Subject: [PATCH 10/32] More descriptive error message for diagnostic 727 (#12832) More descriptive error message for discriminated union pattern matching. This applies when unsufficient number of tupled arguments is in the pattern. The error message then displays proposals for the missing fields. Co-authored-by: Tomas Grosup --- src/Compiler/Checking/CheckPatterns.fs | 15 ++-- src/Compiler/FSComp.txt | 2 +- src/Compiler/TypedTree/TypedTree.fs | 2 +- src/Compiler/xlf/FSComp.txt.cs.xlf | 4 +- src/Compiler/xlf/FSComp.txt.de.xlf | 4 +- src/Compiler/xlf/FSComp.txt.es.xlf | 4 +- src/Compiler/xlf/FSComp.txt.fr.xlf | 4 +- src/Compiler/xlf/FSComp.txt.it.xlf | 4 +- src/Compiler/xlf/FSComp.txt.ja.xlf | 4 +- src/Compiler/xlf/FSComp.txt.ko.xlf | 4 +- src/Compiler/xlf/FSComp.txt.pl.xlf | 4 +- src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 4 +- src/Compiler/xlf/FSComp.txt.ru.xlf | 4 +- src/Compiler/xlf/FSComp.txt.tr.xlf | 4 +- src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 4 +- src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 4 +- .../UnionCasePatternMatchingErrors.fs | 72 +++++++++++++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + tests/service/PatternMatchCompilationTests.fs | 62 ---------------- 19 files changed, 112 insertions(+), 94 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/ErrorMessages/UnionCasePatternMatchingErrors.fs diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index dccff65781b..1e9c0418a18 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -565,7 +565,7 @@ and ApplyUnionCaseOrExn m (cenv: cenv) env overallTy item = UnifyTypes cenv env m overallTy g.exn_ty CheckTyconAccessible cenv.amap m ad ecref |> ignore let mkf mArgs args = TPat_exnconstr(ecref, args, unionRanges m mArgs) - mkf, recdFieldTysOfExnDefRef ecref, [ for f in (recdFieldsOfExnDefRef ecref) -> f.Id ] + mkf, recdFieldTysOfExnDefRef ecref, [ for f in (recdFieldsOfExnDefRef ecref) -> f ] | Item.UnionCase(ucinfo, showDeprecated) -> if showDeprecated then @@ -582,7 +582,7 @@ and ApplyUnionCaseOrExn m (cenv: cenv) env overallTy item = let inst = mkTyparInst ucref.TyconRef.TyparsNoRange ucinfo.TypeInst UnifyTypes cenv env m overallTy resTy let mkf mArgs args = TPat_unioncase(ucref, ucinfo.TypeInst, args, unionRanges m mArgs) - mkf, actualTysOfUnionCaseFields inst ucref, [ for f in ucref.AllFieldsAsList -> f.Id ] + mkf, actualTysOfUnionCaseFields inst ucref, [ for f in ucref.AllFieldsAsList -> f] | _ -> invalidArg "item" "not a union case or exception reference" @@ -610,7 +610,7 @@ and TcPatLongIdentUnionCaseOrExnCase warnOnUpper cenv env ad vFlags patEnv ty (m let extraPatterns = List () for id, _, pat in pairs do - match argNames |> List.tryFindIndex (fun id2 -> id.idText = id2.idText) with + match argNames |> List.tryFindIndex (fun id2 -> id.idText = id2.Id.idText) with | None -> extraPatterns.Add pat match item with @@ -678,7 +678,14 @@ and TcPatLongIdentUnionCaseOrExnCase warnOnUpper cenv env ad vFlags patEnv ty (m elif numArgs < numArgTys then if numArgTys > 1 then // Expects tuple without enough args - errorR (Error (FSComp.SR.tcUnionCaseExpectsTupledArguments numArgTys, m)) + let printTy = NicePrint.minimalStringOfType env.DisplayEnv + let missingArgs = + argNames.[numArgs..numArgTys - 1] + |> List.map (fun id -> (if id.rfield_name_generated then "" else id.DisplayName + ": ") + printTy id.FormalType) + |> String.concat (Environment.NewLine + "\t") + |> fun s -> Environment.NewLine + "\t" + s + + errorR (Error (FSComp.SR.tcUnionCaseExpectsTupledArguments(numArgTys, numArgs, missingArgs), m)) else errorR (UnionCaseWrongArguments (env.DisplayEnv, numArgTys, numArgs, m)) args @ (List.init (numArgTys - numArgs) (fun _ -> SynPat.Wild (m.MakeSynthetic()))), extraPatterns diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 61054bba210..48b39055581 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -572,7 +572,7 @@ tcCouldNotFindIDisposable,"Couldn't find Dispose on IDisposable, or it was overl 724,tcInvalidIndexIntoActivePatternArray,"Internal error. Invalid index into active pattern array" 725,tcUnionCaseDoesNotTakeArguments,"This union case does not take arguments" 726,tcUnionCaseRequiresOneArgument,"This union case takes one argument" -727,tcUnionCaseExpectsTupledArguments,"This union case expects %d arguments in tupled form" +727,tcUnionCaseExpectsTupledArguments,"This union case expects %d arguments in tupled form, but was given %d. The missing field arguments may be any of:%s" 728,tcFieldIsNotStatic,"Field '%s' is not static" 729,tcFieldNotLiteralCannotBeUsedInPattern,"This field is not a literal and cannot be used in a pattern" 730,tcRequireVarConstRecogOrLiteral,"This is not a variable, constant, active recognizer or literal" diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs index b3fcdd6c7d5..dfdc9640a0c 100644 --- a/src/Compiler/TypedTree/TypedTree.fs +++ b/src/Compiler/TypedTree/TypedTree.fs @@ -4156,7 +4156,7 @@ type TType = (match anonInfo.TupInfo with | TupInfo.Const false -> "" | TupInfo.Const true -> "struct ") - + "{|" + String.concat "," (Seq.map2 (fun nm ty -> nm + " " + string ty + ";") anonInfo.SortedNames tinst) + ")" + "|}" + + "{|" + String.concat "," (Seq.map2 (fun nm ty -> nm + " " + string ty + ";") anonInfo.SortedNames tinst) + "|}" | TType_fun (domainTy, retTy, _) -> "(" + string domainTy + " -> " + string retTy + ")" | TType_ucase (uc, tinst) -> "ucase " + uc.CaseName + (match tinst with [] -> "" | tys -> "<" + String.concat "," (List.map string tys) + ">") | TType_var (tp, _) -> diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index e0e999dc993..04cb5e27259 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - Tento případ typu union očekává argumenty v počtu {0} v podobě řazené kolekce členů. + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 9b090dcdb5c..c7f65de13a0 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - Dieser Union-Fall erwartet {0} Argumente als Tupel. + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index a410c3381fd..c76f988d7a5 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - Este caso de unión espera {0} argumentos en forma de tupla. + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 542a1f4fc33..a89ad510309 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - Ce cas d'union attend {0} arguments basés sur des tuples + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 885462d4313..a4044cee248 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - Questo case di unione prevede {0} argomenti sotto forma di tupla + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index e75546a4060..06c51c429d4 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - この共用体ケースにはタプル形式の引数を {0} 個指定してください + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 0d61eacd4aa..f6cfde3fd98 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - 이 공용 구조체 케이스에는 튜플된 형식의 인수 {0}개가 필요합니다. + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 32a58e4b23a..95a8895c109 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - Ten przypadek unii oczekuje {0} argumentów w postaci spójnej kolekcji + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 41465827411..f8e182c61d8 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - Este caso união espera argumentos {0} na forma de tupla + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 303abbe53e7..6041cda9ec8 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - Для данного случая объединения требуется {0} аргументов в форме кортежа + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index d3e695d0686..d9738db5a5f 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - Bu birleşim durumu grup olarak tanımlanmış biçimde {0} bağımsız değişken bekliyor + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 29db57871b0..0bf4e080159 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - 此联合用例需要 {0} 个元组格式的参数 + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 45bf1a52370..24faf41e95c 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -3793,8 +3793,8 @@ - This union case expects {0} arguments in tupled form - 這個聯集需要 {0} 個 Tuple 形式的引數 + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} + This union case expects {0} arguments in tupled form, but was given {1}. The missing field arguments may be any of:{2} diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UnionCasePatternMatchingErrors.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UnionCasePatternMatchingErrors.fs new file mode 100644 index 00000000000..b64dff5176c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UnionCasePatternMatchingErrors.fs @@ -0,0 +1,72 @@ +module FSharp.Compiler.ComponentTests.ErrorMessages.UnionCasePatternMatchingErrors + +open Xunit +open FSharp.Test.Compiler + +[] +let ``Union matching error - Incomplete union fields`` () = + FSharp """ +module Tests +type U = + | B of f1:int list * {|X:string|} * f3:U * f4: (int * System.String) + +let x : U = failwith "" +let myVal = + match x with + | B -> 42""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 727, Line 9, Col 7, Line 9, Col 8, + "This union case expects 4 arguments in tupled form, but was given 0. The missing field arguments may be any of: +\tf1: int list +\t{| X: string |} +\tf3: U +\tf4: (int * System.String)") + +[] +let ``Union matching error - Named args - Name used twice`` () = + FSharp """ +module Tests +type U = + | B of field: int * int +let x : U = failwith "" +let myVal = + match x with + | B (field = x; field = z) -> let y = x + z + 1 in ()""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3175, Line 8, Col 21, Line 8, Col 26, "Union case/exception field 'field' cannot be used more than once.") + +[] +let ``Union matching error - Multiple tupled args`` () = + FSharp """ +module Tests +type U = + | B of field: int * int + +let x : U = failwith "" +let myVal = + match x with + | B x z -> let y = x + z + 1 in ()""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 727, Line 9, Col 7, Line 9, Col 12, "This union case expects 2 arguments in tupled form, but was given 0. The missing field arguments may be any of: +\tfield: int +\tint") + +[] +let ``Union matching error - Missing field`` () = + FSharp """ +module Tests +type U = + | A + | B of int * int * int + +let myVal = + match A with + | A -> 15 + | B (x, _) -> 16""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 727, Line 10, Col 7, Line 10, Col 15, "This union case expects 3 arguments in tupled form, but was given 2. The missing field arguments may be any of: +\tint") \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 4acda7d0cd7..3ef7efa769f 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -158,6 +158,7 @@ + diff --git a/tests/service/PatternMatchCompilationTests.fs b/tests/service/PatternMatchCompilationTests.fs index 8654a59caf3..7daef75bcf8 100644 --- a/tests/service/PatternMatchCompilationTests.fs +++ b/tests/service/PatternMatchCompilationTests.fs @@ -81,26 +81,6 @@ match 1, 2 with ] -[] -#if !NETCOREAPP -[] -#endif -let ``Union case 01 - Missing field`` () = - let _, checkResults = getParseAndCheckResults """ -type U = - | A - | B of int * int * int - -match A with -| B (x, _) -> let y = x + 1 in () -""" - assertHasSymbolUsages ["x"; "y"] checkResults - dumpDiagnostics checkResults |> shouldEqual [ - "(7,2--7,10): This union case expects 3 arguments in tupled form" - "(6,6--6,7): Incomplete pattern matches on this expression. For example, the value 'A' may indicate a case not covered by the pattern(s)." - ] - - [] #if !NETCOREAPP [] @@ -197,47 +177,6 @@ match A with "(6,6--6,7): Incomplete pattern matches on this expression. For example, the value 'A' may indicate a case not covered by the pattern(s)." ] - -[] -#if !NETCOREAPP -[] -#endif -let ``Union case 07 - Named args - Name used twice`` () = - let _, checkResults = getParseAndCheckResults """ -type U = - | A - | B of field: int * int - -match A with -| B (field = x; field = z) -> let y = x + z + 1 in () -""" - assertHasSymbolUsages ["x"; "y"; "z"] checkResults - dumpDiagnostics checkResults |> shouldEqual [ - "(7,16--7,21): Union case/exception field 'field' cannot be used more than once." - "(6,6--6,7): Incomplete pattern matches on this expression. For example, the value 'A' may indicate a case not covered by the pattern(s)." - ] - - -[] -#if !NETCOREAPP -[] -#endif -let ``Union case 08 - Multiple tupled args`` () = - let _, checkResults = getParseAndCheckResults """ -type U = - | A - | B of field: int * int - -match A with -| B x z -> let y = x + z + 1 in () -""" - assertHasSymbolUsages ["x"; "y"; "z"] checkResults - dumpDiagnostics checkResults |> shouldEqual [ - "(7,2--7,7): This union case expects 2 arguments in tupled form" - "(6,6--6,7): Incomplete pattern matches on this expression. For example, the value 'A' may indicate a case not covered by the pattern(s)." - ] - - [] let ``Union case 09 - Single arg`` () = let _, checkResults = getParseAndCheckResults """ @@ -249,7 +188,6 @@ match None with dumpDiagnostics checkResults |> shouldEqual [ ] - [] #if !NETCOREAPP [] From f30672421b38952abd81fb45b02097f75f50beb6 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 13:50:18 +0000 Subject: [PATCH 11/32] [main] Update dependencies from dotnet/arcade (#13992) [main] Update dependencies from dotnet/arcade - Merge branch 'main' into darc-main-e1b92d5d-2126-455c-8126-13d1289898da --- eng/Version.Details.xml | 8 ++++---- eng/common/templates/job/execute-sdl.yml | 2 +- eng/common/templates/post-build/post-build.yml | 4 ++-- global.json | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 80e7ef74b8e..1c47ca2db38 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -8,14 +8,14 @@ - + https://github.com/dotnet/arcade - ba4d2568dd2e3e7538feeaba60215f7bcb99e89c + 0213f8ad31ac8c63ad41760f02a929998abf69bb - + https://github.com/dotnet/arcade - ba4d2568dd2e3e7538feeaba60215f7bcb99e89c + 0213f8ad31ac8c63ad41760f02a929998abf69bb diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index 781a41c9404..65f87b40c66 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -34,7 +34,7 @@ jobs: - job: Run_SDL dependsOn: ${{ parameters.dependsOn }} displayName: Run SDL tool - condition: eq( ${{ parameters.enable }}, 'true') + condition: and(succeededOrFailed(), eq( ${{ parameters.enable }}, 'true')) variables: - group: DotNet-VSTS-Bot - name: AzDOProjectName diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 87fcae940cf..258ed2d1108 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -98,7 +98,7 @@ stages: jobs: - job: displayName: NuGet Validation - condition: eq( ${{ parameters.enableNugetValidation }}, 'true') + condition: and(succeededOrFailed(), eq( ${{ parameters.enableNugetValidation }}, 'true')) pool: # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: @@ -282,4 +282,4 @@ stages: -MaestroToken '$(MaestroApiAccessToken)' -WaitPublishingFinish true -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' \ No newline at end of file + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/global.json b/global.json index ed1a0361528..f79b5c3aeda 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.22473.1", - "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.22473.1" + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.22477.1", + "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.22477.1" } } From 33edc2c9c5561cfa9e440ab7bf3a6bcc85b1aeba Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 29 Sep 2022 20:14:36 +0100 Subject: [PATCH 12/32] Fix analysis of conjunctive patterns for exhaustiveness (#13020) * try to fix analysis of conjunctive patterns * add test cases Co-authored-by: Vlad Zarytovskii --- .../Checking/PatternMatchCompilation.fs | 8 +------- tests/fsharp/tests.fs | 15 +++++++++++++++ tests/fsharp/typecheck/sigs/pos1281.fs | 17 +++++++++++++++++ tests/fsharp/typecheck/sigs/pos3294.fs | 8 ++++++++ 4 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 tests/fsharp/typecheck/sigs/pos1281.fs create mode 100644 tests/fsharp/typecheck/sigs/pos3294.fs diff --git a/src/Compiler/Checking/PatternMatchCompilation.fs b/src/Compiler/Checking/PatternMatchCompilation.fs index 0b0a5e0624f..2c53c73202e 100644 --- a/src/Compiler/Checking/PatternMatchCompilation.fs +++ b/src/Compiler/Checking/PatternMatchCompilation.fs @@ -143,7 +143,6 @@ let GetSubExprOfInput g (gtps, tyargs, tinst) (SubExpr(accessf, (ve2, v2))) = // The ints record which choices taken, e.g. tuple/record fields. type Path = | PathQuery of Path * Unique - | PathConj of Path * int | PathTuple of Path * TypeInst * int | PathRecd of Path * TyconRef * TypeInst * int | PathUnionConstr of Path * UnionCaseRef * TypeInst * int @@ -154,7 +153,6 @@ type Path = let rec pathEq p1 p2 = match p1, p2 with | PathQuery(p1, n1), PathQuery(p2, n2) -> (n1 = n2) && pathEq p1 p2 - | PathConj(p1, n1), PathConj(p2, n2) -> (n1 = n2) && pathEq p1 p2 | PathTuple(p1, _, n1), PathTuple(p2, _, n2) -> (n1 = n2) && pathEq p1 p2 | PathRecd(p1, _, _, n1), PathRecd(p2, _, _, n2) -> (n1 = n2) && pathEq p1 p2 | PathUnionConstr(p1, _, _, n1), PathUnionConstr(p2, _, _, n2) -> (n1 = n2) && pathEq p1 p2 @@ -203,8 +201,6 @@ let RefuteDiscrimSet g m path discrims = let rec go path tm = match path with | PathQuery _ -> raise CannotRefute - | PathConj (p, _j) -> - go p tm | PathTuple (p, tys, j) -> let k, eCoversVals = mkOneKnown tm j tys go p (fun _ -> mkRefTupled g m k tys, eCoversVals) @@ -391,8 +387,6 @@ type Frontier = Frontier of ClauseNumber * Actives * ValMap type InvestigationPoint = Investigation of ClauseNumber * DecisionTreeTest * Path // Note: actives must be a SortedDictionary -// REVIEW: improve these data structures, though surprisingly these functions don't tend to show up -// on profiling runs let rec isMemOfActives p1 actives = match actives with | [] -> false @@ -1624,7 +1618,7 @@ let CompilePatternBasic subPats |> List.collect (fun subPat -> BindProjectionPattern (Active(inpPath, inpExpr, subPat)) activeState) | TPat_conjs(subPats, _m) -> - let newActives = List.mapi (mkSubActive (fun path j -> PathConj(path, j)) (fun _j -> inpAccess)) subPats + let newActives = List.mapi (mkSubActive (fun path _j -> path) (fun _j -> inpAccess)) subPats BindProjectionPatterns newActives activeState | TPat_range (c1, c2, m) -> diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index 44cf37b3268..a43f9b08d89 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -2586,6 +2586,21 @@ module TypecheckTests = peverify cfg "pos40.exe" exec cfg ("." ++ "pos40.exe") "" + [] + let ``sigs pos1281`` () = + let cfg = testConfig "typecheck/sigs" + // This checks that warning 25 "incomplete matches" is not triggered + fsc cfg "%s --target:exe -o:pos1281.exe --warnaserror --nowarn:26" cfg.fsc_flags ["pos1281.fs"] + peverify cfg "pos1281.exe" + exec cfg ("." ++ "pos1281.exe") "" + + [] + let ``sigs pos3294`` () = + let cfg = testConfig "typecheck/sigs" + fsc cfg "%s --target:exe -o:pos3294.exe --warnaserror" cfg.fsc_flags ["pos3294.fs"] + peverify cfg "pos3294.exe" + exec cfg ("." ++ "pos3294.exe") "" + [] let ``sigs pos23`` () = let cfg = testConfig "typecheck/sigs" diff --git a/tests/fsharp/typecheck/sigs/pos1281.fs b/tests/fsharp/typecheck/sigs/pos1281.fs new file mode 100644 index 00000000000..f2a73c07c3d --- /dev/null +++ b/tests/fsharp/typecheck/sigs/pos1281.fs @@ -0,0 +1,17 @@ +module Pos1281 + +type Cond = Foo | Bar | Baz +let (|SetV|) x _ = x + +let c = Cond.Foo + +match c with +| Baz -> + printfn "Baz" +| Foo & SetV "and" kwd +| Bar & SetV "or" kwd -> + printfn "Keyword: %s" kwd +| Baz -> failwith "wat" + +printfn "test completed" +exit 0 diff --git a/tests/fsharp/typecheck/sigs/pos3294.fs b/tests/fsharp/typecheck/sigs/pos3294.fs new file mode 100644 index 00000000000..55fc5f2631b --- /dev/null +++ b/tests/fsharp/typecheck/sigs/pos3294.fs @@ -0,0 +1,8 @@ +module Pos40 + +let f = function + | [] -> 0 + | (_ :: _) & _ -> 0 + +printfn "test completed" +exit 0 From 0ec7fb270c9c2495ad306955a4b0cc33deed66cd Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Fri, 30 Sep 2022 10:21:04 +0200 Subject: [PATCH 13/32] Compiler ignores obsolete attribute for enum cases (#13997) [] attribute for enum cases support added. --- src/Compiler/Checking/AttributeChecking.fs | 3 +- src/Compiler/Checking/CheckDeclarations.fs | 1 + .../ObsoleteAttributeCheckingTests.fs | 32 +++++++++++++++---- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs index d1d50393523..82f504865ab 100644 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -507,7 +507,8 @@ let CheckUnionCaseAttributes g (x:UnionCaseRef) m = /// Check the attributes on a record field, returning errors and warnings as data. let CheckRecdFieldAttributes g (x:RecdFieldRef) m = CheckEntityAttributes g x.TyconRef m ++ (fun () -> - CheckFSharpAttributes g x.PropertyAttribs m) + CheckFSharpAttributes g x.PropertyAttribs m) ++ (fun () -> + CheckFSharpAttributes g x.RecdField.FieldAttribs m) /// Check the attributes on an F# value, returning errors and warnings as data. let CheckValAttributes g (x:ValRef) m = diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 1081998708b..ac0080ca829 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -545,6 +545,7 @@ module TcRecdUnionAndEnumDeclarations = let TcEnumDecl cenv env parent thisTy fieldTy (SynEnumCase(attributes=Attributes synAttrs; ident= SynIdent(id,_); value=v; xmlDoc=xmldoc; range=m)) = let attrs = TcAttributes cenv env AttributeTargets.Field synAttrs + match v with | SynConst.Bytes _ | SynConst.UInt16s _ diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs index c2fa57509fc..29ea071835f 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs @@ -206,9 +206,9 @@ C.Update() |> withDiagnostics [ (Error 101, Line 9, Col 1, Line 9, Col 9, "This construct is deprecated. Use B instead") ] - + [] - let ``Obsolete attribute is taken into account when used on an enum and invocation`` () = + let ``Obsolete attribute error is taken into account when used on an enum and invocation`` () = Fsx """ open System @@ -219,15 +219,14 @@ type Color = let c = Color.Red """ - |> ignoreWarnings |> compile |> shouldFail |> withDiagnostics [ (Error 101, Line 9, Col 9, Line 9, Col 14, "This construct is deprecated. Use B instead") ] - + [] - let ``Obsolete attribute is taken into account when used on an enum entry and invocation`` () = + let ``Obsolete attribute error is taken into account when used on an enum field and invocation`` () = Fsx """ open System @@ -237,9 +236,28 @@ type Color = let c = Color.Red """ - |> ignoreWarnings |> compile - |> shouldSucceed + |> shouldFail + |> withDiagnostics [ + (Error 101, Line 8, Col 9, Line 8, Col 18, "This construct is deprecated. Use B instead") + ] + + [] + let ``Obsolete attribute warning is taken into account when used on an enum field and invocation`` () = + Fsx """ +open System + +type Color = + | [] Red = 0 + | Green = 1 + +let c = Color.Red + """ + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 8, Col 9, Line 8, Col 18, "This construct is deprecated. Use B instead") + ] [] let ``Obsolete attribute is taken into account when used on an type and use extension method`` () = From bc000c2f94262a8e1e7bfcb91cf8f2d7707b3726 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 1 Oct 2022 14:00:19 +0000 Subject: [PATCH 14/32] [main] Update dependencies from dotnet/arcade (#14000) [main] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 8 ++++---- eng/common/init-tools-native.ps1 | 1 + eng/common/templates/job/job.yml | 4 ++++ eng/common/templates/jobs/source-build.yml | 2 +- eng/common/templates/steps/generate-sbom.yml | 4 ++++ global.json | 4 ++-- 6 files changed, 16 insertions(+), 7 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1c47ca2db38..b06376f547d 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -8,14 +8,14 @@ - + https://github.com/dotnet/arcade - 0213f8ad31ac8c63ad41760f02a929998abf69bb + 60e9ab3c31d68167f8dac5b8e2c536deb12ef737 - + https://github.com/dotnet/arcade - 0213f8ad31ac8c63ad41760f02a929998abf69bb + 60e9ab3c31d68167f8dac5b8e2c536deb12ef737 diff --git a/eng/common/init-tools-native.ps1 b/eng/common/init-tools-native.ps1 index ac42f04a9d8..fbc67effc36 100644 --- a/eng/common/init-tools-native.ps1 +++ b/eng/common/init-tools-native.ps1 @@ -113,6 +113,7 @@ try { $ToolPath = Convert-Path -Path $BinPath Write-Host "Adding $ToolName to the path ($ToolPath)..." Write-Host "##vso[task.prependpath]$ToolPath" + $env:PATH = "$ToolPath;$env:PATH" $InstalledTools += @{ $ToolName = $ToolDirectory.FullName } } } diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 459f3c4fcbb..9f55d3f4666 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -25,6 +25,7 @@ parameters: enablePublishTestResults: false enablePublishUsingPipelines: false disableComponentGovernance: false + componentGovernanceIgnoreDirectories: '' mergeTestResults: false testRunTitle: '' testResultsFormat: '' @@ -146,6 +147,8 @@ jobs: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), ne(parameters.disableComponentGovernance, 'true')) }}: - task: ComponentGovernanceComponentDetection@0 continueOnError: true + inputs: + ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: @@ -223,4 +226,5 @@ jobs: parameters: PackageVersion: ${{ parameters.packageVersion}} BuildDropPath: ${{ parameters.buildDropPath }} + IgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} diff --git a/eng/common/templates/jobs/source-build.yml b/eng/common/templates/jobs/source-build.yml index 8dd2d355f22..bcd8279944b 100644 --- a/eng/common/templates/jobs/source-build.yml +++ b/eng/common/templates/jobs/source-build.yml @@ -14,7 +14,7 @@ parameters: # This is the default platform provided by Arcade, intended for use by a managed-only repo. defaultManagedPlatform: name: 'Managed' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8-20220809204800-17a4aab' + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream8-latest' # Defines the platforms on which to run build jobs. One job is created for each platform, and the # object in this array is sent to the job template as 'platform'. If no platforms are specified, diff --git a/eng/common/templates/steps/generate-sbom.yml b/eng/common/templates/steps/generate-sbom.yml index 4cea8c33187..a06373f38fa 100644 --- a/eng/common/templates/steps/generate-sbom.yml +++ b/eng/common/templates/steps/generate-sbom.yml @@ -2,12 +2,14 @@ # PackageName - The name of the package this SBOM represents. # PackageVersion - The version of the package this SBOM represents. # ManifestDirPath - The path of the directory where the generated manifest files will be placed +# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. parameters: PackageVersion: 7.0.0 BuildDropPath: '$(Build.SourcesDirectory)/artifacts' PackageName: '.NET' ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom + IgnoreDirectories: '' sbomContinueOnError: true steps: @@ -34,6 +36,8 @@ steps: BuildDropPath: ${{ parameters.buildDropPath }} PackageVersion: ${{ parameters.packageVersion }} ManifestDirPath: ${{ parameters.manifestDirPath }} + ${{ if ne(parameters.IgnoreDirectories, '') }}: + AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' - task: PublishPipelineArtifact@1 displayName: Publish SBOM manifest diff --git a/global.json b/global.json index f79b5c3aeda..91bb40453aa 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.22477.1", - "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.22477.1" + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.22480.2", + "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.22480.2" } } From a5a22bcbd8e3832385ba42cad9354cf98c153136 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 3 Oct 2022 12:56:54 +0200 Subject: [PATCH 15/32] Reflecting PR feedback for #13956 (#13989) --- src/Compiler/Service/FSharpCheckerResults.fs | 6 +++--- src/Compiler/Service/ServiceDeclarationLists.fs | 2 +- src/Compiler/Service/ServiceDeclarationLists.fsi | 2 +- src/Compiler/Service/ServiceLexing.fs | 8 +++++++- src/Compiler/Service/ServiceLexing.fsi | 2 +- ...Sharp.CompilerService.SurfaceArea.netstandard.expected | 3 --- 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index 2abbb49b4d2..70647f70d59 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -2652,9 +2652,9 @@ type FSharpCheckFileResults ToolTipText.ToolTipText [ for kw in names do - match Tokenization.FSharpKeywords.KeywordsDescriptionLookup.TryGetValue kw with - | false, _ -> () - | true, kwDescription -> + match Tokenization.FSharpKeywords.KeywordsDescriptionLookup kw with + | None -> () + | Some kwDescription -> let kwText = kw |> TaggedText.tagKeyword |> wordL |> LayoutRender.toArray let kwTip = ToolTipElementData.Create(kwText, FSharpXmlDoc.None) diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index 17f8b27213d..399a3037eac 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -39,7 +39,7 @@ type ToolTipElementData = Remarks: TaggedText[] option ParamName : string option } - static member Create(layout, xml, ?typeMapping, ?paramName, ?remarks) = + static member internal Create(layout, xml, ?typeMapping, ?paramName, ?remarks) = { MainDescription=layout; XmlDoc=xml; TypeMapping=defaultArg typeMapping []; ParamName=paramName; Remarks=remarks } /// A single data tip display element diff --git a/src/Compiler/Service/ServiceDeclarationLists.fsi b/src/Compiler/Service/ServiceDeclarationLists.fsi index b67f53da34b..5bb8dcd9173 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fsi +++ b/src/Compiler/Service/ServiceDeclarationLists.fsi @@ -31,7 +31,7 @@ type public ToolTipElementData = ParamName: string option } - static member Create: layout: TaggedText[] * xml: FSharpXmlDoc * ?typeMapping: TaggedText[] list * ?paramName: string * ?remarks: TaggedText[] -> ToolTipElementData + static member internal Create: layout: TaggedText[] * xml: FSharpXmlDoc * ?typeMapping: TaggedText[] list * ?paramName: string * ?remarks: TaggedText[] -> ToolTipElementData /// A single tool tip display element // diff --git a/src/Compiler/Service/ServiceLexing.fs b/src/Compiler/Service/ServiceLexing.fs index 6ee75eab602..80cfb38cc6c 100644 --- a/src/Compiler/Service/ServiceLexing.fs +++ b/src/Compiler/Service/ServiceLexing.fs @@ -1216,7 +1216,13 @@ module FSharpKeywords = let KeywordsWithDescription = PrettyNaming.keywordsWithDescription - let KeywordsDescriptionLookup = KeywordsWithDescription |> dict + let internal KeywordsDescriptionLookup = + let d = KeywordsWithDescription |> dict + + fun kw -> + match d.TryGetValue kw with + | false, _ -> None + | true, desc -> Some desc let KeywordNames = Lexhelp.Keywords.keywordNames diff --git a/src/Compiler/Service/ServiceLexing.fsi b/src/Compiler/Service/ServiceLexing.fsi index a53bba2669f..39b2febf315 100755 --- a/src/Compiler/Service/ServiceLexing.fsi +++ b/src/Compiler/Service/ServiceLexing.fsi @@ -345,7 +345,7 @@ module FSharpKeywords = val KeywordsWithDescription: (string * string) list /// A lookup from keywords to their descriptions - val KeywordsDescriptionLookup: System.Collections.Generic.IDictionary + val internal KeywordsDescriptionLookup: (string -> string option) /// All the keywords in the F# language val KeywordNames: string list diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index 736193358e7..6c3b9c7a42f 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -3977,7 +3977,6 @@ FSharp.Compiler.EditorServices.ToolTipElementData FSharp.Compiler.EditorServices.ToolTipElementData: Boolean Equals(FSharp.Compiler.EditorServices.ToolTipElementData) FSharp.Compiler.EditorServices.ToolTipElementData: Boolean Equals(System.Object) FSharp.Compiler.EditorServices.ToolTipElementData: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.EditorServices.ToolTipElementData: FSharp.Compiler.EditorServices.ToolTipElementData Create(FSharp.Compiler.Text.TaggedText[], FSharp.Compiler.Symbols.FSharpXmlDoc, Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Text.TaggedText[]]], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.TaggedText[]]) FSharp.Compiler.EditorServices.ToolTipElementData: FSharp.Compiler.Symbols.FSharpXmlDoc XmlDoc FSharp.Compiler.EditorServices.ToolTipElementData: FSharp.Compiler.Symbols.FSharpXmlDoc get_XmlDoc() FSharp.Compiler.EditorServices.ToolTipElementData: FSharp.Compiler.Text.TaggedText[] MainDescription @@ -9901,8 +9900,6 @@ FSharp.Compiler.Tokenization.FSharpKeywords: Microsoft.FSharp.Collections.FSharp FSharp.Compiler.Tokenization.FSharpKeywords: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_KeywordNames() FSharp.Compiler.Tokenization.FSharpKeywords: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] KeywordsWithDescription FSharp.Compiler.Tokenization.FSharpKeywords: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.String,System.String]] get_KeywordsWithDescription() -FSharp.Compiler.Tokenization.FSharpKeywords: System.Collections.Generic.IDictionary`2[System.String,System.String] KeywordsDescriptionLookup -FSharp.Compiler.Tokenization.FSharpKeywords: System.Collections.Generic.IDictionary`2[System.String,System.String] get_KeywordsDescriptionLookup() FSharp.Compiler.Tokenization.FSharpKeywords: System.String NormalizeIdentifierBackticks(System.String) FSharp.Compiler.Tokenization.FSharpLexer FSharp.Compiler.Tokenization.FSharpLexer: Void Tokenize(FSharp.Compiler.Text.ISourceText, Microsoft.FSharp.Core.FSharpFunc`2[FSharp.Compiler.Tokenization.FSharpToken,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[System.String], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpList`1[System.String]], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Tokenization.FSharpLexerFlags], Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Collections.FSharpMap`2[System.String,System.String]], Microsoft.FSharp.Core.FSharpOption`1[System.Threading.CancellationToken]) From ca85fd8f56235631dda9f9cccdaf1e8f46d45da8 Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Mon, 3 Oct 2022 14:14:54 +0200 Subject: [PATCH 16/32] Update README.md --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3107814f512..2026df28022 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ # The F# compiler, F# core library, and F# editor tools +[![Build Status](https://dev.azure.com/dnceng-public/public/_apis/build/status/dotnet/fsharp/fsharp-ci?branchName=main)](https://dev.azure.com/dnceng-public/public/_build/latest?definitionId=90&branchName=main) +[![Help Wanted](https://img.shields.io/github/issues/dotnet/fsharp/help%20wanted?style=flat-square&color=%232EA043&label=help%20wanted)](https://github.com/dotnet/runtime/labels/help%20wanted) + You're invited to contribute to future releases of the F# compiler, core library, and tools. Development of this repository can be done on any OS supported by [.NET](https://dotnet.microsoft.com/). -You will also need the latest .NET 6 SDK installed from [here](https://dotnet.microsoft.com/download/dotnet/6.0). +You will also need the latest .NET 7 SDK installed from [here](https://dotnet.microsoft.com/download/dotnet/7.0). ## Contributing @@ -54,12 +57,6 @@ After it's finished, open `FSharp.sln` in your editor of choice. Even if you find a single-character typo, we're happy to take the change! Although the codebase can feel daunting for beginners, we and other contributors are happy to help you along. -## Build Status - -| Branch | Status | -|:------:|:------:| -|main|[![Build Status](https://dev.azure.com/dnceng/public/_apis/build/status/dotnet/fsharp/fsharp-ci?branchName=main)](https://dev.azure.com/dnceng/public/_build/latest?definitionId=496&branchName=main)| - ## Per-build NuGet packages Per-build [versions](https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-tools&view=versions&package=FSharp.Compiler.Service&protocolType=NuGet) of our NuGet packages are available via this URL: `https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json` From c208e5ca8a8c9ba864f0cfcce7153fda6eb4d718 Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Mon, 3 Oct 2022 17:16:42 +0200 Subject: [PATCH 17/32] Add SynArgPatsNamePatPairsTrivia to SynArgPats.NamePatPairs. (#14009) --- src/Compiler/Checking/CheckPatterns.fs | 6 ++--- src/Compiler/Service/ServiceParseTreeWalk.fs | 2 +- src/Compiler/Service/ServiceParsedInputOps.fs | 4 +-- src/Compiler/SyntaxTree/SyntaxTree.fs | 4 +-- src/Compiler/SyntaxTree/SyntaxTree.fsi | 2 +- src/Compiler/SyntaxTree/SyntaxTrivia.fs | 3 +++ src/Compiler/SyntaxTree/SyntaxTrivia.fsi | 8 ++++++ src/Compiler/pars.fsy | 5 +++- ...erService.SurfaceArea.netstandard.expected | 9 ++++++- tests/service/SyntaxTreeTests/PatternTests.fs | 26 ++++++++++++++++++- 10 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index 1e9c0418a18..238e3668de7 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -471,13 +471,13 @@ and TcNullPat cenv env patEnv ty m = and CheckNoArgsForLiteral args m = match args with | SynArgPats.Pats [] - | SynArgPats.NamePatPairs ([], _) -> () + | SynArgPats.NamePatPairs (pats = []) -> () | _ -> errorR (Error (FSComp.SR.tcLiteralDoesNotTakeArguments (), m)) and GetSynArgPatterns args = match args with | SynArgPats.Pats args -> args - | SynArgPats.NamePatPairs (pairs, _) -> List.map (fun (_, _, pat) -> pat) pairs + | SynArgPats.NamePatPairs (pats = pairs) -> List.map (fun (_, _, pat) -> pat) pairs and TcArgPats warnOnUpper (cenv: cenv) env vFlags patEnv args = let g = cenv.g @@ -600,7 +600,7 @@ and TcPatLongIdentUnionCaseOrExnCase warnOnUpper cenv env ad vFlags patEnv ty (m let args, extraPatternsFromNames = match args with | SynArgPats.Pats args -> args, [] - | SynArgPats.NamePatPairs (pairs, m) -> + | SynArgPats.NamePatPairs (pairs, m, _) -> // rewrite patterns from the form (name-N = pat-N; ...) to (..._, pat-N, _...) // so type T = Case of name: int * value: int // | Case(value = v) diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fs b/src/Compiler/Service/ServiceParseTreeWalk.fs index 08c89d969f9..c75b133a371 100755 --- a/src/Compiler/Service/ServiceParseTreeWalk.fs +++ b/src/Compiler/Service/ServiceParseTreeWalk.fs @@ -797,7 +797,7 @@ module SyntaxTraversal = | SynPat.LongIdent (argPats = args) -> match args with | SynArgPats.Pats ps -> ps |> List.tryPick (traversePat path) - | SynArgPats.NamePatPairs (ps, _) -> ps |> List.map (fun (_, _, pat) -> pat) |> List.tryPick (traversePat path) + | SynArgPats.NamePatPairs (pats = ps) -> ps |> List.map (fun (_, _, pat) -> pat) |> List.tryPick (traversePat path) | SynPat.Typed (p, ty, _) -> match traversePat path p with | None -> traverseSynType path ty diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs index 6b6a1c906f0..ab24bcb5a44 100644 --- a/src/Compiler/Service/ServiceParsedInputOps.fs +++ b/src/Compiler/Service/ServiceParsedInputOps.fs @@ -556,7 +556,7 @@ module ParsedInput = let (|ConstructorPats|) pats = match pats with | SynArgPats.Pats ps -> ps - | SynArgPats.NamePatPairs (xs, _) -> List.map (fun (_, _, pat) -> pat) xs + | SynArgPats.NamePatPairs (pats = xs) -> List.map (fun (_, _, pat) -> pat) xs /// A recursive pattern that collect all sequential expressions to avoid StackOverflowException let rec (|Sequentials|_|) expr = @@ -1566,7 +1566,7 @@ module ParsedInput = let (|ConstructorPats|) pats = match pats with | SynArgPats.Pats ps -> ps - | SynArgPats.NamePatPairs (xs, _) -> List.map (fun (_, _, pat) -> pat) xs + | SynArgPats.NamePatPairs (pats = xs) -> List.map (fun (_, _, pat) -> pat) xs /// Returns all `Ident`s and `LongIdent`s found in an untyped AST. let getLongIdents (parsedInput: ParsedInput) : IDictionary = diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index 1845f463540..11c0c28375b 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -886,12 +886,12 @@ type SynSimplePats = type SynArgPats = | Pats of pats: SynPat list - | NamePatPairs of pats: (Ident * range * SynPat) list * range: range + | NamePatPairs of pats: (Ident * range * SynPat) list * range: range * trivia: SynArgPatsNamePatPairsTrivia member x.Patterns = match x with | Pats pats -> pats - | NamePatPairs (pats, _) -> pats |> List.map (fun (_, _, pat) -> pat) + | NamePatPairs (pats = pats) -> pats |> List.map (fun (_, _, pat) -> pat) [] type SynPat = diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index b1538eaa489..2a34ba55c46 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -1024,7 +1024,7 @@ type SynSimplePats = type SynArgPats = | Pats of pats: SynPat list - | NamePatPairs of pats: (Ident * range * SynPat) list * range: range + | NamePatPairs of pats: (Ident * range * SynPat) list * range: range * trivia: SynArgPatsNamePatPairsTrivia member Patterns: SynPat list diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs index 1b03d20b615..5f500caec88 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs @@ -257,3 +257,6 @@ type SynMemberGetSetTrivia = AndKeyword: range option SetKeyword: range option } + +[] +type SynArgPatsNamePatPairsTrivia = { ParenRange: range } diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi index fbdf8ecf30e..3cac74f9026 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi @@ -365,3 +365,11 @@ type SynMemberGetSetTrivia = /// The syntax range of the `set` keyword SetKeyword: range option } + +/// Represents additional information for SynArgPats.NamePatPairs +[] +type SynArgPatsNamePatPairsTrivia = + { + /// The syntax range from the beginning of the `(` token till the end of the `)` token. + ParenRange: range + } diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 6e194678018..63dba4eb2cb 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -3237,7 +3237,10 @@ constrPattern: atomicPatsOrNamePatPairs: | LPAREN namePatPairs rparen - { SynArgPats.NamePatPairs $2, snd $2 } + { let mParen = rhs2 parseState 1 3 + let pats, m = $2 + let trivia = { ParenRange = mParen } + SynArgPats.NamePatPairs(pats, m, trivia), snd $2 } | atomicPatterns { let mParsed = rhs parseState 1 diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index 6c3b9c7a42f..4bb3025a106 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -5829,6 +5829,8 @@ FSharp.Compiler.Syntax.SynArgInfo: Microsoft.FSharp.Core.FSharpOption`1[FSharp.C FSharp.Compiler.Syntax.SynArgInfo: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident] ident FSharp.Compiler.Syntax.SynArgInfo: System.String ToString() FSharp.Compiler.Syntax.SynArgPats +FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia get_trivia() +FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia trivia FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynArgPats+NamePatPairs: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]] get_pats() @@ -5841,7 +5843,7 @@ FSharp.Compiler.Syntax.SynArgPats: Boolean IsNamePatPairs FSharp.Compiler.Syntax.SynArgPats: Boolean IsPats FSharp.Compiler.Syntax.SynArgPats: Boolean get_IsNamePatPairs() FSharp.Compiler.Syntax.SynArgPats: Boolean get_IsPats() -FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewNamePatPairs(Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]], FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewNamePatPairs(Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[FSharp.Compiler.Syntax.Ident,FSharp.Compiler.Text.Range,FSharp.Compiler.Syntax.SynPat]], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia) FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats NewPats(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynPat]) FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats+NamePatPairs FSharp.Compiler.Syntax.SynArgPats: FSharp.Compiler.Syntax.SynArgPats+Pats @@ -9395,6 +9397,11 @@ FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia: Microsoft.FSharp.Collecti FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTrivia.ConditionalDirectiveTrivia] get_ConditionalDirectives() FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia: System.String ToString() FSharp.Compiler.SyntaxTrivia.ParsedSigFileInputTrivia: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTrivia.ConditionalDirectiveTrivia], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTrivia.CommentTrivia]) +FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia +FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia: FSharp.Compiler.Text.Range ParenRange +FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia: FSharp.Compiler.Text.Range get_ParenRange() +FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia: System.String ToString() +FSharp.Compiler.SyntaxTrivia.SynArgPatsNamePatPairsTrivia: Void .ctor(FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTrivia.SynBindingTrivia FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: FSharp.Compiler.SyntaxTrivia.SynBindingTrivia Zero FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: FSharp.Compiler.SyntaxTrivia.SynBindingTrivia get_Zero() diff --git a/tests/service/SyntaxTreeTests/PatternTests.fs b/tests/service/SyntaxTreeTests/PatternTests.fs index 61a511dc88a..72b10da7790 100644 --- a/tests/service/SyntaxTreeTests/PatternTests.fs +++ b/tests/service/SyntaxTreeTests/PatternTests.fs @@ -97,4 +97,28 @@ match x with ) ]) ])) -> Assert.AreEqual("op_ColonColon", opColonColonIdent.idText) - | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" \ No newline at end of file + | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" + +[] +let ``Parentheses of SynArgPats.NamePatPairs`` () = + let parseResults = + getParseResults + """ +match data with +| OnePartData( // foo + part1 = p1 + (* bar *) ) -> p1 +| _ -> failwith "todo" +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Expr( + expr = SynExpr.Match(clauses = [ + SynMatchClause(pat = SynPat.LongIdent(argPats = SynArgPats.NamePatPairs(trivia = trivia))) + _ + ]) + ) + ]) ])) -> + assertRange (3, 13) (5, 13) trivia.ParenRange + | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" From a312dc6b134a3bd0c8fe12d8f4f0d807aa985cac Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 3 Oct 2022 18:43:36 +0200 Subject: [PATCH 18/32] Infer isreadonly from structs ("readonly struct" in C#) to avoid struct-copies just like we do with readonly methods (#13999) Method on a readonly struct (instance or extension) will avoid a defensive copy of the struct, just like it was already done with readonly methods. This is done especially to play well with C# defined "readonly struct" --- src/Compiler/Checking/infos.fs | 18 +- .../CompilerOptions/fsc/warn.fs | 12 ++ .../StructDefensiveCopy.fs | 158 ++++++++++++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + .../fsc/warn/nowarn_readonlystruct.fs | 9 + .../CompilerOptions/fsc/warn/warn_level5.fs | 12 +- 6 files changed, 203 insertions(+), 7 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/StructDefensiveCopy/StructDefensiveCopy.fs create mode 100644 tests/FSharp.Compiler.ComponentTests/resources/tests/CompilerOptions/fsc/warn/nowarn_readonlystruct.fs diff --git a/src/Compiler/Checking/infos.fs b/src/Compiler/Checking/infos.fs index 1c0612eb611..1dc35e9ab09 100644 --- a/src/Compiler/Checking/infos.fs +++ b/src/Compiler/Checking/infos.fs @@ -438,6 +438,11 @@ type ILTypeInfo = member x.IsValueType = x.RawMetadata.IsStructOrEnum + /// Indicates if the type is marked with the [] attribute. + member x.IsReadOnly (g: TcGlobals) = + x.RawMetadata.CustomAttrs + |> TryFindILAttribute g.attrib_IsReadOnlyAttribute + member x.Instantiate inst = let (ILTypeInfo(g, ty, tref, tdef)) = x ILTypeInfo(g, instType inst ty, tref, tdef) @@ -993,15 +998,22 @@ type MethInfo = member x.IsStruct = isStructTy x.TcGlobals x.ApparentEnclosingType - /// Indicates if this method is read-only; usually by the [] attribute. + member x.IsOnReadOnlyType = + let g = x.TcGlobals + let typeInfo = ILTypeInfo.FromType g x.ApparentEnclosingType + typeInfo.IsReadOnly g + + /// Indicates if this method is read-only; usually by the [] attribute on method or struct level. /// Must be an instance method. /// Receiver must be a struct type. member x.IsReadOnly = - // Perf Review: Is there a way we can cache this result? + // Perf Review: Is there a way we can cache this result? + x.IsInstance && x.IsStruct && match x with - | ILMeth (g, ilMethInfo, _) -> ilMethInfo.IsReadOnly g + | ILMeth (g, ilMethInfo, _) -> + ilMethInfo.IsReadOnly g || x.IsOnReadOnlyType | FSMeth _ -> false // F# defined methods not supported yet. Must be a language feature. | _ -> false diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/warn.fs b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/warn.fs index 1ba362eb86a..4e98ff92545 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/warn.fs +++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/warn.fs @@ -70,6 +70,18 @@ module TestCompilerWarningLevel = |> withDiagnosticMessageMatches "The value has been copied to ensure the original is not mutated by this operation or because the copy is implicit when returning a struct from a member and another member is then accessed$" |> ignore +#if NETSTANDARD +// This test works with KeyValuePair, which is not a 'readonly struct' in net472 + [] + let ``no error 52 with readonly struct`` compilation = + compilation + |> asExe + |> withOptions ["--warn:5"; "--warnaserror:52"] + |> compile + |> shouldSucceed + |> ignore +#endif + [] let ``warn_level6_fs --warn:6`` compilation = compilation diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/StructDefensiveCopy/StructDefensiveCopy.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/StructDefensiveCopy/StructDefensiveCopy.fs new file mode 100644 index 00000000000..fe7f88ff74a --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/StructDefensiveCopy/StructDefensiveCopy.fs @@ -0,0 +1,158 @@ +module FSharp.Compiler.ComponentTests.EmittedIL.StructDefensiveCopy + +open Xunit +open System.IO +open FSharp.Test +open FSharp.Test.Compiler + +let verifyKeyValuePairInstanceMethodCall expectedIl = + FSharp """ +module StructUnion01 +open System.Runtime.CompilerServices +open System.Collections.Generic + +let doWork(kvp1:inref>) = + kvp1.ToString() + """ + |> ignoreWarnings + |> compile + |> shouldSucceed + |> verifyIL expectedIl + +#if NETSTANDARD +// KeyValuePair defined as a readonly struct (in C#) +[] +let ``Defensive copy can be skipped on read-only structs``() = + verifyKeyValuePairInstanceMethodCall [""" .method public static string doWork([in] valuetype [runtime]System.Collections.Generic.KeyValuePair`2& kvp1) cil managed + { + .param [1] + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: constrained. valuetype [runtime]System.Collections.Generic.KeyValuePair`2 + IL_0007: callvirt instance string [runtime]System.Object::ToString() + IL_000c: ret + } + +} """] + +#else +// KeyValuePair just a regular struct. Notice the "ldobj" instruction +[] +let ``Non readonly struct needs a defensive copy``() = + verifyKeyValuePairInstanceMethodCall [""" .method public static string doWork([in] valuetype [runtime]System.Collections.Generic.KeyValuePair`2& kvp1) cil managed + { + .param [1] + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype [runtime]System.Collections.Generic.KeyValuePair`2 V_0) + IL_0000: ldarg.0 + IL_0001: ldobj valuetype [runtime]System.Collections.Generic.KeyValuePair`2 + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: constrained. valuetype [runtime]System.Collections.Generic.KeyValuePair`2 + IL_000f: callvirt instance string [runtime]System.Object::ToString() + IL_0014: ret + } """] +#endif + +let verifyDateTimeExtensionMethodCall expectedIl = + FSharp """ +module DateTimeExtensionMethod + +open System +open System.Collections.Generic +open System.Runtime.CompilerServices + +[] +type DateTimeExtensions = + [] + static member PrintDate(d: inref) = d.ToString() + +let doWork(dt:inref) = + dt.PrintDate() + """ + |> ignoreWarnings + |> compile + |> shouldSucceed + |> verifyIL expectedIl + +#if NETSTANDARD +// DateTime defined as a readonly struct (in C#) +[] +let ``Defensive copy can be skipped for extension methods on read-only structs``() = + verifyDateTimeExtensionMethodCall [""" .method public static string doWork([in] valuetype [runtime]System.DateTime& dt) cil managed + { + .param [1] + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: constrained. [runtime]System.DateTime + IL_0007: callvirt instance string [runtime]System.Object::ToString() + IL_000c: ret + } """] + +#else +// DateTime just a regular struct. Notice the "ldobj" instruction +[] +let ``Non readonly struct needs a defensive copy when its extension method is called``() = + verifyDateTimeExtensionMethodCall [""" .method public static string doWork([in] valuetype [runtime]System.DateTime& dt) cil managed + { + .param [1] + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 3 + .locals init (valuetype [runtime]System.DateTime& V_0, + valuetype [runtime]System.DateTime V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: ldobj [runtime]System.DateTime + IL_0008: stloc.1 + IL_0009: ldloca.s V_1 + IL_000b: constrained. [runtime]System.DateTime + IL_0011: callvirt instance string [runtime]System.Object::ToString() + IL_0016: ret + } """] +#endif + + +#if NETSTANDARD +[] +#endif +let ``Csharp extension method on a readonly struct does not need defensive copy``() = + let csLib = + CSharp """ +using System; +public static class DateTimeExtensionMethod +{ + public static string CustomPrintDate(this in DateTime d) + { + return d.Date.ToShortDateString(); + } +}""" |> withName "CsLib" + + FSharp """ +module DateTimeDefinedInCsharpUsage +open System +let doWork(dt:inref) = + dt.CustomPrintDate() + """ + |> withReferences [csLib] + |> ignoreWarnings + |> compile + |> shouldSucceed + |> verifyIL [""" .method public static string doWork([in] valuetype [runtime]System.DateTime& dt) cil managed + { + .param [1] + .custom instance void [runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call string [CsLib]DateTimeExtensionMethod::CustomPrintDate(valuetype [runtime]System.DateTime&) + IL_0006: ret + } """] + diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 3ef7efa769f..0b5e005d7b7 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -134,6 +134,7 @@ + diff --git a/tests/FSharp.Compiler.ComponentTests/resources/tests/CompilerOptions/fsc/warn/nowarn_readonlystruct.fs b/tests/FSharp.Compiler.ComponentTests/resources/tests/CompilerOptions/fsc/warn/nowarn_readonlystruct.fs new file mode 100644 index 00000000000..2a4f0152709 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/resources/tests/CompilerOptions/fsc/warn/nowarn_readonlystruct.fs @@ -0,0 +1,9 @@ +// #Regression #NoMT #CompilerOptions +// See DevDiv:364238 +open System.Collections.Generic + +let x : IEnumerator> = failwith "" +printfn "%A" x.Current.Key // no defensive copy needed, because KeyValuePair is a "readonly struct" + +let y : list> = failwith "" // KeyValuePair +printfn "%A" y.[0].Key // no defensive copy needed, because KeyValuePair is a "readonly struct" diff --git a/tests/FSharp.Compiler.ComponentTests/resources/tests/CompilerOptions/fsc/warn/warn_level5.fs b/tests/FSharp.Compiler.ComponentTests/resources/tests/CompilerOptions/fsc/warn/warn_level5.fs index d33dfcf9eec..2b6115e5718 100644 --- a/tests/FSharp.Compiler.ComponentTests/resources/tests/CompilerOptions/fsc/warn/warn_level5.fs +++ b/tests/FSharp.Compiler.ComponentTests/resources/tests/CompilerOptions/fsc/warn/warn_level5.fs @@ -2,8 +2,12 @@ // See DevDiv:364238 open System.Collections.Generic -let x : IEnumerator> = failwith "" -printfn "%A" x.Current.Key // defensive copy +[] +type NonReadOnlyStruct= + member val Property = "" with get, set -let y : list> = failwith "" -printfn "%A" y.[0].Key // defensive copy +let x : IEnumerator = failwith "" +printfn "%A" x.Current.Property // defensive copy + +let y : list = failwith "" // KeyValuePair +printfn "%A" y.[0].Property // defensive copy From 30b3a8fa53bf48da2b79492cddd98b4d219336a3 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 4 Oct 2022 12:36:32 +0200 Subject: [PATCH 19/32] First steps towards reviving CodeLens --- .../CodeLens/CodeLensProvider.fs | 79 +++++++++---------- .../CodeLens/FSharpCodeLensService.fs | 4 +- 2 files changed, 41 insertions(+), 42 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/CodeLens/CodeLensProvider.fs b/vsintegration/src/FSharp.Editor/CodeLens/CodeLensProvider.fs index 8d3be2fcf35..7c015abad27 100644 --- a/vsintegration/src/FSharp.Editor/CodeLens/CodeLensProvider.fs +++ b/vsintegration/src/FSharp.Editor/CodeLens/CodeLensProvider.fs @@ -28,51 +28,43 @@ type internal CodeLensProvider settings: EditorOptions ) = - let lineLensProvider = ResizeArray() + let tryGetTextDocument (buffer: ITextBuffer) (factory: ITextDocumentFactoryService) = + match factory.TryGetTextDocument buffer with + | true, document -> Some document + | _ -> None + let taggers = ResizeArray() + let lineLensProviders = ResizeArray() let componentModel = Package.GetGlobalService(typeof) :?> ComponentModelHost.IComponentModel let workspace = componentModel.GetService() - /// Returns an provider for the textView if already one has been created. Else create one. - let addCodeLensProviderOnce wpfView buffer = - let res = taggers |> Seq.tryFind(fun (view, _) -> view = wpfView) - match res with - | Some (_, (tagger, _)) -> tagger - | None -> - let documentId = - lazy ( - match textDocumentFactory.TryGetTextDocument(buffer) with - | true, textDocument -> - Seq.tryHead (workspace.CurrentSolution.GetDocumentIdsWithFilePath(textDocument.FilePath)) - | _ -> None - |> Option.get - ) - - let tagger = CodeLensGeneralTagger(wpfView, buffer) - let service = FSharpCodeLensService(serviceProvider, workspace, documentId, buffer, metadataAsSource, componentModel.GetService(), typeMap, tagger, settings) - let provider = (wpfView, (tagger, service)) - wpfView.Closed.Add (fun _ -> taggers.Remove provider |> ignore) - taggers.Add((wpfView, (tagger, service))) - tagger + let tryGetCodeLensTagger wpfView buffer = + taggers + |> Seq.tryFind (fun (view, _) -> view = wpfView) + |> Option.map (fun (_, (tagger, _)) -> tagger) + |> Option.orElse + (textDocumentFactory + |> tryGetTextDocument buffer + |> Option.map (fun document -> workspace.CurrentSolution.GetDocumentIdsWithFilePath document.FilePath) + |> Option.bind Seq.tryHead + |> Option.map (fun documentId -> + let tagger = CodeLensGeneralTagger(wpfView, buffer) + let service = FSharpCodeLensService(serviceProvider, workspace, documentId, buffer, metadataAsSource, componentModel.GetService(), typeMap, tagger, settings) + let provider = (wpfView, (tagger, service)) + wpfView.Closed.Add (fun _ -> taggers.Remove provider |> ignore) + taggers.Add provider + tagger)) - /// Returns an provider for the textView if already one has been created. Else create one. - let addLineLensProviderOnce wpfView buffer = - let res = lineLensProvider |> Seq.tryFind(fun (view, _) -> view = wpfView) - match res with - | None -> - let documentId = - lazy ( - match textDocumentFactory.TryGetTextDocument(buffer) with - | true, textDocument -> - Seq.tryHead (workspace.CurrentSolution.GetDocumentIdsWithFilePath(textDocument.FilePath)) - | _ -> None - |> Option.get - ) + let addLineLensProvider wpfView buffer = + textDocumentFactory + |> tryGetTextDocument buffer + |> Option.map (fun document -> workspace.CurrentSolution.GetDocumentIdsWithFilePath(document.FilePath)) + |> Option.bind Seq.tryHead + |> Option.map (fun documentId -> let service = FSharpCodeLensService(serviceProvider, workspace, documentId, buffer, metadataAsSource, componentModel.GetService(), typeMap, LineLensDisplayService(wpfView, buffer), settings) let provider = (wpfView, service) - wpfView.Closed.Add (fun _ -> lineLensProvider.Remove provider |> ignore) - lineLensProvider.Add(provider) - | _ -> () + wpfView.Closed.Add (fun _ -> lineLensProviders.Remove provider |> ignore) + lineLensProviders.Add(provider)) [); Name("CodeLens"); Order(Before = PredefinedAdornmentLayers.Text); @@ -92,11 +84,18 @@ type internal CodeLensProvider | :? IWpfTextView as view -> view | _ -> failwith "error" - box(addCodeLensProviderOnce wpfView buffer) :?> _ + match tryGetCodeLensTagger wpfView buffer with + | Some tagger -> box tagger :?> _ + | None -> null else null interface IWpfTextViewCreationListener with override _.TextViewCreated view = if settings.CodeLens.Enabled && settings.CodeLens.ReplaceWithLineLens then - addLineLensProviderOnce view (view.TextBuffer) |> ignore \ No newline at end of file + let provider = + lineLensProviders + |> Seq.tryFind (fun (v, _) -> v = view) + + if provider.IsNone then + addLineLensProvider view (view.TextBuffer) |> ignore \ No newline at end of file diff --git a/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs b/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs index 2e18270e97e..01360f29edd 100644 --- a/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs +++ b/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs @@ -42,7 +42,7 @@ type internal FSharpCodeLensService ( serviceProvider: IServiceProvider, workspace: Workspace, - documentId: Lazy, + documentId: DocumentId, buffer: ITextBuffer, metadataAsSource: FSharpMetadataAsSourceService, classificationFormatMapService: IClassificationFormatMapService, @@ -153,7 +153,7 @@ type internal FSharpCodeLensService #if DEBUG logInfof "Rechecking code due to buffer edit!" #endif - let! document = workspace.CurrentSolution.GetDocument(documentId.Value) |> Option.ofObj + let! document = workspace.CurrentSolution.GetDocument documentId |> Option.ofObj let! parseFileResults, checkFileResults = document.GetFSharpParseAndCheckResultsAsync(nameof(FSharpUseMutationWhenValueIsMutableFixProvider)) |> liftAsync let parsedInput = parseFileResults.ParseTree #if DEBUG From 382714004f0cbfa18f25135a38f70c9c1c0860ad Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Tue, 4 Oct 2022 15:38:40 +0200 Subject: [PATCH 20/32] More DU obsolete attribute tests (#13996) --- .../ObsoleteAttributeCheckingTests.fs | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs index 29ea071835f..4c87a14d9fb 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs @@ -205,7 +205,77 @@ C.Update() |> shouldFail |> withDiagnostics [ (Error 101, Line 9, Col 1, Line 9, Col 9, "This construct is deprecated. Use B instead") - ] + ] + + [] + let ``Obsolete attribute error is taken into account when used on a struct du and invocation`` () = + Fsx """ +open System +[] +[] +type Color = + | Red + | Green + +let c = Color.Red + """ + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 101, Line 9, Col 9, Line 9, Col 14, "This construct is deprecated. Use B instead") + ] + + [] + let ``Obsolete attribute error is taken into account when used on a du and invocation`` () = + Fsx """ +open System +[] +type Color = + | Red + | Green + +let c = Color.Red + """ + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 101, Line 8, Col 9, Line 8, Col 14, "This construct is deprecated. Use B instead") + ] + + [] + let ``Obsolete attribute error is taken into account when used on a du field and invocation`` () = + Fsx """ +open System +type Color = + | [] Red + | Green + +let c = Color.Red + """ + |> ignoreWarnings + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 101, Line 7, Col 9, Line 7, Col 18, "This construct is deprecated. Use B instead") + ] + + [] + let ``Obsolete attribute warning is taken into account when used on a du field and invocation`` () = + Fsx """ +open System +type Color = + | [] Red + | Green + +let c = Color.Red + """ + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 7, Col 9, Line 7, Col 18, "This construct is deprecated. Use B instead") + ] [] let ``Obsolete attribute error is taken into account when used on an enum and invocation`` () = From eac93fe851eccfde8ce26a26791efaf14114e0f7 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 14:52:05 +0000 Subject: [PATCH 21/32] Update dependencies from https://github.com/dotnet/arcade build 20221003.1 (#14021) [main] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 8 ++++---- eng/common/cross/build-rootfs.sh | 7 ++++--- eng/common/templates/steps/source-build.yml | 6 ++++++ global.json | 4 ++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b06376f547d..a129a95dffa 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -8,14 +8,14 @@ - + https://github.com/dotnet/arcade - 60e9ab3c31d68167f8dac5b8e2c536deb12ef737 + d2d39276af2db3da7816ee2dc543e120d7e5781e - + https://github.com/dotnet/arcade - 60e9ab3c31d68167f8dac5b8e2c536deb12ef737 + d2d39276af2db3da7816ee2dc543e120d7e5781e diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index 5680980fa29..eddb4c380af 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -391,9 +391,9 @@ elif [[ "$__CodeName" == "illumos" ]]; then --with-gnu-ld --disable-nls --disable-libgomp --disable-libquadmath --disable-libssp --disable-libvtv --disable-libcilkrts --disable-libada --disable-libsanitizer \ --disable-libquadmath-support --disable-shared --enable-tls make -j "$JOBS" && make install && cd .. - BaseUrl=https://pkgsrc.joyent.com + BaseUrl=https://pkgsrc.smartos.org if [[ "$__UseMirror" == 1 ]]; then - BaseUrl=http://pkgsrc.smartos.skylime.net + BaseUrl=https://pkgsrc.smartos.skylime.net fi BaseUrl="$BaseUrl/packages/SmartOS/trunk/${__illumosArch}/All" echo "Downloading manifest" @@ -402,7 +402,8 @@ elif [[ "$__CodeName" == "illumos" ]]; then read -ra array <<<"$__IllumosPackages" for package in "${array[@]}"; do echo "Installing '$package'" - package="$(grep ">$package-[0-9]" All | sed -En 's/.*href="(.*)\.tgz".*/\1/p')" + # find last occurrence of package in listing and extract its name + package="$(sed -En '/.*href="('"$package"'-[0-9].*).tgz".*/h;$!d;g;s//\1/p' All)" echo "Resolved name '$package'" wget "$BaseUrl"/"$package".tgz ar -x "$package".tgz diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index 4ec5577d28a..a97a185a367 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -63,6 +63,11 @@ steps: targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' fi + runtimeOsArgs= + if [ '${{ parameters.platform.runtimeOS }}' != '' ]; then + runtimeOsArgs='/p:RuntimeOS=${{ parameters.platform.runtimeOS }}' + fi + publishArgs= if [ '${{ parameters.platform.skipPublishValidation }}' != 'true' ]; then publishArgs='--publish' @@ -80,6 +85,7 @@ steps: $internalRuntimeDownloadArgs \ $internalRestoreArgs \ $targetRidArgs \ + $runtimeOsArgs \ /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ /p:ArcadeBuildFromSource=true \ /p:AssetManifestFileName=$assetManifestFileName diff --git a/global.json b/global.json index 91bb40453aa..f44a501cf14 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.22480.2", - "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.22480.2" + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.22503.1", + "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.22503.1" } } From b68720d5d40362e61b2a9f7beedd6cf888dce839 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Tue, 4 Oct 2022 21:00:03 +0200 Subject: [PATCH 22/32] Warning or error is raised when consuming IL Event with an Obsolete attribute (#14006) * Check for ILEventDef custom attributes and make sure in this case the Obsolete attribute is raised * Fix formatting * Fix PR comments --- src/Compiler/Checking/AttributeChecking.fs | 3 +++ src/Compiler/Checking/AttributeChecking.fsi | 2 ++ src/Compiler/Checking/CheckExpressions.fs | 4 +++- src/Compiler/Checking/infos.fs | 6 ++++++ src/Compiler/Checking/infos.fsi | 3 +++ .../Language/ObsoleteAttributeCheckingTests.fs | 2 ++ 6 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs index 82f504865ab..de1aadfc803 100644 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -412,6 +412,9 @@ let CheckEntityAttributes g (tcref: TyconRef) m = CheckILAttributes g (isByrefLikeTyconRef g m tcref) tcref.ILTyconRawMetadata.CustomAttrs m else CheckFSharpAttributes g tcref.Attribs m + +let CheckILEventAttributes g (tcref: TyconRef) cattrs m = + CheckILAttributes g (isByrefLikeTyconRef g m tcref) cattrs m /// Check the attributes associated with a method, returning warnings and errors as data. let CheckMethInfoAttributes g m tyargsOpt (minfo: MethInfo) = diff --git a/src/Compiler/Checking/AttributeChecking.fsi b/src/Compiler/Checking/AttributeChecking.fsi index 3236d3bfdbe..622864eff4e 100644 --- a/src/Compiler/Checking/AttributeChecking.fsi +++ b/src/Compiler/Checking/AttributeChecking.fsi @@ -101,3 +101,5 @@ val IsSecurityAttribute: val IsSecurityCriticalAttribute: g: TcGlobals -> Attrib -> bool val IsAssemblyVersionAttribute: g: TcGlobals -> Attrib -> bool + +val CheckILEventAttributes: g: TcGlobals -> tcref: TyconRef -> cattrs: ILAttributes -> m: range -> OperationResult diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 1b65421daba..bd675aba272 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -9095,7 +9095,9 @@ and TcEventItemThen (cenv: cenv) overallTy env tpenv mItem mExprAndItem objDetai let (SigOfFunctionForDelegate(delInvokeMeth, delArgTys, _, _)) = GetSigOfFunctionForDelegate cenv.infoReader delTy mItem ad let objArgs = Option.toList (Option.map fst objDetails) MethInfoChecks g cenv.amap true None objArgs env.eAccessRights mItem delInvokeMeth - + + CheckILEventAttributes g einfo.DeclaringTyconRef (einfo.GetCustomAttrs()) mItem |> CommitOperationResult + // This checks for and drops the 'object' sender let argsTy = ArgsTypeOfEventInfo cenv.infoReader mItem ad einfo if not (slotSigHasVoidReturnTy (delInvokeMeth.GetSlotSig(cenv.amap, mItem))) then errorR (nonStandardEventError einfo.EventName mItem) diff --git a/src/Compiler/Checking/infos.fs b/src/Compiler/Checking/infos.fs index 1dc35e9ab09..68e844fa919 100644 --- a/src/Compiler/Checking/infos.fs +++ b/src/Compiler/Checking/infos.fs @@ -2275,6 +2275,12 @@ type EventInfo = | ProvidedEvent (_, ei, _) -> ProvidedEventInfo.TaintedGetHashCode ei #endif override x.ToString() = "event " + x.EventName + + /// Get custom attributes for events (only applicable for IL events) + member x.GetCustomAttrs() = + match x with + | ILEvent(ILEventInfo(_, ilEventDef))-> ilEventDef.CustomAttrs + | _ -> ILAttributes.Empty //------------------------------------------------------------------------- // Helpers associated with getting and comparing method signatures diff --git a/src/Compiler/Checking/infos.fsi b/src/Compiler/Checking/infos.fsi index 63a24eb6502..550c7860b34 100644 --- a/src/Compiler/Checking/infos.fsi +++ b/src/Compiler/Checking/infos.fsi @@ -1009,6 +1009,9 @@ type EventInfo = /// Get the delegate type associated with the event. member GetDelegateType: amap: ImportMap * m: range -> TType + /// Get custom attributes for events (only applicable for IL events) + member GetCustomAttrs: unit -> ILAttributes + /// An exception type used to raise an error using the old error system. /// /// Error text: "A definition to be compiled as a .NET event does not have the expected form. Only property members can be compiled as .NET events." diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs index 4c87a14d9fb..20e785370a3 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs @@ -987,6 +987,7 @@ Class.ObsoleteEvent |> ignore (Warning 44, Line 3, Col 1, Line 3, Col 20, "This construct is deprecated. Field is obsolete"); (Warning 44, Line 4, Col 1, Line 4, Col 21, "This construct is deprecated. Method is obsolete"); (Warning 44, Line 5, Col 1, Line 5, Col 23, "This construct is deprecated. Property is obsolete") + (Warning 44, Line 6, Col 1, Line 6, Col 20, "This construct is deprecated. Event is obsolete") ] [] @@ -1025,4 +1026,5 @@ Class.ObsoleteEvent |> ignore (Error 101, Line 3, Col 1, Line 3, Col 20, "This construct is deprecated. Field is obsolete"); (Error 101, Line 4, Col 1, Line 4, Col 21, "This construct is deprecated. Method is obsolete"); (Error 101, Line 5, Col 1, Line 5, Col 23, "This construct is deprecated. Property is obsolete") + (Error 101, Line 6, Col 1, Line 6, Col 20, "This construct is deprecated. Event is obsolete") ] From cc4f64158c5d086ce0dffec1da65c8c6bca3223e Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Tue, 4 Oct 2022 21:05:01 +0200 Subject: [PATCH 23/32] Added parallelization options to VS (#14022) * Added parallelization options to VS * More consistent option label --- .../LanguageService/LanguageService.fs | 33 +++++++++++++++---- .../FSharp.Editor/Options/EditorOptions.fs | 8 +++-- .../FSharp.UIResources.csproj | 15 +++++++++ ...nguageServicePerformanceOptionControl.xaml | 10 ++++++ .../FSharp.UIResources/Strings.Designer.cs | 31 +++++++++++++++-- .../src/FSharp.UIResources/Strings.resx | 9 +++++ .../src/FSharp.UIResources/xlf/Strings.cs.xlf | 15 +++++++++ .../src/FSharp.UIResources/xlf/Strings.de.xlf | 15 +++++++++ .../src/FSharp.UIResources/xlf/Strings.es.xlf | 15 +++++++++ .../src/FSharp.UIResources/xlf/Strings.fr.xlf | 15 +++++++++ .../src/FSharp.UIResources/xlf/Strings.it.xlf | 15 +++++++++ .../src/FSharp.UIResources/xlf/Strings.ja.xlf | 15 +++++++++ .../src/FSharp.UIResources/xlf/Strings.ko.xlf | 15 +++++++++ .../src/FSharp.UIResources/xlf/Strings.pl.xlf | 15 +++++++++ .../FSharp.UIResources/xlf/Strings.pt-BR.xlf | 15 +++++++++ .../src/FSharp.UIResources/xlf/Strings.ru.xlf | 15 +++++++++ .../src/FSharp.UIResources/xlf/Strings.tr.xlf | 15 +++++++++ .../xlf/Strings.zh-Hans.xlf | 15 +++++++++ .../xlf/Strings.zh-Hant.xlf | 15 +++++++++ 19 files changed, 290 insertions(+), 11 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs index 203867a6afe..ed20c78bf39 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs @@ -93,20 +93,39 @@ type internal FSharpWorkspaceServiceFactory match checkerSingleton with | Some _ -> () | _ -> - let checker = + let checker = lazy - let checker = + let editorOptions = + let editorOptions = workspace.Services.GetService() + + match box editorOptions with + | null -> None + | _ -> Some editorOptions + + let enableParallelCheckingWithSignatureFiles = + editorOptions + |> Option.map (fun options -> options.LanguageServicePerformance.EnableParallelCheckingWithSignatureFiles) + |> Option.defaultValue false + + let enableParallelReferenceResolution = + editorOptions + |> Option.map (fun options -> options.LanguageServicePerformance.EnableParallelReferenceResolution) + |> Option.defaultValue false + + let checker = FSharpChecker.Create( - projectCacheSize = 5000, // We do not care how big the cache is. VS will actually tell FCS to clear caches, so this is fine. + projectCacheSize = 5000, // We do not care how big the cache is. VS will actually tell FCS to clear caches, so this is fine. keepAllBackgroundResolutions = false, legacyReferenceResolver=LegacyMSBuildReferenceResolver.getResolver(), tryGetMetadataSnapshot = tryGetMetadataSnapshot, keepAllBackgroundSymbolUses = false, enableBackgroundItemKeyStoreAndSemanticClassification = true, - enablePartialTypeChecking = true) - checker - checkerSingleton <- Some checker - ) + enablePartialTypeChecking = true, + enableParallelCheckingWithSignatureFiles = enableParallelCheckingWithSignatureFiles, + parallelReferenceResolution = enableParallelReferenceResolution) + checker + checkerSingleton <- Some checker + ) let optionsManager = lazy diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs index 689c410b5f1..a90c32bda44 100644 --- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs +++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs @@ -63,12 +63,16 @@ type LanguageServicePerformanceOptions = { EnableInMemoryCrossProjectReferences: bool AllowStaleCompletionResults: bool TimeUntilStaleCompletion: int - ProjectCheckCacheSize: int } + ProjectCheckCacheSize: int + EnableParallelCheckingWithSignatureFiles: bool + EnableParallelReferenceResolution: bool } static member Default = { EnableInMemoryCrossProjectReferences = true AllowStaleCompletionResults = true TimeUntilStaleCompletion = 2000 // In ms, so this is 2 seconds - ProjectCheckCacheSize = 200 } + ProjectCheckCacheSize = 200 + EnableParallelCheckingWithSignatureFiles = false + EnableParallelReferenceResolution = false } [] type CodeLensOptions = diff --git a/vsintegration/src/FSharp.UIResources/FSharp.UIResources.csproj b/vsintegration/src/FSharp.UIResources/FSharp.UIResources.csproj index b11c35d2187..1dfea7e42c8 100644 --- a/vsintegration/src/FSharp.UIResources/FSharp.UIResources.csproj +++ b/vsintegration/src/FSharp.UIResources/FSharp.UIResources.csproj @@ -24,4 +24,19 @@ + + + True + True + Strings.resx + + + + + + PublicResXFileCodeGenerator + Strings.Designer.cs + + + diff --git a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml index e67690250dd..aacbd45f966 100644 --- a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml +++ b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml @@ -75,6 +75,16 @@ + + + + + + diff --git a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs index fd74fbb404f..23696b3433b 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs +++ b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs @@ -19,7 +19,7 @@ namespace Microsoft.VisualStudio.FSharp.UIResources { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Strings { @@ -177,6 +177,24 @@ public static string Enable_in_memory_cross_project_references { } } + /// + /// 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. + /// + public static string Enable_Parallel_Reference_Resolution { + get { + return ResourceManager.GetString("Enable_Parallel_Reference_Resolution", resourceCulture); + } + } + /// /// Looks up a localized string similar to Enable stale data for IntelliSense features. /// @@ -223,7 +241,7 @@ public static string Enter_Key_Rule { } /// - /// Looks up a localized string similar to Re-format indentation on paste. + /// Looks up a localized string similar to Re-format indentation on paste (Experimental). /// public static string Format_on_paste { get { @@ -267,6 +285,15 @@ public static string Outlining { } } + /// + /// Looks up a localized string similar to Parallelization (requires restart). + /// + public static string Parallelization { + get { + return ResourceManager.GetString("Parallelization", resourceCulture); + } + } + /// /// Looks up a localized string similar to Number of projects whose data is cached in memory. /// diff --git a/vsintegration/src/FSharp.UIResources/Strings.resx b/vsintegration/src/FSharp.UIResources/Strings.resx index b0ceb57d47a..eed808c6247 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.resx +++ b/vsintegration/src/FSharp.UIResources/Strings.resx @@ -237,4 +237,13 @@ Diagnostics + + Parallelization (requires restart) + + + Enable parallel type checking with signature files + + + Enable parallel reference resolution + \ No newline at end of file diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf index eb4650c57ed..ea2a1e1c217 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf @@ -47,6 +47,16 @@ Diagnostika + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance Výkon @@ -67,6 +77,11 @@ Navigační odkazy + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces Zobrazit s_ymboly v neotevřených oborech názvů diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf index 7db4ba605f3..ea3ff5af63e 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf @@ -47,6 +47,16 @@ Diagnose + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance Leistung @@ -67,6 +77,11 @@ Navigationslinks + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces S_ymbole in nicht geöffneten Namespaces anzeigen diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf index 674c69434c2..502bff48f23 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf @@ -47,6 +47,16 @@ Diagnóstico + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance Rendimiento @@ -67,6 +77,11 @@ Vínculos de navegación + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces Mostrar sím_bolos en espacios de nombres sin abrir diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf index ec9bafbe8df..b92f835f8a8 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf @@ -47,6 +47,16 @@ Diagnostics + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance Performances @@ -67,6 +77,11 @@ Liens de navigation + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces Afficher les sym_boles dans les espaces de noms non ouverts diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf index 9b2acf06d1b..477bfb6e4e7 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf @@ -47,6 +47,16 @@ Diagnostica + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance Prestazioni @@ -67,6 +77,11 @@ Collegamenti di navigazione + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces Mostra si_mboli in spazi dei nomi non aperti diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf index 8ab4c15b6e1..b81582ec376 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf @@ -47,6 +47,16 @@ 診断 + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance パフォーマンス @@ -67,6 +77,11 @@ ナビゲーション リンク + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces 開かれていない名前空間の記号を表示する(_Y) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf index 4812b0acc99..fff6f72deff 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf @@ -47,6 +47,16 @@ 진단 + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance 성능 @@ -67,6 +77,11 @@ 탐색 링크 + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces 열려 있지 않은 네임스페이스에 기호 표시(_Y) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf index c96168985ec..c9d8832b245 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf @@ -47,6 +47,16 @@ Diagnostyka + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance Wydajność @@ -67,6 +77,11 @@ Linki nawigacyjne + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces Pokaż s_ymbole w nieotwartych przestrzeniach nazw diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf index 076de7f9087..d30fdc11f79 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf @@ -47,6 +47,16 @@ Diagnóstico + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance Desempenho @@ -67,6 +77,11 @@ Links de navegação + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces Mostrar s_ímbolos em namespaces não abertos diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf index 690059925df..fb14d225f99 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf @@ -47,6 +47,16 @@ Диагностика + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance Производительность @@ -67,6 +77,11 @@ Ссылки навигации + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces По_казать символы в неоткрытых пространствах имен diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf index e05c403767a..005c16db45a 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf @@ -47,6 +47,16 @@ Tanılama + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance Performans @@ -67,6 +77,11 @@ Gezinti bağlantıları + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces Açılmamış ad alanlarında s_embolleri göster diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf index b219edc12c0..542657151fb 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf @@ -47,6 +47,16 @@ 诊断 + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance 性能 @@ -67,6 +77,11 @@ 导航链接 + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces 显示未打开的命名空间中的符号(_Y) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf index 0b6b964edda..38a5a484f58 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf @@ -47,6 +47,16 @@ 診斷 + + Enable parallel type checking with signature files + Enable parallel type checking with signature files + + + + Enable parallel reference resolution + Enable parallel reference resolution + + Performance 效能 @@ -67,6 +77,11 @@ 導覽連結 + + Parallelization (requires restart) + Parallelization (requires restart) + + Show s_ymbols in unopened namespaces 顯示未開啟之命名空間中的符號(_Y) From cadaf3f0b5256bf13f57c8c994ac71197fe2288c Mon Sep 17 00:00:00 2001 From: Petr Date: Wed, 5 Oct 2022 11:36:32 +0200 Subject: [PATCH 24/32] Fixing some rendering issues for CodeLens --- .../CodeLens/FSharpCodeLensService.fs | 28 +++++++------------ .../CodeLens/LineLensDisplayService.fs | 21 +++++--------- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs b/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs index 01360f29edd..18e0aa8098c 100644 --- a/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs +++ b/vsintegration/src/FSharp.Editor/CodeLens/FSharpCodeLensService.fs @@ -12,18 +12,12 @@ open System.Windows.Media open System.Windows.Media.Animation open Microsoft.CodeAnalysis -open Microsoft.CodeAnalysis.Editor.Shared.Extensions open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Classification open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Editor.Shared.Extensions -open FSharp.Compiler.CodeAnalysis -open FSharp.Compiler.Diagnostics -open FSharp.Compiler.EditorServices open FSharp.Compiler.Symbols open FSharp.Compiler.Syntax open FSharp.Compiler.Text -open FSharp.Compiler.Text -open FSharp.Compiler.Tokenization open Microsoft.VisualStudio.FSharp.Editor.Logging open Microsoft.VisualStudio.Shell.Interop @@ -32,10 +26,10 @@ open Microsoft.VisualStudio.Text.Classification open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Editor.Shared.Utilities -type internal CodeLens(taggedText, computed, fullTypeSignature, uiElement) = +type internal CodeLens(taggedText, computed, funcID, uiElement) = member val TaggedText: Async<(ResizeArray * FSharpNavigation) option> = taggedText member val Computed: bool = computed with get, set - member val FullTypeSignature: string = fullTypeSignature + member val FuncID: string = funcID member val UiElement: UIElement = uiElement with get, set type internal FSharpCodeLensService @@ -221,14 +215,12 @@ type internal FSharpCodeLensService match symbolUse.Symbol with | :? FSharpMemberOrFunctionOrValue as func when func.IsModuleValueOrMember || func.IsProperty -> let funcID = func.LogicalName + (func.FullType.ToString() |> hash |> string) - // Use a combination of the the function name + the hashed value of the type signature - let fullTypeSignature = func.FullType.ToString() // Try to re-use the last results if lastResults.ContainsKey funcID then // Make sure that the results are usable let inline setNewResultsAndWarnIfOverridenLocal value = setNewResultsAndWarnIfOverriden funcID value let lastTrackingSpan, codeLens as lastResult = lastResults.[funcID] - if codeLens.FullTypeSignature = fullTypeSignature then + if codeLens.FuncID = funcID then setNewResultsAndWarnIfOverridenLocal lastResult oldResults.Remove funcID |> ignore else @@ -247,7 +239,7 @@ type internal FSharpCodeLensService let res = CodeLens( Async.cache (useResults (symbolUse.DisplayContext, func, range)), false, - fullTypeSignature, + funcID, null) // The old results aren't computed at all, because the line might have changed create new results tagsToUpdate.[lastTrackingSpan] <- (newTrackingSpan, funcID, res) @@ -257,12 +249,12 @@ type internal FSharpCodeLensService else // The symbol might be completely new or has slightly changed. // We need to track this and iterate over the left entries to ensure that there isn't anything - unattachedSymbols.Add((symbolUse, func, funcID, fullTypeSignature)) + unattachedSymbols.Add(symbolUse, func, funcID) | _ -> () // In best case this works quite `covfefe` fine because often enough we change only a small part of the file and not the complete. for unattachedSymbol in unattachedSymbols do - let symbolUse, func, funcID, fullTypeSignature = unattachedSymbol + let symbolUse, func, funcID = unattachedSymbol let declarationLine, range = match visit func.DeclarationLocation.Start parsedInput with | Some range -> range.StartLine - 1, range @@ -270,7 +262,7 @@ type internal FSharpCodeLensService let test (v:KeyValuePair<_, _>) = let _, (codeLens:CodeLens) = v.Value - codeLens.FullTypeSignature = fullTypeSignature + codeLens.FuncID = funcID match oldResults |> Seq.tryFind test with | Some res -> let (trackingSpan : ITrackingSpan), (codeLens : CodeLens) = res.Value @@ -288,7 +280,7 @@ type internal FSharpCodeLensService CodeLens( Async.cache (useResults (symbolUse.DisplayContext, func, range)), false, - fullTypeSignature, + funcID, null) // The tag might be still valid but it hasn't been computed yet so create fresh results tagsToUpdate.[trackingSpan] <- (newTrackingSpan, funcID, res) @@ -303,7 +295,7 @@ type internal FSharpCodeLensService CodeLens( Async.cache (useResults (symbolUse.DisplayContext, func, range)), false, - fullTypeSignature, + funcID, null) try let declarationSpan = @@ -347,7 +339,7 @@ type internal FSharpCodeLensService sb.Begin() else #if DEBUG - logWarningf "Couldn't retrieve code lens information for %A" codeLens.FullTypeSignature + logWarningf "Couldn't retrieve code lens information for %A" codeLens.FuncID #endif () } |> (RoslynHelpers.StartAsyncSafe CancellationToken.None) "UIElement creation" diff --git a/vsintegration/src/FSharp.Editor/CodeLens/LineLensDisplayService.fs b/vsintegration/src/FSharp.Editor/CodeLens/LineLensDisplayService.fs index a34df51c722..85f0349112a 100644 --- a/vsintegration/src/FSharp.Editor/CodeLens/LineLensDisplayService.fs +++ b/vsintegration/src/FSharp.Editor/CodeLens/LineLensDisplayService.fs @@ -16,23 +16,16 @@ type internal LineLensDisplayService (view, buffer) = /// Layouts all stack panels on the line override self.LayoutUIElementOnLine _ (line:ITextViewLine) (ui:Grid) = let left, top = - match self.UiElementNeighbour.TryGetValue ui with - | true, parent -> - let left = Canvas.GetLeft parent - let top = Canvas.GetTop parent - let width = parent.ActualWidth - left + width, top - | _ -> - try - let bounds = line.GetCharacterBounds(line.Start) - line.TextRight + 5.0, bounds.Top - 1. - with e -> + try + let bounds = line.GetCharacterBounds(line.Start) + line.TextRight + 5.0, bounds.Top - 1. + with e -> #if DEBUG - logExceptionWithContext (e, "Error in layout ui element on line") + logExceptionWithContext (e, "Error in layout ui element on line") #else - ignore e + ignore e #endif - Canvas.GetLeft ui, Canvas.GetTop ui + Canvas.GetLeft ui, Canvas.GetTop ui Canvas.SetLeft(ui, left) Canvas.SetTop(ui, top) From d1bf2975ef48a14daa028cbdd874cae1aca1326d Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Wed, 5 Oct 2022 13:45:15 +0300 Subject: [PATCH 25/32] Optimize `IntrinsicFunctions.getTypeInfo`. (#13858) It became generic, allowing it to be optimized by the JIT if it gets passed a value type, and `IsDefined` was used in certain cases instead of `GetCustomAttributes. Co-authored-by: Don Syme Co-authored-by: Tomas Grosup --- src/FSharp.Core/prim-types.fs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs index eb92de29cba..0489528c062 100644 --- a/src/FSharp.Core/prim-types.fs +++ b/src/FSharp.Core/prim-types.fs @@ -601,20 +601,19 @@ namespace Microsoft.FSharp.Core // duplicated from above since we're using integers in this section let CompilationRepresentationFlags_PermitNull = 8 - let getTypeInfo (ty:Type) = - if ty.IsValueType + let private getTypeInfo<'T> = + if typeof<'T>.IsValueType then TypeNullnessSemantics_NullNever else - let mappingAttrs = ty.GetCustomAttributes(typeof, false) - if mappingAttrs.Length = 0 + if not (typeof<'T>.IsDefined(typeof, false)) then TypeNullnessSemantics_NullIsExtraValue - elif ty.Equals(typeof) then + elif typeof<'T>.Equals(typeof) then TypeNullnessSemantics_NullTrueValue - elif typeof.IsAssignableFrom(ty) then + elif typeof.IsAssignableFrom(typeof<'T>) then TypeNullnessSemantics_NullIsExtraValue - elif ty.GetCustomAttributes(typeof, false).Length > 0 then + elif typeof<'T>.IsDefined(typeof, false) then TypeNullnessSemantics_NullIsExtraValue else - let reprAttrs = ty.GetCustomAttributes(typeof, false) + let reprAttrs = typeof<'T>.GetCustomAttributes(typeof, false) if reprAttrs.Length = 0 then TypeNullnessSemantics_NullNotLiked else @@ -627,7 +626,7 @@ namespace Microsoft.FSharp.Core type TypeInfo<'T>() = // Compute an on-demand per-instantiation static field - static let info = getTypeInfo typeof<'T> + static let info = getTypeInfo<'T> // Publish the results of that computation static member TypeInfo = info From 2d86dbd731171b836a58f3c9a60c79cb049fcb13 Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Wed, 5 Oct 2022 18:11:20 +0200 Subject: [PATCH 26/32] Add SynPat.ListCons. (#14010) --- src/Compiler/Checking/CheckPatterns.fs | 5 ++++ src/Compiler/Service/ServiceParseTreeWalk.fs | 3 ++- src/Compiler/Service/ServiceParsedInputOps.fs | 6 +++-- src/Compiler/Service/ServiceXmlDocParser.fs | 1 + src/Compiler/SyntaxTree/SyntaxTree.fs | 3 +++ src/Compiler/SyntaxTree/SyntaxTree.fsi | 3 +++ src/Compiler/SyntaxTree/SyntaxTrivia.fs | 3 +++ src/Compiler/SyntaxTree/SyntaxTrivia.fsi | 8 +++++++ src/Compiler/pars.fsy | 6 +++-- ...erService.SurfaceArea.netstandard.expected | 18 ++++++++++++++ tests/service/SyntaxTreeTests/PatternTests.fs | 24 +++++++++++++++---- 11 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index 238e3668de7..70382723f92 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -289,6 +289,11 @@ and TcPat warnOnUpper (cenv: cenv) env valReprInfo vFlags (patEnv: TcPatLinearEn | SynPat.Or (pat1, pat2, m, _) -> TcPatOr warnOnUpper cenv env vFlags patEnv ty pat1 pat2 m + | SynPat.ListCons(pat1, pat2, m, trivia) -> + let longDotId = SynLongIdent((mkSynCaseName trivia.ColonColonRange opNameCons), [], [Some (FSharp.Compiler.SyntaxTrivia.IdentTrivia.OriginalNotation "::")]) + let args = SynArgPats.Pats [ SynPat.Tuple(false, [ pat1; pat2 ], m) ] + TcPatLongIdent warnOnUpper cenv env ad valReprInfo vFlags patEnv ty (longDotId, None, args, None, m) + | SynPat.Ands (pats, m) -> TcPatAnds warnOnUpper cenv env vFlags patEnv ty pats m diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fs b/src/Compiler/Service/ServiceParseTreeWalk.fs index c75b133a371..f3443fd95ff 100755 --- a/src/Compiler/Service/ServiceParseTreeWalk.fs +++ b/src/Compiler/Service/ServiceParseTreeWalk.fs @@ -789,7 +789,8 @@ module SyntaxTraversal = match p with | SynPat.Paren (p, _) -> traversePat path p | SynPat.As (p1, p2, _) - | SynPat.Or (p1, p2, _, _) -> [ p1; p2 ] |> List.tryPick (traversePat path) + | SynPat.Or (p1, p2, _, _) + | SynPat.ListCons (p1, p2, _, _) -> [ p1; p2 ] |> List.tryPick (traversePat path) | SynPat.Ands (ps, _) | SynPat.Tuple (_, ps, _) | SynPat.ArrayOrList (_, ps, _) -> ps |> List.tryPick (traversePat path) diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs index ab24bcb5a44..86d560091ea 100644 --- a/src/Compiler/Service/ServiceParsedInputOps.fs +++ b/src/Compiler/Service/ServiceParsedInputOps.fs @@ -619,7 +619,8 @@ module ParsedInput = | SynPat.As (pat1, pat2, _) -> List.tryPick walkPat [ pat1; pat2 ] | SynPat.Typed (pat, t, _) -> walkPat pat |> Option.orElseWith (fun () -> walkType t) | SynPat.Attrib (pat, Attributes attrs, _) -> walkPat pat |> Option.orElseWith (fun () -> List.tryPick walkAttribute attrs) - | SynPat.Or (pat1, pat2, _, _) -> List.tryPick walkPat [ pat1; pat2 ] + | SynPat.Or (pat1, pat2, _, _) + | SynPat.ListCons (pat1, pat2, _, _) -> List.tryPick walkPat [ pat1; pat2 ] | SynPat.LongIdent (typarDecls = typars; argPats = ConstructorPats pats; range = r) -> ifPosInRange r (fun _ -> kind) |> Option.orElseWith (fun () -> @@ -1638,7 +1639,8 @@ module ParsedInput = walkPat pat List.iter walkAttribute attrs | SynPat.As (pat1, pat2, _) - | SynPat.Or (pat1, pat2, _, _) -> List.iter walkPat [ pat1; pat2 ] + | SynPat.Or (pat1, pat2, _, _) + | SynPat.ListCons (pat1, pat2, _, _) -> List.iter walkPat [ pat1; pat2 ] | SynPat.LongIdent (longDotId = ident; typarDecls = typars; argPats = ConstructorPats pats) -> addLongIdentWithDots ident diff --git a/src/Compiler/Service/ServiceXmlDocParser.fs b/src/Compiler/Service/ServiceXmlDocParser.fs index ae9217e8a02..4a7eca7868d 100644 --- a/src/Compiler/Service/ServiceXmlDocParser.fs +++ b/src/Compiler/Service/ServiceXmlDocParser.fs @@ -25,6 +25,7 @@ module XmlDocParsing = | SynPat.Typed (pat, _type, _range) -> digNamesFrom pat | SynPat.Attrib (pat, _attrs, _range) -> digNamesFrom pat | SynPat.LongIdent(argPats = ConstructorPats pats) -> pats |> List.collect digNamesFrom + | SynPat.ListCons (p1, p2, _, _) -> List.collect digNamesFrom [ p1; p2 ] | SynPat.Tuple (_, pats, _range) -> pats |> List.collect digNamesFrom | SynPat.Paren (pat, _range) -> digNamesFrom pat | SynPat.OptionalVal (id, _) -> [ id.idText ] diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index 11c0c28375b..9412e8486ae 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -908,6 +908,8 @@ type SynPat = | Or of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatOrTrivia + | ListCons of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatListConsTrivia + | Ands of pats: SynPat list * range: range | As of lhsPat: SynPat * rhsPat: SynPat * range: range @@ -953,6 +955,7 @@ type SynPat = | SynPat.Wild (range = m) | SynPat.Named (range = m) | SynPat.Or (range = m) + | SynPat.ListCons (range = m) | SynPat.Ands (range = m) | SynPat.As (range = m) | SynPat.LongIdent (range = m) diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index 2a34ba55c46..1dfd44d2c0f 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -1050,6 +1050,9 @@ type SynPat = /// A disjunctive pattern 'pat1 | pat2' | Or of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatOrTrivia + /// A conjunctive pattern 'pat1 :: pat2' + | ListCons of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatListConsTrivia + /// A conjunctive pattern 'pat1 & pat2' | Ands of pats: SynPat list * range: range diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs index 5f500caec88..e4b58c85c00 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs @@ -122,6 +122,9 @@ type SynUnionCaseTrivia = { BarRange: range option } [] type SynPatOrTrivia = { BarRange: range } +[] +type SynPatListConsTrivia = { ColonColonRange: range } + [] type SynTypeDefnTrivia = { diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi index 3cac74f9026..3e0dea3db0b 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi @@ -199,6 +199,14 @@ type SynPatOrTrivia = BarRange: range } +/// Represents additional information for SynPat.Cons +[] +type SynPatListConsTrivia = + { + /// The syntax range of the `::` token. + ColonColonRange: range + } + /// Represents additional information for SynTypeDefn [] type SynTypeDefnTrivia = diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 63dba4eb2cb..c9dd108bf2d 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -3124,7 +3124,8 @@ headBindingPattern: SynPat.Or($1, $3, rhs2 parseState 1 3, { BarRange = mBar }) } | headBindingPattern COLON_COLON headBindingPattern - { SynPat.LongIdent (SynLongIdent(mkSynCaseName (rhs parseState 2) opNameCons, [], [ Some (IdentTrivia.OriginalNotation "::") ]), None, None, SynArgPats.Pats [SynPat.Tuple (false, [$1;$3], rhs2 parseState 1 3)], None, lhs parseState) } + { let mColonColon = rhs parseState 2 + SynPat.ListCons($1, $3, rhs2 parseState 1 3, { ColonColonRange = mColonColon }) } | tuplePatternElements %prec pat_tuple { let pats = normalizeTuplePat $1 @@ -3398,7 +3399,8 @@ parenPattern: SynPat.Attrib($2, $1, mLhs) } | parenPattern COLON_COLON parenPattern - { SynPat.LongIdent (SynLongIdent(mkSynCaseName (rhs parseState 2) opNameCons, [], [ Some (IdentTrivia.OriginalNotation "::") ]), None, None, SynArgPats.Pats [ SynPat.Tuple (false, [$1;$3], rhs2 parseState 1 3) ], None, lhs parseState) } + { let mColonColon = rhs parseState 2 + SynPat.ListCons($1, $3, rhs2 parseState 1 3, { ColonColonRange = mColonColon }) } | constrPattern { $1 } diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index 4bb3025a106..a6713fdbc26 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -8004,6 +8004,14 @@ FSharp.Compiler.Syntax.SynPat+IsInst: FSharp.Compiler.Syntax.SynType get_pat() FSharp.Compiler.Syntax.SynPat+IsInst: FSharp.Compiler.Syntax.SynType pat FSharp.Compiler.Syntax.SynPat+IsInst: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynPat+IsInst: FSharp.Compiler.Text.Range range +FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Syntax.SynPat get_lhsPat() +FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Syntax.SynPat get_rhsPat() +FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Syntax.SynPat lhsPat +FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Syntax.SynPat rhsPat +FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia get_trivia() +FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia trivia +FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Text.Range get_range() +FSharp.Compiler.Syntax.SynPat+ListCons: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynPat+LongIdent: FSharp.Compiler.Syntax.SynArgPats argPats FSharp.Compiler.Syntax.SynPat+LongIdent: FSharp.Compiler.Syntax.SynArgPats get_argPats() FSharp.Compiler.Syntax.SynPat+LongIdent: FSharp.Compiler.Syntax.SynLongIdent get_longDotId() @@ -8059,6 +8067,7 @@ FSharp.Compiler.Syntax.SynPat+Tags: Int32 DeprecatedCharRange FSharp.Compiler.Syntax.SynPat+Tags: Int32 FromParseError FSharp.Compiler.Syntax.SynPat+Tags: Int32 InstanceMember FSharp.Compiler.Syntax.SynPat+Tags: Int32 IsInst +FSharp.Compiler.Syntax.SynPat+Tags: Int32 ListCons FSharp.Compiler.Syntax.SynPat+Tags: Int32 LongIdent FSharp.Compiler.Syntax.SynPat+Tags: Int32 Named FSharp.Compiler.Syntax.SynPat+Tags: Int32 Null @@ -8093,6 +8102,7 @@ FSharp.Compiler.Syntax.SynPat: Boolean IsDeprecatedCharRange FSharp.Compiler.Syntax.SynPat: Boolean IsFromParseError FSharp.Compiler.Syntax.SynPat: Boolean IsInstanceMember FSharp.Compiler.Syntax.SynPat: Boolean IsIsInst +FSharp.Compiler.Syntax.SynPat: Boolean IsListCons FSharp.Compiler.Syntax.SynPat: Boolean IsLongIdent FSharp.Compiler.Syntax.SynPat: Boolean IsNamed FSharp.Compiler.Syntax.SynPat: Boolean IsNull @@ -8113,6 +8123,7 @@ FSharp.Compiler.Syntax.SynPat: Boolean get_IsDeprecatedCharRange() FSharp.Compiler.Syntax.SynPat: Boolean get_IsFromParseError() FSharp.Compiler.Syntax.SynPat: Boolean get_IsInstanceMember() FSharp.Compiler.Syntax.SynPat: Boolean get_IsIsInst() +FSharp.Compiler.Syntax.SynPat: Boolean get_IsListCons() FSharp.Compiler.Syntax.SynPat: Boolean get_IsLongIdent() FSharp.Compiler.Syntax.SynPat: Boolean get_IsNamed() FSharp.Compiler.Syntax.SynPat: Boolean get_IsNull() @@ -8133,6 +8144,7 @@ FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewDeprecatedCharRa FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewFromParseError(FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewInstanceMember(FSharp.Compiler.Syntax.Ident, FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewIsInst(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewListCons(FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia) FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewLongIdent(FSharp.Compiler.Syntax.SynLongIdent, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynValTyparDecls], FSharp.Compiler.Syntax.SynArgPats, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewNamed(FSharp.Compiler.Syntax.SynIdent, Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat NewNull(FSharp.Compiler.Text.Range) @@ -8153,6 +8165,7 @@ FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+DeprecatedCharRange FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+FromParseError FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+InstanceMember FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+IsInst +FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+ListCons FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+LongIdent FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+Named FSharp.Compiler.Syntax.SynPat: FSharp.Compiler.Syntax.SynPat+Null @@ -9556,6 +9569,11 @@ FSharp.Compiler.SyntaxTrivia.SynModuleSigDeclNestedModuleTrivia: Microsoft.FShar FSharp.Compiler.SyntaxTrivia.SynModuleSigDeclNestedModuleTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_ModuleKeyword() FSharp.Compiler.SyntaxTrivia.SynModuleSigDeclNestedModuleTrivia: System.String ToString() FSharp.Compiler.SyntaxTrivia.SynModuleSigDeclNestedModuleTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range]) +FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia +FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia: FSharp.Compiler.Text.Range ColonColonRange +FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia: FSharp.Compiler.Text.Range get_ColonColonRange() +FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia: System.String ToString() +FSharp.Compiler.SyntaxTrivia.SynPatListConsTrivia: Void .ctor(FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTrivia.SynPatOrTrivia FSharp.Compiler.SyntaxTrivia.SynPatOrTrivia: FSharp.Compiler.Text.Range BarRange FSharp.Compiler.SyntaxTrivia.SynPatOrTrivia: FSharp.Compiler.Text.Range get_BarRange() diff --git a/tests/service/SyntaxTreeTests/PatternTests.fs b/tests/service/SyntaxTreeTests/PatternTests.fs index 72b10da7790..c03325e6077 100644 --- a/tests/service/SyntaxTreeTests/PatternTests.fs +++ b/tests/service/SyntaxTreeTests/PatternTests.fs @@ -73,10 +73,10 @@ let (head::tail) = [ 1;2;4] match parseResults with | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ SynModuleDecl.Let( - bindings = [ SynBinding(headPat = SynPat.Paren(SynPat.LongIdent(longDotId = SynLongIdent([ opColonColonIdent ], _, [ Some (IdentTrivia.OriginalNotation "::") ])), _)) ] + bindings = [ SynBinding(headPat = SynPat.Paren(pat = SynPat.ListCons(trivia = trivia))) ] ) ]) ])) -> - Assert.AreEqual("op_ColonColon", opColonColonIdent.idText) + assertRange (2,9) (2,11) trivia.ColonColonRange | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" [] @@ -92,11 +92,11 @@ match x with | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ SynModuleDecl.Expr( expr = SynExpr.Match(clauses = [ - SynMatchClause(pat = SynPat.LongIdent(longDotId = SynLongIdent([ opColonColonIdent ], _, [ Some (IdentTrivia.OriginalNotation "::") ]))) + SynMatchClause(pat = SynPat.ListCons(trivia = trivia)) ]) ) ]) ])) -> - Assert.AreEqual("op_ColonColon", opColonColonIdent.idText) + assertRange (3, 9) (3, 11) trivia.ColonColonRange | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" [] @@ -122,3 +122,19 @@ match data with ]) ])) -> assertRange (3, 13) (5, 13) trivia.ParenRange | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" + +[] +let ``:: in head pattern`` () = + let parseResults = + getParseResults + """ +let 1 :: _ = [ 4; 5; 6 ] +""" + + match parseResults with + | ParsedInput.ImplFile(ParsedImplFileInput(contents = [ SynModuleOrNamespace(decls = [ + SynModuleDecl.Let(bindings = [ SynBinding(headPat = + SynPat.ListCons(trivia = trivia)) ]) + ]) ])) -> + assertRange (2,6) (2, 8) trivia.ColonColonRange + | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" From 88e8cb33a977d15ddf2adc2f754cf2e402b372c3 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Thu, 6 Oct 2022 10:15:00 +0200 Subject: [PATCH 27/32] Remove unused option from performance options dialogue (#14028) --- .../FSharp.Editor/Options/EditorOptions.fs | 2 -- ...nguageServicePerformanceOptionControl.xaml | 21 ------------------- .../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 --------- 17 files changed, 177 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs index a90c32bda44..b0c94ecc865 100644 --- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs +++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs @@ -63,14 +63,12 @@ type LanguageServicePerformanceOptions = { EnableInMemoryCrossProjectReferences: bool AllowStaleCompletionResults: bool TimeUntilStaleCompletion: int - ProjectCheckCacheSize: int EnableParallelCheckingWithSignatureFiles: bool EnableParallelReferenceResolution: bool } static member Default = { EnableInMemoryCrossProjectReferences = true AllowStaleCompletionResults = true TimeUntilStaleCompletion = 2000 // In ms, so this is 2 seconds - ProjectCheckCacheSize = 200 EnableParallelCheckingWithSignatureFiles = false EnableParallelReferenceResolution = false } diff --git a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml index aacbd45f966..26a38d423d5 100644 --- a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml +++ b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml @@ -23,27 +23,6 @@ IsChecked="{Binding EnableInMemoryCrossProjectReferences}" Content="{x:Static local:Strings.Enable_in_memory_cross_project_references}" ToolTip="{x:Static local:Strings.Tooltip_in_memory_cross_project_references}"/> - - - - - - diff --git a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs index 23696b3433b..2227b3e1819 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs +++ b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs @@ -294,15 +294,6 @@ public static string Parallelization { } } - /// - /// Looks up a localized string similar to Number of projects whose data is cached in memory. - /// - public static string Project_check_cache_size { - get { - return ResourceManager.GetString("Project_check_cache_size", resourceCulture); - } - } - /// /// Looks up a localized string similar to F# Project and Caching Performance Options. /// @@ -420,15 +411,6 @@ public static string Tooltip_in_memory_cross_project_references { } } - /// - /// Looks up a localized string similar to Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions.. - /// - public static string Tooltip_project_check_cache_size { - get { - return ResourceManager.GetString("Tooltip_project_check_cache_size", resourceCulture); - } - } - /// /// Looks up a localized string similar to Analyze and suggest fixes for unused values. /// diff --git a/vsintegration/src/FSharp.UIResources/Strings.resx b/vsintegration/src/FSharp.UIResources/Strings.resx index eed808c6247..9846b778ddc 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.resx +++ b/vsintegration/src/FSharp.UIResources/Strings.resx @@ -165,9 +165,6 @@ _Enable in-memory cross project references - - Number of projects whose data is cached in memory - S_how navigation links as @@ -210,9 +207,6 @@ In-memory cross-project references store project-level data in memory to allow IDE features to work across projects. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - 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 ea2a1e1c217..a2cc11c84f8 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf @@ -102,11 +102,6 @@ _Povolit odkazy mezi projekty v paměti - - Number of projects whose data is cached in memory - Počet projektů, jejichž data jsou uložená v mezipaměti - - S_how navigation links as Zo_brazit navigační odkazy jako @@ -182,11 +177,6 @@ V odkazech v paměti pro různé projekty jsou uložená data na úrovni projektů, aby mohly mezi projekty fungovat funkce IDE. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - Projektová data jsou uložená v mezipaměti pro funkce IDE. Vyšší hodnoty znamenají využití více paměti, protože je uloženo více projektů. Vyladění této hodnoty by nemělo mít vliv na malá a středně velká řešení. - - 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 ea3ff5af63e..3724e517a15 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf @@ -102,11 +102,6 @@ Proj_ektübergreifende Verweise im Arbeitsspeicher aktivieren - - Number of projects whose data is cached in memory - Anzahl von Projekten, deren Daten im Arbeitsspeicher zwischengespeichert werden - - S_how navigation links as Navigationslink_s anzeigen als @@ -182,11 +177,6 @@ Bei projektübergreifenden In-Memory-Verweisen werden Daten auf Projektebene im Arbeitsspeicher abgelegt, damit IDE-Features projektübergreifend verwendet werden können. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - Für IDE-Features werden Projektdaten zwischengespeichert. Bei höheren Werten wird mehr Arbeitsspeicher beansprucht, weil mehr Projekte zwischengespeichert werden. Die Optimierung dieses Werts besitzt keine Auswirkungen auf kleine oder mittelgroße Projektmappen. - - 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 502bff48f23..b8fe4df4030 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf @@ -102,11 +102,6 @@ _Habilitar referencias entre proyectos en memoria - - Number of projects whose data is cached in memory - Número de proyectos cuyos datos se almacenan en la memoria caché - - S_how navigation links as M_ostrar vínculos de navegación como @@ -182,11 +177,6 @@ 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. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - Los datos de proyecto se almacenan en caché para que funcionen las características del IDE. Los valores más altos utilizan más memoria porque se almacenan en caché más proyectos. El ajuste de este valor no debería afectar a soluciones de tamaño pequeño o medio. - - 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 b92f835f8a8..82a00f7f4ac 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf @@ -102,11 +102,6 @@ _Activer les références de projet croisé en mémoire - - Number of projects whose data is cached in memory - Nombre de projets dont les données sont mises en cache dans la mémoire - - S_how navigation links as Affic_her les liens de navigation en tant que @@ -182,11 +177,6 @@ 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. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - Les données de projet sont mises en cache pour les fonctionnalités de l'IDE. Les valeurs plus élevées utilisent plus de mémoire, car davantage de projets sont mis en cache. L'ajustement de cette valeur ne devrait pas affecter les petites ou moyennes solutions. - - 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 477bfb6e4e7..3f5a0bef8bb 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf @@ -102,11 +102,6 @@ _Abilita i riferimenti tra progetti in memoria - - Number of projects whose data is cached in memory - Numero di progetti i cui dati sono disponibili nella cache in memoria - - S_how navigation links as M_ostra collegamenti di navigazione come @@ -182,11 +177,6 @@ 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. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - I dati del progetto sono memorizzati nella cache per le funzionalità IDE. Con valori più elevati viene usata una maggiore quantità di memoria perché nella cache viene memorizzato un numero maggiore di progetti. La disattivazione di questo valore non dovrebbe influire su soluzioni di piccole e medie dimensioni. - - 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 b81582ec376..0476d98187d 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf @@ -102,11 +102,6 @@ メモリ内のプロジェクト間参照を有効にする(_E) - - Number of projects whose data is cached in memory - データがメモリ内にキャッシュされているプロジェクトの数 - - S_how navigation links as 次としてナビゲーション リンクを表示する(_H) @@ -182,11 +177,6 @@ メモリ内のプロジェクト間参照に、プロジェクトをまたいで IDE 機能を動作可能にするプロジェクト レベルのデータが格納されます。 - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - 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 fff6f72deff..b14183356b6 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf @@ -102,11 +102,6 @@ 메모리 내 크로스 프로젝트 참조 사용(_E) - - Number of projects whose data is cached in memory - 메모리에 데이터가 캐시된 프로젝트 수 - - S_how navigation links as 탐색 링크를 다음으로 표시(_H) @@ -182,11 +177,6 @@ 메모리 내 크로스 프로젝트 참조가 메모리에 프로젝트 수준 데이터를 저장하여 IDE 기능이 프로젝트에서 작동하도록 합니다. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - 프로젝트 데이터가 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 c9d8832b245..02fd84cb017 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf @@ -102,11 +102,6 @@ _Włącz odwołania między projektami w pamięci - - Number of projects whose data is cached in memory - Liczba projektów, które mają dane buforowane w pamięci - - S_how navigation links as P_okaż linki nawigacyjne jako @@ -182,11 +177,6 @@ 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. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - Dane projektów są buforowane na potrzeby funkcji środowiska IDE. Wyższe wartości powodują używanie większej ilości pamięci, ponieważ buforowanych jest więcej projektów. Dostrajanie tej wartości nie powinno mieć wpływu na małe ani średnie rozwiązania. - - 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 d30fdc11f79..7ca5a251c15 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf @@ -102,11 +102,6 @@ _Habilitar referências de projeto cruzado na memória - - Number of projects whose data is cached in memory - Número de projetos cujos dados estão em cache na memória - - S_how navigation links as E_xibir link de navegação como @@ -182,11 +177,6 @@ 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. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - Os dados do projeto são colocados em cache para os recursos do IDE. Os valores mais altos utilizam mais memória porque mais projetos são colocados em cache. O ajuste desses valores não deve afetar as soluções de pequeno ou médio porte. - - 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 fb14d225f99..91c8065c0ca 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf @@ -102,11 +102,6 @@ _Включить перекрестные ссылки между проектами в памяти - - Number of projects whose data is cached in memory - Число проектов, данные которых кэшируются в памяти - - S_how navigation links as П_оказать ссылки навигации как @@ -182,11 +177,6 @@ Перекрестные ссылки между проектами в памяти хранят данные уровня проекта в памяти, поэтому функции и компоненты IDE могут работать в разных проектах. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - Для функций и компонентов 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 005c16db45a..f7de45984dc 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf @@ -102,11 +102,6 @@ _Bellek içi çapraz proje başvurularını etkinleştir - - Number of projects whose data is cached in memory - Verileri bellekte önbelleğe alınan proje sayısı - - S_how navigation links as Gezinti bağlantılarını farklı _göster @@ -182,11 +177,6 @@ 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. - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - IDE özellikleri için proje verileri önbelleğe alınır. Değer yüksek olduğunda daha fazla proje önbelleğe alındığından daha fazla bellek kullanılır. Bu değerin ayarlanması küçük veya orta ölçekli çözümleri etkilememelidir. - - 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 542657151fb..7478bb60d18 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf @@ -102,11 +102,6 @@ 启用内存中跨项目引用(_E) - - Number of projects whose data is cached in memory - 内存中缓存了其数据的项目数 - - S_how navigation links as 导航链接显示方式(_H) @@ -182,11 +177,6 @@ 内存中跨项目引用将项目级数据存储在内存中,让 IDE 功能能够跨项目工作。 - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - 针对 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 38a5a484f58..255c7ee09d5 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf @@ -102,11 +102,6 @@ 允許記憶體內跨專案參考(_E) - - Number of projects whose data is cached in memory - 資料會快取到記憶體的專案數 - - S_how navigation links as 顯示導覽連結為(_H) @@ -182,11 +177,6 @@ 記憶體內跨專案參考,會在記憶體中儲存專案等級的資料,以允許 IDE 功能在各專案中皆可運作。 - - Project data is cached for IDE features. Higher values use more memory because more projects are cached. Tuning this value should not affect small or medium-sized solutions. - 專案資料會進行快取,供 IDE 功能使用。值較高時會使用較多的記憶體,這是因為會快取較多的專案數。調整此值應該不會影響中小型的解決方案。 - - Always add new line on enter 一律在按 ENTER 時新增新行 From ffdfc71669f2902be3491c2e3db4b5157064b2a7 Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Thu, 6 Oct 2022 10:46:13 +0200 Subject: [PATCH 28/32] Missing xml doc for member getset (#13841) * Extract Member tests to separate module. * Assert XML comment is present. * Remove duplicate tests. * Rename modules to contents. --- .../FSharp.Compiler.Service.Tests.fsproj | 3 + tests/service/SyntaxTreeTests/MemberTests.fs | 225 ++++++++++++++++++ tests/service/SyntaxTreeTests/TypeTests.fs | 199 +--------------- 3 files changed, 231 insertions(+), 196 deletions(-) create mode 100644 tests/service/SyntaxTreeTests/MemberTests.fs diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 19175fd7f05..99af61de377 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -101,6 +101,9 @@ SyntaxTree\MemberFlagTests.fs + + SyntaxTree\MemberTests.fs + SyntaxTree\ComputationExpressionTests.fs diff --git a/tests/service/SyntaxTreeTests/MemberTests.fs b/tests/service/SyntaxTreeTests/MemberTests.fs new file mode 100644 index 00000000000..084af4bff85 --- /dev/null +++ b/tests/service/SyntaxTreeTests/MemberTests.fs @@ -0,0 +1,225 @@ +module FSharp.Compiler.Service.Tests.SyntaxTreeTests.MemberTests + +open FSharp.Compiler.Service.Tests.Common +open FSharp.Compiler.Syntax +open FSharp.Compiler.SyntaxTrivia +open NUnit.Framework + +[] +let ``SynTypeDefn with AutoProperty contains the range of the equals sign`` () = + let parseResults = + getParseResults + """ +/// mutable class with auto-properties +type Person(name : string, age : int) = + /// Full name + member val Name = name with get, set +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types( + typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [_ ; SynMemberDefn.AutoProperty(equalsRange = mEquals)])) ] + ) + ]) ])) -> + assertRange (5, 20) (5, 21) mEquals + | _ -> Assert.Fail "Could not get valid AST" + +[] +let ``SynTypeDefn with AutoProperty contains the range of the with keyword`` () = + let parseResults = + getParseResults + """ +type Foo() = + member val AutoProperty = autoProp with get, set + member val AutoProperty2 = autoProp +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types( + typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [_ + SynMemberDefn.AutoProperty(withKeyword=Some mWith) + SynMemberDefn.AutoProperty(withKeyword=None)])) ] + ) + ]) ])) -> + assertRange (3, 39) (3, 43) mWith + | _ -> Assert.Fail "Could not get valid AST" + +[] +let ``SynTypeDefn with AbstractSlot contains the range of the with keyword`` () = + let parseResults = + getParseResults + """ +type Foo() = + abstract member Bar : int with get,set +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types( + typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [_ + SynMemberDefn.AbstractSlot(slotSig=SynValSig(trivia = { WithKeyword = Some mWith }))])) ] + ) + ]) ])) -> + assertRange (3, 30) (3, 34) mWith + | _ -> Assert.Fail "Could not get valid AST" + +[] +let ``read-only property in SynMemberDefn.Member contains the range of the with keyword`` () = + let parseResults = + getParseResults + """ +type Foo() = + // A read-only property. + member this.MyReadProperty with get () = myInternalValue +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types( + typeDefns = [ SynTypeDefn(typeRepr = + SynTypeDefnRepr.ObjectModel(members=[ + _ + SynMemberDefn.GetSetMember(Some(SynBinding _), None, _, { WithKeyword = mWith }) ]) + ) ]) + ]) ])) -> + assertRange (4, 31) (4, 35) mWith + | _ -> Assert.Fail "Could not get valid AST" + +[] +let ``write-only property in SynMemberDefn.Member contains the range of the with keyword`` () = + let parseResults = + getParseResults + """ +type Foo() = + // A write-only property. + member this.MyWriteOnlyProperty with set (value) = myInternalValue <- value +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types( + typeDefns = [ SynTypeDefn(typeRepr = + SynTypeDefnRepr.ObjectModel(members=[ + _ + SynMemberDefn.GetSetMember(None, Some(SynBinding _), _, { WithKeyword = mWith }) ]) + ) ]) + ]) ])) -> + assertRange (4, 36) (4, 40) mWith + | _ -> Assert.Fail "Could not get valid AST" + +[] +let ``read/write property in SynMemberDefn.Member contains the range of the with keyword`` () = + let parseResults = + getParseResults + """ +type Foo() = + // A read-write property. + member this.MyReadWriteProperty + with get () = myInternalValue + and set (value) = myInternalValue <- value +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types( + typeDefns = [ SynTypeDefn(typeRepr = + SynTypeDefnRepr.ObjectModel(members=[ + _ + SynMemberDefn.GetSetMember(Some _, Some _, _, { WithKeyword = mWith; AndKeyword = Some mAnd }) ]) + ) ]) + ]) ])) -> + assertRange (5, 8) (5, 12) mWith + assertRange (6, 8) (6, 11) mAnd + | _ -> Assert.Fail "Could not get valid AST" + +[] +let ``SynTypeDefn with static member with get/set`` () = + let parseResults = + getParseResults + """ +type Foo = + static member ReadWrite2 + with set x = lastUsed <- ("ReadWrite2", x) + and get () = lastUsed <- ("ReadWrite2", 0); 4 +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types( + typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [ + SynMemberDefn.GetSetMember(Some _, Some _, m, { WithKeyword = mWith + GetKeyword = Some mGet + AndKeyword = Some mAnd + SetKeyword = Some mSet }) + ])) ] + ) + ]) ])) -> + assertRange (4, 8) (4, 12) mWith + assertRange (4, 13) (4, 16) mSet + assertRange (5, 8) (5, 11) mAnd + assertRange (5, 13) (5, 16) mGet + assertRange (3, 4) (5, 54) m + | _ -> Assert.Fail "Could not get valid AST" + +[] +let ``SynTypeDefn with member with set/get`` () = + let parseResults = + getParseResults + """ +type A() = + member this.Z with set (_:int):unit = () and get():int = 1 +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types( + typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [ + SynMemberDefn.ImplicitCtor _ + SynMemberDefn.GetSetMember(Some (SynBinding(headPat = SynPat.LongIdent(extraId = Some getIdent))), + Some (SynBinding(headPat = SynPat.LongIdent(extraId = Some setIdent))), + m, + { WithKeyword = mWith + GetKeyword = Some mGet + AndKeyword = Some mAnd + SetKeyword = Some mSet }) + ])) ] + ) + ]) ])) -> + Assert.AreEqual("get", getIdent.idText) + Assert.AreEqual("set", setIdent.idText) + assertRange (3, 18) (3, 22) mWith + assertRange (3, 23) (3, 26) mSet + assertRange (3, 23) (3, 26) setIdent.idRange + assertRange (3, 45) (3, 48) mAnd + assertRange (3, 49) (3, 52) mGet + assertRange (3, 49) (3, 52) getIdent.idRange + assertRange (3, 4) (3, 62) m + | _ -> Assert.Fail "Could not get valid AST" + +[] +let ``SynTypeDefn with member with get has xml comment`` () = + let parseResults = + getParseResults + """ +type A = + /// B + member x.B with get() = 5 +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types( + typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [ + SynMemberDefn.GetSetMember(Some (SynBinding(xmlDoc = preXmlDoc)), + None, + _, + _) + ])) ] + ) + ]) ])) -> + Assert.False preXmlDoc.IsEmpty + let comment = preXmlDoc.ToXmlDoc(false, None).GetXmlText() + Assert.False (System.String.IsNullOrWhiteSpace(comment)) + | _ -> Assert.Fail "Could not get valid AST" diff --git a/tests/service/SyntaxTreeTests/TypeTests.fs b/tests/service/SyntaxTreeTests/TypeTests.fs index 874c1f41dac..c006a7cd529 100644 --- a/tests/service/SyntaxTreeTests/TypeTests.fs +++ b/tests/service/SyntaxTreeTests/TypeTests.fs @@ -169,26 +169,6 @@ type Shape = assertRange (2, 11) (2, 12) mEquals | _ -> Assert.Fail "Could not get valid AST" -[] -let ``SynTypeDefn with AutoProperty contains the range of the equals sign`` () = - let parseResults = - getParseResults - """ -/// mutable class with auto-properties -type Person(name : string, age : int) = - /// Full name - member val Name = name with get, set -""" - - match parseResults with - | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ - SynModuleDecl.Types( - typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [_ ; SynMemberDefn.AutoProperty(equalsRange = mEquals)])) ] - ) - ]) ])) -> - assertRange (5, 20) (5, 21) mEquals - | _ -> Assert.Fail "Could not get valid AST" - [] let ``SynTypeDefn with Record contains the range of the with keyword`` () = let parseResults = @@ -250,115 +230,6 @@ type Foo() = assertRange (3, 18) (3, 22) mWithKeyword | _ -> Assert.Fail "Could not get valid AST" -[] -let ``SynTypeDefn with AutoProperty contains the range of the with keyword`` () = - let parseResults = - getParseResults - """ -type Foo() = - member val AutoProperty = autoProp with get, set - member val AutoProperty2 = autoProp -""" - - match parseResults with - | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ - SynModuleDecl.Types( - typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [_ - SynMemberDefn.AutoProperty(withKeyword=Some mWith) - SynMemberDefn.AutoProperty(withKeyword=None)])) ] - ) - ]) ])) -> - assertRange (3, 39) (3, 43) mWith - | _ -> Assert.Fail "Could not get valid AST" - -[] -let ``SynTypeDefn with AbstractSlot contains the range of the with keyword`` () = - let parseResults = - getParseResults - """ -type Foo() = - abstract member Bar : int with get,set -""" - - match parseResults with - | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ - SynModuleDecl.Types( - typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [_ - SynMemberDefn.AbstractSlot(slotSig=SynValSig(trivia = { WithKeyword = Some mWith }))])) ] - ) - ]) ])) -> - assertRange (3, 30) (3, 34) mWith - | _ -> Assert.Fail "Could not get valid AST" - -[] -let ``read-only property in SynMemberDefn.Member contains the range of the with keyword`` () = - let parseResults = - getParseResults - """ -type Foo() = - // A read-only property. - member this.MyReadProperty with get () = myInternalValue -""" - - match parseResults with - | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ - SynModuleDecl.Types( - typeDefns = [ SynTypeDefn(typeRepr = - SynTypeDefnRepr.ObjectModel(members=[ - _ - SynMemberDefn.GetSetMember(Some(SynBinding _), None, _, { WithKeyword = mWith }) ]) - ) ]) - ]) ])) -> - assertRange (4, 31) (4, 35) mWith - | _ -> Assert.Fail "Could not get valid AST" - -[] -let ``write-only property in SynMemberDefn.Member contains the range of the with keyword`` () = - let parseResults = - getParseResults - """ -type Foo() = - // A write-only property. - member this.MyWriteOnlyProperty with set (value) = myInternalValue <- value -""" - - match parseResults with - | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ - SynModuleDecl.Types( - typeDefns = [ SynTypeDefn(typeRepr = - SynTypeDefnRepr.ObjectModel(members=[ - _ - SynMemberDefn.GetSetMember(None, Some(SynBinding _), _, { WithKeyword = mWith }) ]) - ) ]) - ]) ])) -> - assertRange (4, 36) (4, 40) mWith - | _ -> Assert.Fail "Could not get valid AST" - -[] -let ``read/write property in SynMemberDefn.Member contains the range of the with keyword`` () = - let parseResults = - getParseResults - """ -type Foo() = - // A read-write property. - member this.MyReadWriteProperty - with get () = myInternalValue - and set (value) = myInternalValue <- value -""" - - match parseResults with - | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ - SynModuleDecl.Types( - typeDefns = [ SynTypeDefn(typeRepr = - SynTypeDefnRepr.ObjectModel(members=[ - _ - SynMemberDefn.GetSetMember(Some _, Some _, _, { WithKeyword = mWith; AndKeyword = Some mAnd }) ]) - ) ]) - ]) ])) -> - assertRange (5, 8) (5, 12) mWith - assertRange (6, 8) (6, 11) mAnd - | _ -> Assert.Fail "Could not get valid AST" - [] let ``SynTypeDefn with XmlDoc contains the range of the type keyword`` () = let parseResults = @@ -399,70 +270,6 @@ type A = B assertRange (4, 0) (4, 4) mType | _ -> Assert.Fail "Could not get valid AST" -[] -let ``SynTypeDefn with static member with get/set`` () = - let parseResults = - getParseResults - """ -type Foo = - static member ReadWrite2 - with set x = lastUsed <- ("ReadWrite2", x) - and get () = lastUsed <- ("ReadWrite2", 0); 4 -""" - - match parseResults with - | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ - SynModuleDecl.Types( - typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [ - SynMemberDefn.GetSetMember(Some _, Some _, m, { WithKeyword = mWith - GetKeyword = Some mGet - AndKeyword = Some mAnd - SetKeyword = Some mSet }) - ])) ] - ) - ]) ])) -> - assertRange (4, 8) (4, 12) mWith - assertRange (4, 13) (4, 16) mSet - assertRange (5, 8) (5, 11) mAnd - assertRange (5, 13) (5, 16) mGet - assertRange (3, 4) (5, 54) m - | _ -> Assert.Fail "Could not get valid AST" - -[] -let ``SynTypeDefn with member with set/get`` () = - let parseResults = - getParseResults - """ -type A() = - member this.Z with set (_:int):unit = () and get():int = 1 -""" - - match parseResults with - | ParsedInput.ImplFile (ParsedImplFileInput (contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ - SynModuleDecl.Types( - typeDefns = [ SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [ - SynMemberDefn.ImplicitCtor _ - SynMemberDefn.GetSetMember(Some (SynBinding(headPat = SynPat.LongIdent(extraId = Some getIdent))), - Some (SynBinding(headPat = SynPat.LongIdent(extraId = Some setIdent))), - m, - { WithKeyword = mWith - GetKeyword = Some mGet - AndKeyword = Some mAnd - SetKeyword = Some mSet }) - ])) ] - ) - ]) ])) -> - Assert.AreEqual("get", getIdent.idText) - Assert.AreEqual("set", setIdent.idText) - assertRange (3, 18) (3, 22) mWith - assertRange (3, 23) (3, 26) mSet - assertRange (3, 23) (3, 26) setIdent.idRange - assertRange (3, 45) (3, 48) mAnd - assertRange (3, 49) (3, 52) mGet - assertRange (3, 49) (3, 52) getIdent.idRange - assertRange (3, 4) (3, 62) m - | _ -> Assert.Fail "Could not get valid AST" - [] let ``SynType.Fun has range of arrow`` () = let parseResults = @@ -502,7 +309,7 @@ let _: struct (int * int) = () ]) ) -> assertRange (2, 7) (2, 25) mTuple - + | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" [] @@ -522,7 +329,7 @@ let _: struct (int * int = () ]) ) -> assertRange (2, 7) (2, 24) mTuple - + | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" [] @@ -593,4 +400,4 @@ type X = ])) -> Assert.AreEqual("a", a.idText) assertRange (3, 23) (3, 41) m - | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" \ No newline at end of file + | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" From e389d7744b7ddf81fd62cf01ce870cf92f6dcabd Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Thu, 6 Oct 2022 11:16:14 +0200 Subject: [PATCH 29/32] Correct SynAttribute range (#13998) * Add failing test. * Update range for SynAttribute. * Use unionRanges instead of mkFileIndexRange. * Update ranges in unit tests. * Fix ServiceTests. * Update failing FSharpSuite.Tests. * Update negative tests. * Trigger CI --- src/Compiler/Service/ServiceParsedInputOps.fs | 2 +- src/Compiler/pars.fsy | 15 ++- .../Attributes/Diags/Diags.fs | 4 +- .../Attributes/Legacy/Legacy.fs | 110 +++++++++--------- .../AttributeUsage/AttributeUsage.fs | 10 +- .../CustomAttributes/Basic/Basic.fs | 8 +- .../LetBindings/Basic/Basic.fs | 4 +- .../ErrorMessages/UnsupportedAttributes.fs | 4 +- .../FSharp.Compiler.Service.Tests.fsproj | 3 + tests/fsharp/typecheck/sigs/neg20.bsl | 8 +- tests/fsharp/typecheck/sigs/neg31.bsl | 12 +- tests/fsharp/typecheck/sigs/neg32.bsl | 2 +- .../fsharp/typecheck/sigs/version50/neg20.bsl | 8 +- .../AttributeMatching01.fs | 2 +- .../AttributeMatching01.fsi | 2 +- tests/fsharpqa/Source/Misc/E_CompiledName.fs | 4 +- tests/service/PatternMatchCompilationTests.fs | 2 +- .../service/SyntaxTreeTests/AttributeTests.fs | 50 ++++++++ 18 files changed, 154 insertions(+), 96 deletions(-) create mode 100644 tests/service/SyntaxTreeTests/AttributeTests.fs diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs index 86d560091ea..7d3c916bc8e 100644 --- a/src/Compiler/Service/ServiceParsedInputOps.fs +++ b/src/Compiler/Service/ServiceParsedInputOps.fs @@ -581,7 +581,7 @@ module ParsedInput = |> Option.orElseWith (fun () -> ifPosInRange r (fun _ -> List.tryPick (walkSynModuleDecl isTopLevel) decls)) and walkAttribute (attr: SynAttribute) = - if isPosInRange attr.Range then + if isPosInRange attr.TypeName.Range then Some EntityKind.Attribute else None diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index c9dd108bf2d..94df75aada1 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -1561,18 +1561,23 @@ attributeListElements: attribute: /* A custom attribute */ | path opt_HIGH_PRECEDENCE_APP opt_atomicExprAfterType - { let arg = match $3 with None -> mkSynUnit $1.Range | Some e -> e - ({ TypeName=$1; ArgExpr=arg; Target=None; AppliesToGetterAndSetter=false; Range=$1.Range } : SynAttribute) } + { let arg = match $3 with None -> mkSynUnit $1.Range | Some e -> e + let m = unionRanges $1.Range arg.Range + ({ TypeName=$1; ArgExpr=arg; Target=None; AppliesToGetterAndSetter=false; Range=m } : SynAttribute) } /* A custom attribute with an attribute target */ | attributeTarget path opt_HIGH_PRECEDENCE_APP opt_atomicExprAfterType - { let arg = match $4 with None -> mkSynUnit $2.Range | Some e -> e - ({ TypeName=$2; ArgExpr=arg; Target=$1; AppliesToGetterAndSetter=false; Range=$2.Range } : SynAttribute) } + { let arg = match $4 with None -> mkSynUnit $2.Range | Some e -> e + let startRange = match $1 with Some (ident:Ident) -> ident.idRange | None -> $2.Range + let m = unionRanges startRange arg.Range + ({ TypeName=$2; ArgExpr=arg; Target=$1; AppliesToGetterAndSetter=false; Range=m } : SynAttribute) } /* A custom attribute with an attribute target */ | attributeTarget OBLOCKBEGIN path oblockend opt_HIGH_PRECEDENCE_APP opt_atomicExprAfterType { let arg = match $6 with None -> mkSynUnit $3.Range | Some e -> e - ({ TypeName=$3; ArgExpr=arg; Target=$1; AppliesToGetterAndSetter=false; Range=$3.Range } : SynAttribute) } + let startRange = match $1 with Some ident -> ident.idRange | None -> $3.Range + let m = unionRanges startRange arg.Range + ({ TypeName=$3; ArgExpr=arg; Target=$1; AppliesToGetterAndSetter=false; Range=m } : SynAttribute) } /* The target of a custom attribute */ diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/Diags/Diags.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/Diags/Diags.fs index 295ee002be7..95fe85e3678 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/Diags/Diags.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/Diags/Diags.fs @@ -17,7 +17,7 @@ module Diags = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 3, Line 7, Col 23, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 7, Col 3, Line 7, Col 30, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") ] // SOURCE=E_AdjustUses01b.fs SCFLAGS=--test:ErrorRanges # E_AdjustUses01b.fs @@ -28,6 +28,6 @@ module Diags = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 3, Line 7, Col 23, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 7, Col 3, Line 7, Col 30, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") ] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/Legacy/Legacy.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/Legacy/Legacy.fs index e26e9b5d08b..af9e9f3472e 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/Legacy/Legacy.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicTypeAndModuleDefinitions/GeneratedEqualityHashingComparison/Attributes/Legacy/Legacy.fs @@ -17,9 +17,9 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 9, Col 5, Line 9, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 28, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 31, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 29, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test02.fs SCFLAGS="--test:ErrorRanges" # Test02.fs @@ -30,9 +30,9 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 8, Col 5, Line 8, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 9, Col 5, Line 9, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 10, Col 5, Line 10, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 28, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 31, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 10, Col 5, Line 10, Col 30, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test03.fs SCFLAGS="--test:ErrorRanges" # Test03.fs @@ -43,8 +43,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 28, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 31, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") ] // SOURCE=Test04.fs SCFLAGS="--test:ErrorRanges" # Test04.fs @@ -55,9 +55,9 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 9, Col 5, Line 9, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 28, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 32, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 29, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test05.fs SCFLAGS="--test:ErrorRanges" # Test05.fs @@ -68,9 +68,9 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 9, Col 5, Line 9, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 28, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 32, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 30, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test06.fs SCFLAGS="--test:ErrorRanges" # Test06.fs @@ -81,8 +81,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 28, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 32, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") ] // SOURCE=Test07.fs SCFLAGS="--test:ErrorRanges" # Test07.fs @@ -93,8 +93,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 9, Col 5, Line 9, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 28, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 29, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test08.fs SCFLAGS="--test:ErrorRanges" # Test08.fs @@ -105,8 +105,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 9, Col 5, Line 9, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 28, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 30, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test09.fs SCFLAGS="--test:ErrorRanges" # Test09.fs @@ -117,7 +117,7 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 6, Col 5, Line 6, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 6, Col 5, Line 6, Col 28, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") ] // SOURCE=Test10.fs SCFLAGS="--test:ErrorRanges" # Test10.fs @@ -128,9 +128,9 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 8, Col 5, Line 8, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 9, Col 5, Line 9, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 10, Col 5, Line 10, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 29, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 31, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 10, Col 5, Line 10, Col 29, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test11.fs SCFLAGS="--test:ErrorRanges" # Test11.fs @@ -141,9 +141,9 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 8, Col 5, Line 8, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 9, Col 5, Line 9, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 10, Col 5, Line 10, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 29, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 31, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 10, Col 5, Line 10, Col 30, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test12.fs SCFLAGS="--test:ErrorRanges" # Test12.fs @@ -154,8 +154,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 29, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 31, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") ] // SOURCE=Test13.fs SCFLAGS="--test:ErrorRanges" # Test13.fs @@ -166,9 +166,9 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 9, Col 5, Line 9, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 29, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 32, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 29, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test14.fs SCFLAGS="--test:ErrorRanges" # Test14.fs @@ -179,9 +179,9 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 9, Col 5, Line 9, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 10, Col 5, Line 10, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 11, Col 5, Line 11, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 29, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 10, Col 5, Line 10, Col 32, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 11, Col 5, Line 11, Col 30, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test15.fs SCFLAGS="--test:ErrorRanges" # Test15.fs @@ -192,8 +192,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 29, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 32, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") ] // SOURCE=Test16.fs SCFLAGS="--test:ErrorRanges" # Test16.fs @@ -204,8 +204,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 9, Col 5, Line 9, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 29, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 29, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test17.fs SCFLAGS="--test:ErrorRanges" # Test17.fs @@ -216,8 +216,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 6, Col 5, Line 6, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 6, Col 5, Line 6, Col 29, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 30, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test18.fs SCFLAGS="--test:ErrorRanges" # Test18.fs @@ -228,7 +228,7 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 6, Col 5, Line 6, Col 22, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") + (Error 501, Line 6, Col 5, Line 6, Col 29, "The object constructor 'ReferenceEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> ReferenceEqualityAttribute'.") ] // SOURCE=Test19.fs SCFLAGS="--test:ErrorRanges" # Test19.fs @@ -239,8 +239,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 31, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 29, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test20.fs SCFLAGS="--test:ErrorRanges" # Test20.fs @@ -251,8 +251,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 31, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 30, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test21.fs SCFLAGS="--test:ErrorRanges" # Test21.fs @@ -263,7 +263,7 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 6, Col 5, Line 6, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 6, Col 5, Line 6, Col 31, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") ] // SOURCE=Test22.fs SCFLAGS="--test:ErrorRanges" # Test22.fs @@ -274,8 +274,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 8, Col 5, Line 8, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 32, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 8, Col 5, Line 8, Col 29, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test23.fs SCFLAGS="--test:ErrorRanges" # Test23.fs @@ -286,8 +286,8 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 9, Col 5, Line 9, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") - (Error 501, Line 10, Col 5, Line 10, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 9, Col 5, Line 9, Col 32, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 10, Col 5, Line 10, Col 30, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test24.fs SCFLAGS="--test:ErrorRanges" # Test24.fs @@ -298,7 +298,7 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 6, Col 5, Line 6, Col 25, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") + (Error 501, Line 6, Col 5, Line 6, Col 32, "The object constructor 'StructuralComparisonAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralComparisonAttribute'.") ] // SOURCE=Test25.fs SCFLAGS="--test:ErrorRanges" # Test25.fs @@ -309,7 +309,7 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 29, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test26.fs SCFLAGS="--test:ErrorRanges" # Test26.fs @@ -320,7 +320,7 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 5, Line 7, Col 23, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 5, Line 7, Col 30, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] // SOURCE=Test27.fs SCFLAGS="--test:ErrorRanges" # Test27.fs @@ -340,7 +340,7 @@ module Legacy = |> compile |> shouldFail |> withDiagnostics [ - (Error 501, Line 7, Col 3, Line 7, Col 21, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") + (Error 501, Line 7, Col 3, Line 7, Col 28, "The object constructor 'StructuralEqualityAttribute' takes 0 argument(s) but is here given 1. The required signature is 'new: unit -> StructuralEqualityAttribute'.") ] diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/CustomAttributes/AttributeUsage/AttributeUsage.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/CustomAttributes/AttributeUsage/AttributeUsage.fs index eeac02384ab..0161db9cd6e 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -79,8 +79,8 @@ module AttributeUsage = |> shouldFail |> withDiagnostics [ (Error 842, Line 21, Col 21, Line 21, Col 22, "This attribute is not valid for use on this language element") - (Error 842, Line 24, Col 28, Line 24, Col 29, "This attribute is not valid for use on this language element") - (Error 842, Line 27, Col 15, Line 27, Col 16, "This attribute is not valid for use on this language element") + (Error 842, Line 24, Col 21, Line 24, Col 29, "This attribute is not valid for use on this language element") + (Error 842, Line 27, Col 7, Line 27, Col 16, "This attribute is not valid for use on this language element") ] // SOURCE=E_AttributeTargets02.fs # E_AttributeTargets02.fs @@ -90,9 +90,9 @@ module AttributeUsage = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 842, Line 14, Col 17, Line 14, Col 34, "This attribute is not valid for use on this language element") - (Error 842, Line 24, Col 14, Line 24, Col 29, "This attribute is not valid for use on this language element") - (Error 842, Line 29, Col 25, Line 29, Col 40, "This attribute is not valid for use on this language element") + (Error 842, Line 14, Col 7, Line 14, Col 34, "This attribute is not valid for use on this language element") + (Error 842, Line 24, Col 7, Line 24, Col 36, "This attribute is not valid for use on this language element") + (Error 842, Line 29, Col 15, Line 29, Col 47, "This attribute is not valid for use on this language element") ] // SOURCE=E_ConditionalAttribute.fs SCFLAGS="--test:ErrorRanges" # E_ConditionalAttribute.fs diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/CustomAttributes/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/CustomAttributes/Basic/Basic.fs index 8bc5e456829..829d0f86f79 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/CustomAttributes/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/CustomAttributes/Basic/Basic.fs @@ -41,7 +41,7 @@ module Basic = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 841, Line 7, Col 12, Line 7, Col 49, "This attribute is not valid for use on this language element. Assembly attributes should be attached to a 'do ()' declaration, if necessary within an F# module.") + (Error 841, Line 7, Col 3, Line 7, Col 111, "This attribute is not valid for use on this language element. Assembly attributes should be attached to a 'do ()' declaration, if necessary within an F# module.") ] // SOURCE=E_AttributeApplication02.fs SCFLAGS="--test:ErrorRanges" # E_AttributeApplication02.fs @@ -106,8 +106,8 @@ module Basic = (Error 1, Line 10, Col 3, Line 10, Col 59, "This expression was expected to have type\n 'int array' \nbut here has type\n 'unit' ") (Error 267, Line 10, Col 3, Line 10, Col 59, "This is not a valid constant expression or custom attribute value") (Error 850, Line 10, Col 3, Line 10, Col 59, "This attribute cannot be used in this version of F#") - (Error 850, Line 13, Col 3, Line 13, Col 52, "This attribute cannot be used in this version of F#") - (Error 850, Line 16, Col 13, Line 16, Col 37, "This attribute cannot be used in this version of F#") + (Error 850, Line 13, Col 3, Line 13, Col 101, "This attribute cannot be used in this version of F#") + (Error 850, Line 16, Col 3, Line 16, Col 50, "This attribute cannot be used in this version of F#") ] // SOURCE=E_AttributeTargetSpecifications.fs # E_AttributeTargetSpecifications.fs @@ -305,7 +305,7 @@ module Basic = |> verifyCompile |> shouldFail |> withDiagnostics [ - (Error 429, Line 16, Col 28, Line 16, Col 31, "The attribute type 'CA1' has 'AllowMultiple=false'. Multiple instances of this attribute cannot be attached to a single language element.") + (Error 429, Line 16, Col 28, Line 16, Col 37, "The attribute type 'CA1' has 'AllowMultiple=false'. Multiple instances of this attribute cannot be attached to a single language element.") ] // SOURCE=W_StructLayoutExplicit01.fs SCFLAGS="--test:ErrorRanges" PEVER="/Exp_Fail" # W_StructLayoutExplicit01.fs diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs index fc9e36d748e..c472ec9b0ea 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/DeclarationElements/LetBindings/Basic/Basic.fs @@ -53,9 +53,9 @@ module Basic = |> shouldFail |> withDiagnostics [ (Error 683, Line 14, Col 6, Line 14, Col 27, "Attributes are not allowed within patterns") - (Error 842, Line 14, Col 8, Line 14, Col 23, "This attribute is not valid for use on this language element") + (Error 842, Line 14, Col 8, Line 14, Col 25, "This attribute is not valid for use on this language element") (Error 683, Line 14, Col 42, Line 14, Col 63, "Attributes are not allowed within patterns") - (Error 842, Line 14, Col 44, Line 14, Col 59, "This attribute is not valid for use on this language element") + (Error 842, Line 14, Col 44, Line 14, Col 61, "This attribute is not valid for use on this language element") ] // SOURCE=E_ErrorsForInlineValue.fs SCFLAGS="--test:ErrorRanges" # E_ErrorsForInlineValue.fs diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UnsupportedAttributes.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UnsupportedAttributes.fs index 439b0bd7bdb..276bad5963c 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UnsupportedAttributes.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/UnsupportedAttributes.fs @@ -27,7 +27,7 @@ type C() = Range = { StartLine = 3 StartColumn = 13 EndLine = 3 - EndColumn = 37 } + EndColumn = 41 } Message = "This attribute is currently unsupported by the F# compiler. Applying it will not achieve its intended effect." } { Error = Warning 202 @@ -41,7 +41,7 @@ type C() = Range = { StartLine = 6 StartColumn = 22 EndLine = 6 - EndColumn = 78 } + EndColumn = 82 } Message = "This attribute is currently unsupported by the F# compiler. Applying it will not achieve its intended effect." } { Error = Warning 202 diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index 99af61de377..d6db862529d 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -119,6 +119,9 @@ SyntaxTree\SynIdentTests.fs + + SyntaxTree\AttributeTests.fs + FileSystemTests.fs diff --git a/tests/fsharp/typecheck/sigs/neg20.bsl b/tests/fsharp/typecheck/sigs/neg20.bsl index 6fe2d2e3295..88f483967e4 100644 --- a/tests/fsharp/typecheck/sigs/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/neg20.bsl @@ -271,7 +271,7 @@ neg20.fs(216,5,216,12): typecheck error FS0842: This attribute is not valid for neg20.fs(219,5,219,15): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(222,5,222,24): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(222,5,222,31): typecheck error FS0842: This attribute is not valid for use on this language element neg20.fs(225,5,225,22): typecheck error FS0842: This attribute is not valid for use on this language element @@ -289,9 +289,9 @@ neg20.fs(243,5,243,23): typecheck error FS0842: This attribute is not valid for neg20.fs(249,9,249,27): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(255,5,255,21): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(255,5,255,28): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(258,5,258,31): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(258,5,258,38): typecheck error FS0842: This attribute is not valid for use on this language element neg20.fs(261,5,261,17): typecheck error FS0842: This attribute is not valid for use on this language element @@ -299,7 +299,7 @@ neg20.fs(265,5,265,24): typecheck error FS0842: This attribute is not valid for neg20.fs(268,5,268,27): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(271,5,271,13): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(271,5,271,15): typecheck error FS0842: This attribute is not valid for use on this language element neg20.fs(278,14,278,95): typecheck error FS0507: No accessible member or object constructor named 'ProcessStartInfo' takes 0 arguments. Note the call to this member also provides 2 named arguments. diff --git a/tests/fsharp/typecheck/sigs/neg31.bsl b/tests/fsharp/typecheck/sigs/neg31.bsl index 86bb626f0b4..9140452d235 100644 --- a/tests/fsharp/typecheck/sigs/neg31.bsl +++ b/tests/fsharp/typecheck/sigs/neg31.bsl @@ -1,12 +1,12 @@ -neg31.fs(9,6,9,30): typecheck error FS1200: The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. +neg31.fs(9,6,9,64): typecheck error FS1200: The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. -neg31.fs(71,12,71,36): typecheck error FS1200: The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. +neg31.fs(71,12,71,70): typecheck error FS1200: The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. -neg31.fs(107,13,107,41): typecheck error FS1200: The attribute 'CLSCompliantAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. +neg31.fs(107,13,107,48): typecheck error FS1200: The attribute 'CLSCompliantAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. -neg31.fs(28,6,28,30): typecheck error FS1200: The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. +neg31.fs(28,6,28,64): typecheck error FS1200: The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. -neg31.fs(93,14,93,42): typecheck error FS1200: The attribute 'CLSCompliantAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. +neg31.fs(93,14,93,49): typecheck error FS1200: The attribute 'CLSCompliantAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. -neg31.fs(47,6,47,30): typecheck error FS1200: The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. +neg31.fs(47,6,47,64): typecheck error FS1200: The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ. Only the attribute from the signature will be included in the compiled code. diff --git a/tests/fsharp/typecheck/sigs/neg32.bsl b/tests/fsharp/typecheck/sigs/neg32.bsl index 6afdd7ae5a7..be532860a7a 100644 --- a/tests/fsharp/typecheck/sigs/neg32.bsl +++ b/tests/fsharp/typecheck/sigs/neg32.bsl @@ -1,5 +1,5 @@ -neg32.fs(17,21,17,49): typecheck error FS0842: This attribute is not valid for use on this language element +neg32.fs(17,11,17,56): typecheck error FS0842: This attribute is not valid for use on this language element neg32.fs(24,15,24,16): typecheck error FS0043: The member or object constructor 'TryParse' does not take 1 argument(s). An overload was found taking 2 arguments. diff --git a/tests/fsharp/typecheck/sigs/version50/neg20.bsl b/tests/fsharp/typecheck/sigs/version50/neg20.bsl index b1e3b87ffb5..37e8f71a499 100644 --- a/tests/fsharp/typecheck/sigs/version50/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/version50/neg20.bsl @@ -319,7 +319,7 @@ neg20.fs(216,5,216,12): typecheck error FS0842: This attribute is not valid for neg20.fs(219,5,219,15): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(222,5,222,24): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(222,5,222,31): typecheck error FS0842: This attribute is not valid for use on this language element neg20.fs(225,5,225,22): typecheck error FS0842: This attribute is not valid for use on this language element @@ -337,9 +337,9 @@ neg20.fs(243,5,243,23): typecheck error FS0842: This attribute is not valid for neg20.fs(249,9,249,27): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(255,5,255,21): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(255,5,255,28): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(258,5,258,31): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(258,5,258,38): typecheck error FS0842: This attribute is not valid for use on this language element neg20.fs(261,5,261,17): typecheck error FS0842: This attribute is not valid for use on this language element @@ -347,7 +347,7 @@ neg20.fs(265,5,265,24): typecheck error FS0842: This attribute is not valid for neg20.fs(268,5,268,27): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(271,5,271,13): typecheck error FS0842: This attribute is not valid for use on this language element +neg20.fs(271,5,271,15): typecheck error FS0842: This attribute is not valid for use on this language element neg20.fs(278,14,278,95): typecheck error FS0507: No accessible member or object constructor named 'ProcessStartInfo' takes 0 arguments. Note the call to this member also provides 2 named arguments. diff --git a/tests/fsharpqa/Source/Conformance/Signatures/SignatureConformance/AttributeMatching01.fs b/tests/fsharpqa/Source/Conformance/Signatures/SignatureConformance/AttributeMatching01.fs index ceeadc93274..082ea859d45 100644 --- a/tests/fsharpqa/Source/Conformance/Signatures/SignatureConformance/AttributeMatching01.fs +++ b/tests/fsharpqa/Source/Conformance/Signatures/SignatureConformance/AttributeMatching01.fs @@ -1,6 +1,6 @@ // #Conformance #SignatureFiles #Attributes #Regression // Regression for 6446 - verifying spec matches implementation when fs/fsi files attributes differ -//The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ\. Only the attribute from the signature will be included in the compiled code\. +//The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ\. Only the attribute from the signature will be included in the compiled code\. module M diff --git a/tests/fsharpqa/Source/Conformance/Signatures/SignatureConformance/AttributeMatching01.fsi b/tests/fsharpqa/Source/Conformance/Signatures/SignatureConformance/AttributeMatching01.fsi index b3092d384b2..8f6e9113446 100644 --- a/tests/fsharpqa/Source/Conformance/Signatures/SignatureConformance/AttributeMatching01.fsi +++ b/tests/fsharpqa/Source/Conformance/Signatures/SignatureConformance/AttributeMatching01.fsi @@ -1,6 +1,6 @@ // #Conformance #SignatureFiles #Attributes #Regression // Regression for 6446 - verifying spec matches implementation when fs/fsi files attributes differ -//The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ\. Only the attribute from the signature will be included in the compiled code\. +//The attribute 'ObsoleteAttribute' appears in both the implementation and the signature, but the attribute arguments differ\. Only the attribute from the signature will be included in the compiled code\. module M diff --git a/tests/fsharpqa/Source/Misc/E_CompiledName.fs b/tests/fsharpqa/Source/Misc/E_CompiledName.fs index cdf5e84ae72..437032e0112 100644 --- a/tests/fsharpqa/Source/Misc/E_CompiledName.fs +++ b/tests/fsharpqa/Source/Misc/E_CompiledName.fs @@ -1,8 +1,8 @@ // #Regression #Misc // Regression test for FSHARP1.0:5936 // This test ensures that you can't apply the CompiledName attribute more than once to a property -//The attribute type 'CompiledNameAttribute' has 'AllowMultiple=false'\. Multiple instances of this attribute cannot be attached to a single language element\.$ -//The attribute type 'CompiledNameAttribute' has 'AllowMultiple=false'\. Multiple instances of this attribute cannot be attached to a single language element\.$ +//The attribute type 'CompiledNameAttribute' has 'AllowMultiple=false'\. Multiple instances of this attribute cannot be attached to a single language element\.$ +//The attribute type 'CompiledNameAttribute' has 'AllowMultiple=false'\. Multiple instances of this attribute cannot be attached to a single language element\.$ module M type T() = diff --git a/tests/service/PatternMatchCompilationTests.fs b/tests/service/PatternMatchCompilationTests.fs index 7daef75bcf8..49117c04cea 100644 --- a/tests/service/PatternMatchCompilationTests.fs +++ b/tests/service/PatternMatchCompilationTests.fs @@ -46,7 +46,7 @@ match () with assertHasSymbolUsages ["x"; "y"; "CompiledNameAttribute"] checkResults dumpDiagnostics checkResults |> shouldEqual [ "(3,2--3,25): Attributes are not allowed within patterns" - "(3,4--3,16): This attribute is not valid for use on this language element" + "(3,4--3,23): This attribute is not valid for use on this language element" ] diff --git a/tests/service/SyntaxTreeTests/AttributeTests.fs b/tests/service/SyntaxTreeTests/AttributeTests.fs new file mode 100644 index 00000000000..c31aefae85f --- /dev/null +++ b/tests/service/SyntaxTreeTests/AttributeTests.fs @@ -0,0 +1,50 @@ +module FSharp.Compiler.Service.Tests.SyntaxTreeTests.AttributeTests + +open FSharp.Compiler.Service.Tests.Common +open FSharp.Compiler.Syntax +open NUnit.Framework + +[] +let ``range of attribute`` () = + let ast = + """ +[] +do () +""" + |> getParseResults + + match ast with + | ParsedInput.ImplFile (ParsedImplFileInput(contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = + [ SynModuleDecl.Attributes(attributes = [ { Attributes = [ { Range = mAttribute } ] } ]) ; SynModuleDecl.Expr _ ] ) ])) -> + assertRange (2, 2) (2, 25) mAttribute + | _ -> Assert.Fail $"Could not get valid AST, got {ast}" + +[] +let ``range of attribute with path`` () = + let ast = + """ +[] +do () +""" + |> getParseResults + + match ast with + | ParsedInput.ImplFile (ParsedImplFileInput(contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = + [ SynModuleDecl.Attributes(attributes = [ { Attributes = [ { Range = mAttribute } ] } ]) ; SynModuleDecl.Expr _ ] ) ])) -> + assertRange (2, 2) (2, 32) mAttribute + | _ -> Assert.Fail $"Could not get valid AST, got {ast}" + +[] +let ``range of attribute with target`` () = + let ast = + """ +[] +do () +""" + |> getParseResults + + match ast with + | ParsedInput.ImplFile (ParsedImplFileInput(contents = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = + [ SynModuleDecl.Attributes(attributes = [ { Attributes = [ { Range = mAttribute } ] } ]) ; SynModuleDecl.Expr _ ] ) ])) -> + assertRange (2, 2) (2, 35) mAttribute + | _ -> Assert.Fail $"Could not get valid AST, got {ast}" From 23d93522a56e139e2fc85e6d2591d38698ae8d38 Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Thu, 6 Oct 2022 19:25:48 +0200 Subject: [PATCH 30/32] Add extern keyword to SynBindingTrivia. (#14030) --- src/Compiler/SyntaxTree/ParseHelpers.fs | 3 +++ src/Compiler/SyntaxTree/SyntaxTrivia.fs | 2 ++ src/Compiler/SyntaxTree/SyntaxTrivia.fsi | 3 +++ src/Compiler/pars.fsy | 16 +++++++------- .../FSharp.Compiler.Service.Tests.fsproj | 3 +++ ...erService.SurfaceArea.netstandard.expected | 4 +++- tests/service/SyntaxTreeTests/ExternTests.fs | 21 +++++++++++++++++++ 7 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 tests/service/SyntaxTreeTests/ExternTests.fs diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs index f3e3fcdfdaf..6aa973d275e 100644 --- a/src/Compiler/SyntaxTree/ParseHelpers.fs +++ b/src/Compiler/SyntaxTree/ParseHelpers.fs @@ -468,6 +468,7 @@ let mkSynMemberDefnGetSet { LetKeyword = None EqualsRange = mEquals + ExternKeyword = None } let binding = @@ -542,6 +543,7 @@ let mkSynMemberDefnGetSet { LetKeyword = None EqualsRange = mEquals + ExternKeyword = None } let binding = @@ -629,6 +631,7 @@ let mkSynMemberDefnGetSet { LetKeyword = None EqualsRange = mEquals + ExternKeyword = None } let bindingOuter = diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs index e4b58c85c00..fa4ebc784c8 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs @@ -159,12 +159,14 @@ type SynTypeDefnSigTrivia = type SynBindingTrivia = { LetKeyword: range option + ExternKeyword: range option EqualsRange: range option } static member Zero: SynBindingTrivia = { LetKeyword = None + ExternKeyword = None EqualsRange = None } diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi index 3e0dea3db0b..b6f0532d73c 100644 --- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi @@ -246,6 +246,9 @@ type SynBindingTrivia = /// The syntax range of the `let` keyword. LetKeyword: range option + /// The syntax range of the `extern` keyword. + ExternKeyword: range option + /// The syntax range of the `=` token. EqualsRange: range option } diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 94df75aada1..b732754d7fc 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -1868,7 +1868,7 @@ memberCore: let xmlDoc = grabXmlDocAtRangeStart(parseState, attrs, rangeStart) let memberFlags = Some (memFlagsBuilder SynMemberKind.Member) let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) - let trivia: SynBindingTrivia = { LetKeyword = None; EqualsRange = Some mEquals } + let trivia: SynBindingTrivia = { LetKeyword = None; EqualsRange = Some mEquals; ExternKeyword = None } let binding = mkSynBinding (xmlDoc, bindingPat) (vis, $1, false, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, optReturnType, $5, mRhs, [], attrs, memberFlags, trivia) let memberRange = unionRanges rangeStart mRhs |> unionRangeWithXmlDoc xmlDoc [ SynMemberDefn.Member (binding, memberRange) ]) } @@ -1985,7 +1985,7 @@ classDefnMember: let declPat = SynPat.LongIdent (SynLongIdent([mkSynId (rhs parseState 3) "new"], [], [None]), None, Some noInferredTypars, SynArgPats.Pats [$4], vis, rhs parseState 3) // Check that 'SynPatForConstructorDecl' matches this correctly assert (match declPat with SynPatForConstructorDecl _ -> true | _ -> false) - let synBindingTrivia: SynBindingTrivia = { LetKeyword = None; EqualsRange = Some mEquals } + let synBindingTrivia: SynBindingTrivia = { LetKeyword = None; EqualsRange = Some mEquals; ExternKeyword = None } [ SynMemberDefn.Member(SynBinding (None, SynBindingKind.Normal, false, false, $1, xmlDoc, valSynData, declPat, None, expr, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, synBindingTrivia), m) ] } | opt_attributes opt_declVisibility STATIC typeKeyword tyconDefn @@ -2743,7 +2743,8 @@ hardwhiteDefnBindingsTerminator: /* An 'extern' DllImport function definition in C-style syntax */ cPrototype: | EXTERN cRetType opt_access ident opt_HIGH_PRECEDENCE_APP LPAREN externArgs rparen - { let rty, vis, nm, args = $2, $3, $4, $7 + { let mExtern = rhs parseState 1 + let rty, vis, nm, args = $2, $3, $4, $7 let nmm = rhs parseState 3 let argsm = rhs parseState 6 let mBindLhs = lhs parseState @@ -2760,10 +2761,11 @@ cPrototype: let bindingPat = SynPat.LongIdent (SynLongIdent([nm], [], [None]), None, Some noInferredTypars, SynArgPats.Pats [SynPat.Tuple(false, args, argsm)], vis, nmm) let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let xmlDoc = grabXmlDoc(parseState, attrs, 1) + let trivia = { LetKeyword = None; ExternKeyword = Some mExtern; EqualsRange = None } let binding = mkSynBinding (xmlDoc, bindingPat) - (vis, false, false, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, Some rty, rhsExpr, mRhs, [], attrs, None, SynBindingTrivia.Zero) + (vis, false, false, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, Some rty, rhsExpr, mRhs, [], attrs, None, trivia) [], [binding]) } /* A list of arguments in an 'extern' DllImport function definition */ @@ -2882,7 +2884,7 @@ localBinding: let mWhole = (unionRanges mLetKwd mRhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let spBind = if IsDebugPointBinding bindingPat expr then DebugPointAtBinding.Yes mWhole else DebugPointAtBinding.NoneAtLet let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) - let trivia: SynBindingTrivia = { LetKeyword = Some mLetKwd; EqualsRange = Some mEquals } + let trivia: SynBindingTrivia = { LetKeyword = Some mLetKwd; EqualsRange = Some mEquals; ExternKeyword = None } mkSynBinding (xmlDoc, bindingPat) (vis, $1, $2, mWholeBindLhs, spBind, optReturnType, expr, mRhs, opts, attrs, None, trivia)) localBindingRange, localBindingBuilder } @@ -2897,7 +2899,7 @@ localBinding: let zeroWidthAtEnd = mEquals.EndRange let rhsExpr = arbExpr("localBinding1", zeroWidthAtEnd) let spBind = if IsDebugPointBinding bindingPat rhsExpr then DebugPointAtBinding.Yes mWhole else DebugPointAtBinding.NoneAtLet - let trivia: SynBindingTrivia = { LetKeyword = Some mLetKwd; EqualsRange = Some mEquals } + let trivia: SynBindingTrivia = { LetKeyword = Some mLetKwd; EqualsRange = Some mEquals; ExternKeyword = None } mkSynBinding (xmlDoc, bindingPat) (vis, $1, $2, mBindLhs, spBind, optReturnType, rhsExpr, mRhs, [], attrs, None, trivia)) mWhole, localBindingBuilder } @@ -2910,7 +2912,7 @@ localBinding: let localBindingBuilder = (fun xmlDoc attrs vis mLetKwd -> let spBind = DebugPointAtBinding.Yes (unionRanges mLetKwd mRhs) - let trivia = { LetKeyword = Some mLetKwd; EqualsRange = None } + let trivia = { LetKeyword = Some mLetKwd; EqualsRange = None; ExternKeyword = None } let rhsExpr = arbExpr("localBinding2", mRhs) mkSynBinding (xmlDoc, bindingPat) (vis, $1, $2, mBindLhs, spBind, optReturnType, rhsExpr, mRhs, [], attrs, None, trivia)) mWhole, localBindingBuilder } diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index d6db862529d..202bd49532e 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -122,6 +122,9 @@ SyntaxTree\AttributeTests.fs + + SyntaxTree\ExternTests.fs + FileSystemTests.fs diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index a6713fdbc26..1d2367fb0a6 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -9419,11 +9419,13 @@ FSharp.Compiler.SyntaxTrivia.SynBindingTrivia FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: FSharp.Compiler.SyntaxTrivia.SynBindingTrivia Zero FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: FSharp.Compiler.SyntaxTrivia.SynBindingTrivia get_Zero() FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] EqualsRange +FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] ExternKeyword FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] LetKeyword FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_EqualsRange() +FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_ExternKeyword() FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_LetKeyword() FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: System.String ToString() -FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range]) +FSharp.Compiler.SyntaxTrivia.SynBindingTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range]) FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia: FSharp.Compiler.Text.Range EqualsRange FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia: FSharp.Compiler.Text.Range get_EqualsRange() diff --git a/tests/service/SyntaxTreeTests/ExternTests.fs b/tests/service/SyntaxTreeTests/ExternTests.fs new file mode 100644 index 00000000000..0599307d994 --- /dev/null +++ b/tests/service/SyntaxTreeTests/ExternTests.fs @@ -0,0 +1,21 @@ +module FSharp.Compiler.Service.Tests.SyntaxTreeTests.ExternTests + +open FSharp.Compiler.Service.Tests.Common +open FSharp.Compiler.Syntax +open FSharp.Compiler.SyntaxTrivia +open NUnit.Framework + +[] +let ``extern keyword is present in trivia`` () = + let parseResults = getParseResults "extern void GetProcessHeap()" + + match parseResults with + | ParsedInput.ImplFile(ParsedImplFileInput(contents = [ + SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Let(bindings = [ + SynBinding(trivia = { ExternKeyword = Some mExtern }) + ]) + ]) + ])) -> + assertRange (1, 0) (1, 6) mExtern + | _ -> Assert.Fail $"Could not get valid AST, got {parseResults}" From 89e91ddcb7f3bb3fc01edcc2cfecea7e06d55cae Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 6 Oct 2022 20:13:08 +0100 Subject: [PATCH 31/32] Prevent `dotnet` process spawn on compiler startup (#13969) * don't start process to determine system assemblies * code format * fix build break --- src/Compiler/Driver/CompilerConfig.fs | 13 ++++++------- src/Compiler/Driver/FxResolver.fs | 15 ++++----------- src/Compiler/Driver/FxResolver.fsi | 6 ++++-- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/Compiler/Driver/CompilerConfig.fs b/src/Compiler/Driver/CompilerConfig.fs index 08946b84f63..91a2e9fde3d 100644 --- a/src/Compiler/Driver/CompilerConfig.fs +++ b/src/Compiler/Driver/CompilerConfig.fs @@ -1405,14 +1405,13 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = /// 'framework' reference set that is potentially shared across multiple compilations. member tcConfig.IsSystemAssembly(fileName: string) = try + let dirName = Path.GetDirectoryName fileName + let baseName = FileSystemUtils.fileNameWithoutExtension fileName + FileSystem.FileExistsShim fileName - && ((tcConfig.GetTargetFrameworkDirectories() - |> List.exists (fun clrRoot -> clrRoot = Path.GetDirectoryName fileName)) - || (tcConfig - .FxResolver - .GetSystemAssemblies() - .Contains(FileSystemUtils.fileNameWithoutExtension fileName)) - || tcConfig.FxResolver.IsInReferenceAssemblyPackDirectory fileName) + && ((tcConfig.GetTargetFrameworkDirectories() |> List.contains dirName) + || FxResolver.GetSystemAssemblies().Contains baseName + || FxResolver.IsReferenceAssemblyPackDirectoryApprox dirName) with _ -> false diff --git a/src/Compiler/Driver/FxResolver.fs b/src/Compiler/Driver/FxResolver.fs index 2fa595ee15b..ce2474a7085 100644 --- a/src/Compiler/Driver/FxResolver.fs +++ b/src/Compiler/Driver/FxResolver.fs @@ -611,7 +611,7 @@ type internal FxResolver // A set of assemblies to always consider to be system assemblies. A common set of these can be used a shared // resources between projects in the compiler services. Also all assemblies where well-known system types exist // referenced from TcGlobals must be listed here. - let systemAssemblies = + static let systemAssemblies = HashSet [ // NOTE: duplicates are ok in this list @@ -789,17 +789,10 @@ type internal FxResolver "WindowsBase" ] - member _.GetSystemAssemblies() = systemAssemblies + static member GetSystemAssemblies() = systemAssemblies - member _.IsInReferenceAssemblyPackDirectory fileName = - fxlock.AcquireLock(fun fxtok -> - RequireFxResolverLock(fxtok, "assuming all member require lock") - - match tryGetNetCoreRefsPackDirectoryRoot () |> replayWarnings with - | _, Some root -> - let path = Path.GetDirectoryName(fileName) - path.StartsWith(root, StringComparison.OrdinalIgnoreCase) - | _ -> false) + static member IsReferenceAssemblyPackDirectoryApprox(dirName: string) = + dirName.Contains "Microsoft.NETCore.App.Ref" member _.TryGetSdkDir() = fxlock.AcquireLock(fun fxtok -> diff --git a/src/Compiler/Driver/FxResolver.fsi b/src/Compiler/Driver/FxResolver.fsi index 2bca0a75d8c..d740d2fc497 100644 --- a/src/Compiler/Driver/FxResolver.fsi +++ b/src/Compiler/Driver/FxResolver.fsi @@ -28,12 +28,14 @@ type internal FxResolver = member GetFrameworkRefsPackDirectory: unit -> string option - member GetSystemAssemblies: unit -> HashSet + static member GetSystemAssemblies: unit -> HashSet /// Gets the selected target framework moniker, e.g netcore3.0, net472, and the running rid of the current machine member GetTfmAndRid: unit -> string * string - member IsInReferenceAssemblyPackDirectory: fileName: string -> bool + /// Determines if an assembly is in the core set of assemblies with high likelihood of + /// being shared amongst a set of common scripting references + static member IsReferenceAssemblyPackDirectoryApprox: dirName: string -> bool member TryGetDesiredDotNetSdkVersionForDirectory: unit -> Result From ec4f3269fbb5a10a0bfd5a7a39d35bd53f932fd1 Mon Sep 17 00:00:00 2001 From: Petr Date: Fri, 7 Oct 2022 12:21:08 +0200 Subject: [PATCH 32/32] Removing some broken CodeLens behavior --- .../CodeLens/CodeLensGeneralTagger.fs | 191 ------------------ .../CodeLens/CodeLensProvider.fs | 40 +--- .../src/FSharp.Editor/FSharp.Editor.fsproj | 1 - .../FSharp.Editor/Options/EditorOptions.fs | 2 - .../CodeLensOptionControl.xaml | 3 - 5 files changed, 1 insertion(+), 236 deletions(-) delete mode 100644 vsintegration/src/FSharp.Editor/CodeLens/CodeLensGeneralTagger.fs diff --git a/vsintegration/src/FSharp.Editor/CodeLens/CodeLensGeneralTagger.fs b/vsintegration/src/FSharp.Editor/CodeLens/CodeLensGeneralTagger.fs deleted file mode 100644 index fbc54c1e5fc..00000000000 --- a/vsintegration/src/FSharp.Editor/CodeLens/CodeLensGeneralTagger.fs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace rec Microsoft.VisualStudio.FSharp.Editor - -open System -open System.Windows.Controls -open Microsoft.VisualStudio.Text -open Microsoft.VisualStudio.Text.Editor -open Microsoft.VisualStudio.Text.Formatting -open System.Windows -open Microsoft.VisualStudio.Text.Tagging - -open Microsoft.VisualStudio.FSharp.Editor.Logging - -type CodeLensGeneralTag(width, topSpace, baseline, textHeight, bottomSpace, affinity, tag:obj, providerTag:obj) = - inherit SpaceNegotiatingAdornmentTag(width, topSpace, baseline, textHeight, bottomSpace, affinity, tag, providerTag) - -/// Class which provides support for general code lens -/// Use the methods AddCodeLens and RemoveCodeLens -type CodeLensGeneralTagger (view, buffer) as self = - inherit CodeLensDisplayService(view, buffer, "CodeLens") - - /// The tags changed event to notify if the data for the tags has changed. - let tagsChangedEvent = new Event,SnapshotSpanEventArgs>() - - /// Layouts all stack panels on the line - override self.LayoutUIElementOnLine (view:IWpfTextView) (line:ITextViewLine) (ui:Grid) = - let left, top = - match self.UiElementNeighbour.TryGetValue ui with - | true, parent -> - let left = Canvas.GetLeft parent - let top = Canvas.GetTop parent - let width = parent.ActualWidth -#if DEBUG - logInfof "Width of parent: %.4f" width -#endif - left + width, top - | _ -> - try - // Get the real offset so that the code lens are placed respectively to their content - let offset = - [0..line.Length - 1] |> Seq.tryFind (fun i -> not (Char.IsWhiteSpace (line.Start.Add(i).GetChar()))) - |> Option.defaultValue 0 - - let realStart = line.Start.Add(offset) - let g = view.TextViewLines.GetCharacterBounds(realStart) - // WORKAROUND VS BUG, left cannot be zero if the offset is creater than zero! - // Calling the method twice fixes this bug and ensures that all values are correct. - // Okay not really :( Must be replaced later with an own calculation depending on editor font settings! - if 7 * offset > int g.Left then -#if DEBUG - logErrorf "Incorrect return from geometry measure" -#endif - Canvas.GetLeft ui, g.Top - else - g.Left, g.Top - with e -> -#if DEBUG - logExceptionWithContext (e, "Error in layout ui element on line") -#else - ignore e -#endif - Canvas.GetLeft ui, Canvas.GetTop ui - Canvas.SetLeft(ui, left) - Canvas.SetTop(ui, top) - - override self.AsyncCustomLayoutOperation _ _ = - asyncMaybe { - // Suspend 16 ms, instantly applying the layout to the adornment elements isn't needed - // and would consume too much performance - do! Async.Sleep(16) |> liftAsync // Skip at least one frames - do! Async.SwitchToContext self.UiContext |> liftAsync - let layer = self.CodeLensLayer - - do! Async.Sleep(495) |> liftAsync - - // WORKAROUND FOR VS BUG - // The layout changed event may not provide us all real changed lines so - // we take care of this on our own. - let visibleSpan = - let first, last = - view.TextViewLines.FirstVisibleLine, - view.TextViewLines.LastVisibleLine - SnapshotSpan(first.Start, last.End) - let customVisibleLines = view.TextViewLines.GetTextViewLinesIntersectingSpan visibleSpan - let isLineVisible (line:ITextViewLine) = line.IsValid - let linesToProcess = customVisibleLines |> Seq.filter isLineVisible - - for line in linesToProcess do - try - match line.GetAdornmentTags self |> Seq.tryHead with - | Some (:? seq as stackPanels) -> - for stackPanel in stackPanels do - if stackPanel |> self.AddedAdornments.Contains |> not then - layer.AddAdornment(AdornmentPositioningBehavior.OwnerControlled, Nullable(), - self, stackPanel, AdornmentRemovedCallback(fun _ _ -> ())) |> ignore - self.AddedAdornments.Add stackPanel |> ignore - | _ -> () - with e -> -#if DEBUG - logExceptionWithContext (e, "LayoutChanged, processing new visible lines") -#else - ignore e -#endif - } |> Async.Ignore - - override self.AddUiElementToCodeLens (trackingSpan:ITrackingSpan, uiElement:UIElement)= - base.AddUiElementToCodeLens (trackingSpan, uiElement) // We do the same as the base call execpt that we need to notify that the tag needs to be refreshed. - tagsChangedEvent.Trigger(self, SnapshotSpanEventArgs(trackingSpan.GetSpan(buffer.CurrentSnapshot))) - - override self.RemoveUiElementFromCodeLens (trackingSpan:ITrackingSpan, uiElement:UIElement) = - base.RemoveUiElementFromCodeLens (trackingSpan, uiElement) - tagsChangedEvent.Trigger(self, SnapshotSpanEventArgs(trackingSpan.GetSpan(buffer.CurrentSnapshot))) // Need to refresh the tag. - - interface ITagger with - [] - override _.TagsChanged = tagsChangedEvent.Publish - - /// Returns the tags which reserve the correct space for adornments - /// Notice, it's asumed that the data in the collection is valid. - override _.GetTags spans = - try - seq { - for span in spans do - let snapshot = span.Snapshot - let lineNumber = - try - snapshot.GetLineNumberFromPosition(span.Start.Position) - with e -> -#if DEBUG - logExceptionWithContext (e, "line number tagging") -#else - ignore e -#endif - 0 - if self.TrackingSpans.ContainsKey(lineNumber) && self.TrackingSpans.[lineNumber] |> Seq.isEmpty |> not then - - let tagSpan = snapshot.GetLineFromLineNumber(lineNumber).Extent - let stackPanels = - self.TrackingSpans.[lineNumber] - |> Seq.map (fun trackingSpan -> - let success, res = self.UiElements.TryGetValue trackingSpan - if success then res else null - ) - |> Seq.filter (isNull >> not) - let span = - try - tagSpan.TranslateTo(span.Snapshot, SpanTrackingMode.EdgeExclusive) - with e -> -#if DEBUG - logExceptionWithContext (e, "tag span translation") -#else - ignore e -#endif - tagSpan - let sizes = - try - stackPanels |> Seq.map (fun ui -> - ui.Measure(Size(10000., 10000.)) - ui.DesiredSize ) - with e -> -#if DEBUG - logExceptionWithContext (e, "internal tagging") -#else - ignore e -#endif - Seq.empty - let height = - try - sizes - |> Seq.map (fun size -> size.Height) - |> Seq.sortDescending - |> Seq.tryHead - |> Option.defaultValue 0. - with e -> -#if DEBUG - logExceptionWithContext (e, "height tagging") -#else - ignore e -#endif - 0.0 - - yield TagSpan(span, CodeLensGeneralTag(0., height, 0., 0., 0., PositionAffinity.Predecessor, stackPanels, self)) :> ITagSpan - } - with e -> -#if DEBUG - logErrorf "Error in code lens get tags %A" e -#else - ignore e -#endif - Seq.empty \ No newline at end of file diff --git a/vsintegration/src/FSharp.Editor/CodeLens/CodeLensProvider.fs b/vsintegration/src/FSharp.Editor/CodeLens/CodeLensProvider.fs index 7c015abad27..abfa68e08b1 100644 --- a/vsintegration/src/FSharp.Editor/CodeLens/CodeLensProvider.fs +++ b/vsintegration/src/FSharp.Editor/CodeLens/CodeLensProvider.fs @@ -15,7 +15,6 @@ open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Editor.Shared.Utilities [)>] [)>] -[)>] [] [] type internal CodeLensProvider @@ -33,28 +32,10 @@ type internal CodeLensProvider | true, document -> Some document | _ -> None - let taggers = ResizeArray() let lineLensProviders = ResizeArray() let componentModel = Package.GetGlobalService(typeof) :?> ComponentModelHost.IComponentModel let workspace = componentModel.GetService() - let tryGetCodeLensTagger wpfView buffer = - taggers - |> Seq.tryFind (fun (view, _) -> view = wpfView) - |> Option.map (fun (_, (tagger, _)) -> tagger) - |> Option.orElse - (textDocumentFactory - |> tryGetTextDocument buffer - |> Option.map (fun document -> workspace.CurrentSolution.GetDocumentIdsWithFilePath document.FilePath) - |> Option.bind Seq.tryHead - |> Option.map (fun documentId -> - let tagger = CodeLensGeneralTagger(wpfView, buffer) - let service = FSharpCodeLensService(serviceProvider, workspace, documentId, buffer, metadataAsSource, componentModel.GetService(), typeMap, tagger, settings) - let provider = (wpfView, (tagger, service)) - wpfView.Closed.Add (fun _ -> taggers.Remove provider |> ignore) - taggers.Add provider - tagger)) - let addLineLensProvider wpfView buffer = textDocumentFactory |> tryGetTextDocument buffer @@ -66,33 +47,14 @@ type internal CodeLensProvider wpfView.Closed.Add (fun _ -> lineLensProviders.Remove provider |> ignore) lineLensProviders.Add(provider)) - [); Name("CodeLens"); - Order(Before = PredefinedAdornmentLayers.Text); - TextViewRole(PredefinedTextViewRoles.Document)>] - member val CodeLensAdornmentLayerDefinition : AdornmentLayerDefinition = null with get, set - [); Name("LineLens"); Order(Before = PredefinedAdornmentLayers.Text); TextViewRole(PredefinedTextViewRoles.Document)>] member val LineLensAdornmentLayerDefinition : AdornmentLayerDefinition = null with get, set - interface IViewTaggerProvider with - override _.CreateTagger(view, buffer) = - if settings.CodeLens.Enabled && not settings.CodeLens.ReplaceWithLineLens then - let wpfView = - match view with - | :? IWpfTextView as view -> view - | _ -> failwith "error" - - match tryGetCodeLensTagger wpfView buffer with - | Some tagger -> box tagger :?> _ - | None -> null - else - null - interface IWpfTextViewCreationListener with override _.TextViewCreated view = - if settings.CodeLens.Enabled && settings.CodeLens.ReplaceWithLineLens then + if settings.CodeLens.Enabled then let provider = lineLensProviders |> Seq.tryFind (fun (v, _) -> v = view) diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index 156c187769d..c3fbf9a4258 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -126,7 +126,6 @@ - diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs index b0c94ecc865..b2df69f41eb 100644 --- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs +++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs @@ -75,13 +75,11 @@ type LanguageServicePerformanceOptions = [] type CodeLensOptions = { Enabled : bool - ReplaceWithLineLens: bool UseColors: bool Prefix : string } static member Default = { Enabled = false UseColors = false - ReplaceWithLineLens = true Prefix = "// " } [] diff --git a/vsintegration/src/FSharp.UIResources/CodeLensOptionControl.xaml b/vsintegration/src/FSharp.UIResources/CodeLensOptionControl.xaml index 7e62f575fd6..750cc260b43 100644 --- a/vsintegration/src/FSharp.UIResources/CodeLensOptionControl.xaml +++ b/vsintegration/src/FSharp.UIResources/CodeLensOptionControl.xaml @@ -27,9 +27,6 @@ -