diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 8bb334d1e44..e1dcf31c425 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -14,6 +14,7 @@ RUN apt-get update \ && apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \ # Verify bash, git, process tools, lsb-release (common in install instructions for CLIs) installed && apt-get -y install bash git openssh-client less iproute2 procps lsb-release \ + && apt-get -y install gnupg \ # Clean up && apt-get autoremove -y \ && apt-get clean -y \ @@ -23,4 +24,4 @@ RUN apt-get update \ ENV DEBIAN_FRONTEND=dialog # Make sure we can build using plain dotnet -ENV BUILDING_USING_DOTNET="true" \ No newline at end of file +ENV BUILDING_USING_DOTNET="true" diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6a15d101828..7ec6813a99c 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -20,14 +20,16 @@ "type": "shell", "args": [ "build", - "-c Debug", + "-c", + "Debug", "FSharp.Compiler.Service.sln" ], "windows": { "command": "dotnet", "args": [ "build", - "-c Debug", + "-c", + "Debug", "FSharp.Compiler.Service.sln" ], }, @@ -40,14 +42,16 @@ "type": "shell", "args": [ "build", - "-c Release", + "-c", + "Release", "FSharp.Compiler.Service.sln" ], "windows": { "command": "dotnet", "args": [ "build", - "-c Release", + "-c", + "Release", "FSharp.Compiler.Service.sln" ], }, diff --git a/DEVGUIDE.md b/DEVGUIDE.md index 8e043b4dd5b..aca6b5c01d6 100644 --- a/DEVGUIDE.md +++ b/DEVGUIDE.md @@ -122,6 +122,12 @@ You can find all test options as separate flags. For example `build -testAll`: Running any of the above will build the latest changes and run tests against them. +## Using your custom compiler to build this repository + +By removing all the subfolders called `Proto` under `artifacts` and running the `build` script again, the proto compiler will include your changes. + +Once the "proto" compiler is built, it won't be built again, so you may want to perform those steps again to ensure your changes don't break building the compiler itself. + ## Using your custom compiler to build other projects Building the compiler using `build.cmd` or `build.sh` will output artifacts in `artifacts\bin`. diff --git a/INTERNAL.md b/INTERNAL.md index 41d34dbcb18..f56689e538b 100644 --- a/INTERNAL.md +++ b/INTERNAL.md @@ -98,29 +98,6 @@ Since github issue filtering is currently not flexible enough, that query was ge Invoke-WebRequest -Uri "https://api.github.com/repos/dotnet/fsharp/labels?per_page=100" | ConvertFrom-Json | % { $_.name } | ? { $_.StartsWith("Area-") } | % { Write-Host -NoNewLine ('-label:"' + $_ + '" ') } ``` -## Less interesting links - -[FSharp.Core (Official NuGet Release)](https://dev.azure.com/dnceng/internal/_release?_a=releases&definitionId=72). -Uploads the final `FSharp.Core` package from the specified build to NuGet. This should only be run when we know for -certain which build produced the final offical package. - -[FSharp.Core (Preview NuGet Release)](https://dev.azure.com/dnceng/internal/_release?_a=releases&definitionId=92). -Uploads the preview `FSharp.Core.*-beta.*` package from the specified build to NuGet. This should be run every time -a new SDK preview is released. - -[FCS (Official NuGet Release)](https://dev.azure.com/dnceng/internal/_release?view=mine&_a=releases&definitionId=99). -Uploads the final `FSharp.Compiler.Service` package from the specified build to NuGet. Only builds from the `release/fcs` -branch can be selected. This should only be run when we're fairly certain that the package is complete. - -[FCS (Preview NuGet Release)](https://dev.azure.com/dnceng/internal/_release?view=mine&_a=releases&definitionId=98). -Uploads the preview `FSharp.Compiler.Service.*-preview.*` package from the specified build to NuGet. Only builds from the -`main` branch can be selected. This can be run whenever we think we're ready to preview a new FCS build. - -[Nightly VSIX (main) uploader](https://dev.azure.com/dnceng/internal/_release?_a=releases&definitionId=70). Uploads -a package from every build of `main` to the [Nightly VSIX feed](README.md#using-nightly-releases-in-visual-studio). - -[Nightly VSIX (preview) uploader](https://dev.azure.com/dnceng/internal/_release?_a=releases&definitionId=71). Uploads -a package from every build of the branch that corresponds to the current Visual Studio preview to the -[Preview VSIX feed](README.md#using-nightly-releases-in-visual-studio). +## Other links [Internal source mirror](https://dev.azure.com/dnceng/internal/_git/dotnet-fsharp). diff --git a/README.md b/README.md index be1f103e9ef..58a61e349e5 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ Even if you find a single-character typo, we're happy to take the change! Althou ``` +**NOTE:** Official NuGet releases of FCS and FSharp.Core are synched with SDK releases (on purpose - we want to be in sync). Nightly packages release to Azure feeds on every successful insertion. + ## Branches These are the branches in use: diff --git a/src/Compiler/Checking/CheckComputationExpressions.fs b/src/Compiler/Checking/CheckComputationExpressions.fs index e27dcffc7bf..82403341f7d 100644 --- a/src/Compiler/Checking/CheckComputationExpressions.fs +++ b/src/Compiler/Checking/CheckComputationExpressions.fs @@ -2210,7 +2210,7 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = let env = { env with eContextInfo = ContextInfo.SequenceExpression genOuterTy } - if enableImplicitYield then + if enableImplicitYield then let hasTypeUnit, expr, tpenv = TryTcStmt cenv env tpenv comp if hasTypeUnit then Choice2Of2 expr, tpenv @@ -2218,6 +2218,7 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp (overallTy: OverallTy) m = let genResultTy = NewInferenceType g let mExpr = expr.Range UnifyTypes cenv env mExpr genOuterTy (mkSeqTy cenv.g genResultTy) + let expr, tpenv = TcExprFlex cenv flex true genResultTy env tpenv comp let exprTy = tyOfExpr cenv.g expr AddCxTypeMustSubsumeType env.eContextInfo env.DisplayEnv cenv.css mExpr NoTrace genResultTy exprTy let resExpr = mkCallSeqSingleton cenv.g mExpr genResultTy (mkCoerceExpr(expr, genResultTy, mExpr, exprTy)) diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index 381c3789acf..c7062e058d2 100644 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -38,7 +38,7 @@ module internal PrintUtilities = let squareAngleL x = LeftL.leftBracketAngle ^^ x ^^ RightL.rightBracketAngle - let angleL x = sepL leftAngle ^^ x ^^ rightL rightAngle + let angleL x = SepL.leftAngle ^^ x ^^ RightL.rightAngle let braceL x = wordL leftBrace ^^ x ^^ wordL rightBrace @@ -113,9 +113,9 @@ module internal PrintUtilities = let layout = argTyL ^^ (if idx = lastIndex then - wordL (tagPunctuation retTyDelim) + wordL retTyDelim else - wordL (tagPunctuation "->")) + WordL.arrow) isTupled, layout) |> List.rev @@ -486,7 +486,7 @@ module PrintTypes = s |> tagNumericLiteral | Const.Char c -> "'" + c.ToString() + "'" |> tagStringLiteral | Const.String bs -> "\"" + bs + "\"" |> tagNumericLiteral - | Const.Unit -> "()" |> tagPunctuation + | Const.Unit -> punctuationUnit | Const.Decimal bs -> string bs + "M" |> tagNumericLiteral // either "null" or "the default value for a struct" | Const.Zero -> tagKeyword(if isRefTy g ty then "null" else "default") @@ -555,14 +555,14 @@ module PrintTypes = // Detect 'typeof' calls | TypeOfExpr denv.g ty -> - LeftL.keywordTypeof ^^ wordL (tagPunctuation "<") ^^ layoutType denv ty ^^ rightL (tagPunctuation ">") + LeftL.keywordTypeof ^^ WordL.leftAngle ^^ layoutType denv ty ^^ RightL.rightAngle // Detect 'typedefof' calls | TypeDefOfExpr denv.g ty -> - LeftL.keywordTypedefof ^^ wordL (tagPunctuation "<") ^^ layoutType denv ty ^^ rightL (tagPunctuation ">") + LeftL.keywordTypedefof ^^ WordL.leftAngle ^^ layoutType denv ty ^^ RightL.rightAngle | Expr.Op (TOp.Coerce, [tgtTy;_], [arg2], _) -> - leftL (tagPunctuation "(") ^^ layoutAttribArg denv arg2 ^^ wordL (tagPunctuation ":>") ^^ layoutType denv tgtTy ^^ rightL (tagPunctuation ")") + LeftL.leftParen ^^ layoutAttribArg denv arg2 ^^ wordL (tagPunctuation ":>") ^^ layoutType denv tgtTy ^^ RightL.rightParen | AttribBitwiseOrExpr denv.g (arg1, arg2) -> layoutAttribArg denv arg1 ^^ wordL (tagPunctuation "|||") ^^ layoutAttribArg denv arg2 @@ -580,7 +580,7 @@ module PrintTypes = props |> List.map (fun (AttribNamedArg(name,_, _, AttribExpr(e1, _))) -> wordL (tagProperty name) ^^ WordL.equals ^^ layoutAttribArg denv e1) - sepListL (rightL (tagPunctuation ",")) (argsL @ propsL) + sepListL RightL.comma (argsL @ propsL) /// Layout an attribute 'Type(arg1, ..., argN)' and layoutAttrib denv (Attrib(tcref, _, args, props, _, _, _)) = @@ -619,7 +619,7 @@ module PrintTypes = wordL (tagNumericLiteral str) | ILAttribElem.Null -> wordL (tagKeyword "null") | ILAttribElem.Array (_, xs) -> - leftL (tagPunctuation "[|") ^^ semiListL (List.map (layoutILAttribElement denv) xs) ^^ RightL.rightBracketBar + LeftL.leftBracketBar ^^ semiListL (List.map (layoutILAttribElement denv) xs) ^^ RightL.rightBracketBar | ILAttribElem.Type (Some ty) -> LeftL.keywordTypeof ^^ SepL.leftAngle ^^ PrintIL.layoutILType denv [] ty ^^ RightL.rightAngle | ILAttribElem.Type None -> wordL (tagText "") @@ -628,7 +628,7 @@ module PrintTypes = | ILAttribElem.TypeRef None -> emptyL and layoutILAttrib denv (ty, args) = - let argsL = bracketL (sepListL (rightL (tagPunctuation ",")) (List.map (layoutILAttribElement denv) args)) + let argsL = bracketL (sepListL RightL.comma (List.map (layoutILAttribElement denv) args)) PrintIL.layoutILType denv [] ty ++ argsL /// Layout '[]' above another block @@ -676,12 +676,12 @@ module PrintTypes = match attrsL with | [] -> restL - | _ -> squareAngleL (sepListL (rightL (tagPunctuation ";")) attrsL) @@ restL + | _ -> squareAngleL (sepListL RightL.semicolon attrsL) @@ restL and layoutTyparAttribs denv kind attrs restL = match attrs, kind with | [], TyparKind.Type -> restL - | _, _ -> squareAngleL (sepListL (rightL (tagPunctuation ";")) ((match kind with TyparKind.Type -> [] | TyparKind.Measure -> [wordL (tagText "Measure")]) @ List.map (layoutAttrib denv) attrs)) ^^ restL + | _, _ -> squareAngleL (sepListL RightL.semicolon ((match kind with TyparKind.Type -> [] | TyparKind.Measure -> [wordL (tagText "Measure")]) @ List.map (layoutAttrib denv) attrs)) ^^ restL and layoutTyparRef denv (typar: Typar) = tagTypeParameter @@ -744,7 +744,7 @@ module PrintTypes = if denv.abbreviateAdditionalConstraints then wordL (tagKeyword "when") ^^ wordL(tagText "") elif denv.shortConstraints then - leftL (tagPunctuation "(") ^^ wordL (tagKeyword "requires") ^^ sepListL (wordL (tagKeyword "and")) cxsL ^^ rightL (tagPunctuation ")") + LeftL.leftParen ^^ wordL (tagKeyword "requires") ^^ sepListL (wordL (tagKeyword "and")) cxsL ^^ RightL.rightParen else wordL (tagKeyword "when") ^^ sepListL (wordL (tagKeyword "and")) cxsL @@ -765,9 +765,9 @@ module PrintTypes = | TyparConstraint.IsEnum(ty, _) -> if denv.shortConstraints then - [wordL (tagKeyword "enum")] + [ WordL.keywordEnum ] else - [longConstraintPrefix (layoutTypeAppWithInfoAndPrec denv env (wordL (tagKeyword "enum")) 2 true [ty])] + [longConstraintPrefix (layoutTypeAppWithInfoAndPrec denv env WordL.keywordEnum 2 true [ty])] | TyparConstraint.SupportsComparison _ -> if denv.shortConstraints then @@ -806,10 +806,10 @@ module PrintTypes = if denv.shortConstraints then [wordL (tagText "reference type")] else - [(wordL (tagKeyword "not") ^^ wordL(tagKeyword "struct")) |> longConstraintPrefix] + [(wordL (tagKeyword "not") ^^ WordL.keywordStruct) |> longConstraintPrefix] | TyparConstraint.SimpleChoice(tys, _) -> - [bracketL (sepListL (sepL (tagPunctuation "|")) (List.map (layoutTypeWithInfo denv env) tys)) |> longConstraintPrefix] + [bracketL (sepListL (sepL bar) (List.map (layoutTypeWithInfo denv env) tys)) |> longConstraintPrefix] | TyparConstraint.RequiresDefaultConstructor _ -> if denv.shortConstraints then @@ -854,13 +854,13 @@ module PrintTypes = | [] -> retTyL | _ -> let argTysL = layoutTypesWithInfoAndPrec denv env 2 (wordL (tagPunctuation "*")) argTys - curriedLayoutsL "->" [argTysL] retTyL + curriedLayoutsL arrow [argTysL] retTyL let getterSetterL = match memFlags.MemberKind with | SynMemberKind.PropertyGet when not argTys.IsEmpty -> - wordL (tagKeyword "with") ^^ wordL (tagText "get") + WordL.keywordWith ^^ WordL.keywordGet | SynMemberKind.PropertySet -> - wordL (tagKeyword "with") ^^ wordL (tagText "set") + WordL.keywordWith ^^ WordL.keywordSet | _ -> emptyL (tysL |> addColonL) --- bracketL (stat ++ (nameL |> addColonL) --- sigL --- getterSetterL) @@ -881,20 +881,20 @@ module PrintTypes = List.map (fun (c, e) -> measureToPowerL (unconL c) (NegRational e)) negcs) match (negvs, negcs) with | [], [] -> (match posvs, poscs with [], [] -> wordL (tagNumericLiteral "1") | _ -> prefix) - | _ -> prefix ^^ sepL (tagPunctuation "/") ^^ (if List.length negvs + List.length negcs > 1 then sepL (tagPunctuation "(") ^^ postfix ^^ sepL (tagPunctuation ")") else postfix) + | _ -> prefix ^^ sepL (tagPunctuation "/") ^^ (if List.length negvs + List.length negcs > 1 then SepL.leftParen ^^ postfix ^^ SepL.rightParen else postfix) /// Layout type arguments, either NAME or (ty, ..., ty) NAME *) and layoutTypeAppWithInfoAndPrec denv env tcL prec prefix argTys = if prefix then match argTys with | [] -> tcL - | [argTy] -> tcL ^^ sepL (tagPunctuation "<") ^^ (layoutTypeWithInfoAndPrec denv env 4 argTy) ^^ rightL (tagPunctuation">") - | _ -> bracketIfL (prec <= 1) (tcL ^^ angleL (layoutTypesWithInfoAndPrec denv env 2 (sepL (tagPunctuation ",")) argTys)) + | [argTy] -> tcL ^^ SepL.leftAngle ^^ (layoutTypeWithInfoAndPrec denv env 4 argTy) ^^ RightL.rightAngle + | _ -> bracketIfL (prec <= 1) (tcL ^^ angleL (layoutTypesWithInfoAndPrec denv env 2 SepL.comma argTys)) else match argTys with | [] -> tcL | [arg] -> layoutTypeWithInfoAndPrec denv env 2 arg ^^ tcL - | args -> bracketIfL (prec <= 1) (bracketL (layoutTypesWithInfoAndPrec denv env 2 (sepL (tagPunctuation ",")) args) --- tcL) + | args -> bracketIfL (prec <= 1) (bracketL (layoutTypesWithInfoAndPrec denv env 2 SepL.comma args) --- tcL) /// Layout a type, taking precedence into account to insert brackets where needed and layoutTypeWithInfoAndPrec denv env prec ty = @@ -957,7 +957,7 @@ module PrintTypes = // Layout a tuple type | TType_anon (anonInfo, tys) -> - let core = sepListL (rightL (tagPunctuation ";")) (List.map2 (fun nm ty -> wordL (tagField nm) ^^ rightL (tagPunctuation ":") ^^ layoutTypeWithInfoAndPrec denv env prec ty) (Array.toList anonInfo.SortedNames) tys) + let core = sepListL RightL.semicolon (List.map2 (fun nm ty -> wordL (tagField nm) ^^ RightL.colon ^^ layoutTypeWithInfoAndPrec denv env prec ty) (Array.toList anonInfo.SortedNames) tys) if evalAnonInfoIsStruct anonInfo then WordL.keywordStruct --- braceBarL core else @@ -976,14 +976,14 @@ module PrintTypes = let tauL = layoutTypeWithInfoAndPrec denv env prec tau match tps with | [] -> tauL - | [h] -> layoutTyparRefWithInfo denv env h ^^ rightL (tagPunctuation ".") --- tauL - | h :: t -> spaceListL (List.map (layoutTyparRefWithInfo denv env) (h :: t)) ^^ rightL (tagPunctuation ".") --- tauL + | [h] -> layoutTyparRefWithInfo denv env h ^^ rightL dot --- tauL + | h :: t -> spaceListL (List.map (layoutTyparRefWithInfo denv env) (h :: t)) ^^ rightL dot --- tauL | TType_fun _ -> let argTys, retTy = stripFunTy g ty let retTyL = layoutTypeWithInfoAndPrec denv env 5 retTy let argTysL = argTys |> List.map (layoutTypeWithInfoAndPrec denv env 4) - let funcTyL = curriedLayoutsL "->" argTysL retTyL + let funcTyL = curriedLayoutsL arrow argTysL retTyL bracketIfL (prec <= 4) funcTyL // Layout a type variable . @@ -1013,7 +1013,7 @@ module PrintTypes = let attrsL = [ for attr in attribs do layoutAttrib denv attr ] - squareAngleL (sepListL (rightL (tagPunctuation ";")) attrsL) + squareAngleL (sepListL RightL.semicolon attrsL) // Format each argument, including its name and type let layoutArgInfo denv env (ty, argInfo: ArgReprInfo) = @@ -1056,15 +1056,15 @@ module PrintTypes = match genParamTys with | [] -> emptyL | _ -> - wordL (tagPunctuation "<") + WordL.leftAngle ^^ ( genParamTys |> List.map (layoutTypeWithInfoAndPrec denv env 4) - |> sepListL (wordL (tagPunctuation ",")) + |> sepListL (wordL comma) ) ^^ - wordL (tagPunctuation ">") + wordL rightAngle /// Layout a single type used as the type of a member or value let layoutTopType denv env argInfos retTy cxs = @@ -1073,7 +1073,7 @@ module PrintTypes = match argInfos with | [] -> retTyL --- cxsL | _ -> - let retTyDelim = if denv.useColonForReturnType then ":" else "->" + let retTyDelim = if denv.useColonForReturnType then colon else arrow let allArgsL = layoutCurriedArgInfos denv env argInfos curriedLayoutsL retTyDelim allArgsL retTyL --- cxsL @@ -1090,7 +1090,7 @@ module PrintTypes = | _ -> let tpcsL = layoutConstraintsWithInfo denv env tpcs - let coreL = sepListL (sepL (tagPunctuation ",")) (List.map (layoutTyparRefWithInfo denv env) typars) + let coreL = sepListL SepL.comma (List.map (layoutTyparRefWithInfo denv env) typars) if prefix || not (isNil tpcs) then nmL ^^ angleL (coreL --- tpcsL) else @@ -1653,7 +1653,7 @@ module InfoMemberPrinting = match methInfo with | DefaultStructCtor _ -> let prettyTyparInst, _ = PrettyTypes.PrettifyInst amap.g typarInst - let resL = PrintTypes.layoutTyconRef denv methInfo.ApparentEnclosingTyconRef ^^ wordL (tagPunctuation "()") + let resL = PrintTypes.layoutTyconRef denv methInfo.ApparentEnclosingTyconRef ^^ wordL punctuationUnit prettyTyparInst, resL | FSMeth(_, _, vref, _) -> let prettyTyparInst, resL = PrintTastMemberOrVals.prettyLayoutOfValOrMember { denv with showMemberContainers=true } infoReader typarInst vref @@ -1676,11 +1676,11 @@ module InfoMemberPrinting = let getterSetter = match pinfo.HasGetter, pinfo.HasSetter with | true, false -> - wordL (tagKeyword "with") ^^ wordL (tagText "get") + WordL.keywordWith ^^ WordL.keywordGet | false, true -> - wordL (tagKeyword "with") ^^ wordL (tagText "set") + WordL.keywordWith ^^ WordL.keywordSet | true, true -> - wordL (tagKeyword "with") ^^ wordL (tagText "get, set") + WordL.keywordWith ^^ wordL (tagText "get, set") | false, false -> emptyL @@ -1827,7 +1827,7 @@ module TastDefinitionPrinting = | Some vref -> match pinfo with | DifferentGetterAndSetter(getValRef, setValRef) -> - let getSuffix = if pinfo.IsIndexer then emptyL else wordL (tagKeyword "with") ^^ wordL (tagText "get") + let getSuffix = if pinfo.IsIndexer then emptyL else WordL.keywordWith ^^ WordL.keywordGet [ PrintTastMemberOrVals.prettyLayoutOfValOrMemberNoInst denv infoReader getValRef ^^ getSuffix PrintTastMemberOrVals.prettyLayoutOfValOrMemberNoInst denv infoReader setValRef @@ -1835,7 +1835,7 @@ module TastDefinitionPrinting = | _ -> let propL = PrintTastMemberOrVals.prettyLayoutOfValOrMemberNoInst denv infoReader vref if pinfo.HasGetter && pinfo.HasSetter && not pinfo.IsIndexer && isPublicGetterSetter pinfo.GetterMethod pinfo.SetterMethod then - [ propL ^^ wordL (tagKeyword "with") ^^ wordL (tagText "get, set") ] + [ propL ^^ WordL.keywordWith ^^ wordL (tagText "get, set") ] else [ propL ] | None -> @@ -1928,7 +1928,7 @@ module TastDefinitionPrinting = let iimplsLs = iimpls - |> List.map (fun intfTy -> wordL (tagKeyword (if isInterfaceTy g ty then "inherit" else "interface")) -* layoutType denv intfTy) + |> List.map (fun intfTy -> (if isInterfaceTy g ty then WordL.keywordInherit else WordL.keywordInterface) -* layoutType denv intfTy) let props = GetImmediateIntrinsicPropInfosOfType (None, ad) g amap m ty @@ -2060,7 +2060,7 @@ module TastDefinitionPrinting = let inheritsL = inherits - |> List.map (fun super -> wordL (tagKeyword "inherit") ^^ (layoutType denv super)) + |> List.map (fun super -> WordL.keywordInherit ^^ (layoutType denv super)) let allDecls = inheritsL @ iimplsLs @ ctorLs @ instanceValLs @ methLs @ ilFieldsL @ propLs @ eventLs @ staticValLs @ nestedTypeLs @@ -2300,7 +2300,7 @@ module TastDefinitionPrinting = if mspec.IsNamespace then // This is a container namespace. We print the header when we get to the first concrete module. let pathL = path |> List.map (ConvertLogicalNameToDisplayLayout (tagNamespace >> wordL)) - wordL (tagKeyword "namespace") ^^ sepListL SepL.dot pathL + WordL.keywordNamespace ^^ sepListL SepL.dot pathL else // This is a module let name = path |> List.last @@ -2314,7 +2314,7 @@ module TastDefinitionPrinting = let innerPathL = innerPath |> List.map (ConvertLogicalNameToDisplayLayout (tagNamespace >> wordL)) sepListL SepL.dot innerPathL ^^ SepL.dot ^^ nameL - let modNameL = wordL (tagKeyword "module") ^^ nameL + let modNameL = WordL.keywordModule ^^ nameL let modNameEqualsL = modNameL ^^ WordL.equals let modIsEmpty = mspec.ModuleOrNamespaceType.AllEntities |> Seq.isEmpty && @@ -2326,7 +2326,7 @@ module TastDefinitionPrinting = // If so print a "module" declaration modNameL elif modIsEmpty then - modNameEqualsL ^^ wordL (tagKeyword "begin") ^^ WordL.keywordEnd + modNameEqualsL ^^ WordL.keywordBegin ^^ WordL.keywordEnd else // Otherwise this is an outer module contained immediately in a namespace // We already printed the namespace declaration earlier. So just print the @@ -2483,7 +2483,7 @@ module InferredSigPrinting = let basic = imdefL denv def let attribs: Attribs = List.append mspec.Attribs moduleAttribs let modNameL = - wordL (tagKeyword "module") ^^ nmL + WordL.keywordModule ^^ nmL |> layoutAttribs denv None false mspec.TypeOrMeasureKind attribs let basicL = modNameL @@ basic layoutXmlDoc denv true mspec.XmlDoc basicL @@ -2495,7 +2495,7 @@ module InferredSigPrinting = let pathL = innerPath |> List.map (fst >> ConvertLogicalNameToDisplayLayout (tagNamespace >> wordL)) // This is a container namespace. We print the header when we get to the first concrete module. let headerL = - wordL (tagKeyword "namespace") ^^ sepListL SepL.dot pathL + WordL.keywordNamespace ^^ sepListL SepL.dot pathL headerL @@* basic else // This is a namespace that only contains namespaces. Skip the header @@ -2511,7 +2511,7 @@ module InferredSigPrinting = let denv = denv.AddAccessibility mspec.Accessibility let basic = imdefL denv def let modNameL = - wordL (tagKeyword "module") ^^ nmL + WordL.keywordModule ^^ nmL |> layoutAttribs denv None false mspec.TypeOrMeasureKind mspec.Attribs let modNameEqualsL = modNameL ^^ WordL.equals let isNamespace = function | Namespace _ -> true | _ -> false @@ -2540,7 +2540,7 @@ module InferredSigPrinting = else // OK, this is a nested module, with indentation if isEmptyL basic then - modNameEqualsL ^^ wordL (tagKeyword "begin") @@* basic @@* WordL.keywordEnd + modNameEqualsL ^^ WordL.keywordBegin @@* basic @@* WordL.keywordEnd else modNameEqualsL @@* basic layoutXmlDoc denv true mspec.XmlDoc basicL @@ -2551,11 +2551,11 @@ module InferredSigPrinting = let keyword = if not mspec.IsImplicitNamespace && mspec.IsNamespace then - "namespace" + WordL.keywordNamespace else - "module" + WordL.keywordModule - wordL (tagKeyword keyword) ^^ sepListL SepL.dot pathL + keyword ^^ sepListL SepL.dot pathL match expr with | EmptyModuleOrNamespaces mspecs when showHeader -> @@ -2575,7 +2575,7 @@ module PrintData = match expr with | Expr.Const (c, _, ty) -> if isEnumTy denv.g ty then - wordL (tagKeyword "enum") ^^ angleL (layoutType denv ty) ^^ bracketL (layoutConst denv.g ty c) + WordL.keywordEnum ^^ angleL (layoutType denv ty) ^^ bracketL (layoutConst denv.g ty c) else layoutConst denv.g ty c @@ -2603,17 +2603,17 @@ module PrintData = | Expr.Op (TOp.Recd (_, tc), _, xs, _) -> let fields = tc.TrueInstanceFieldsAsList - let lay fs x = (wordL (tagRecordField fs.rfield_id.idText) ^^ sepL (tagPunctuation "=")) --- (dataExprL denv x) + let lay fs x = (wordL (tagRecordField fs.rfield_id.idText) ^^ sepL equals) --- (dataExprL denv x) braceL (semiListL (List.map2 lay fields xs)) | Expr.Op (TOp.ValFieldGet (RecdFieldRef.RecdFieldRef (tcref, name)), _, _, _) -> - (layoutTyconRef denv tcref) ^^ sepL (tagPunctuation ".") ^^ wordL (tagField name) + (layoutTyconRef denv tcref) ^^ SepL.dot ^^ wordL (tagField name) | Expr.Op (TOp.Array, [_], xs, _) -> - leftL (tagPunctuation "[|") ^^ semiListL (dataExprsL denv xs) ^^ RightL.rightBracketBar + LeftL.leftBracketBar ^^ semiListL (dataExprsL denv xs) ^^ RightL.rightBracketBar | _ -> - wordL (tagPunctuation "?") + wordL questionMark and dataExprsL denv xs = List.map (dataExprL denv) xs diff --git a/src/Compiler/Driver/GraphChecking/TrieMapping.fs b/src/Compiler/Driver/GraphChecking/TrieMapping.fs index bfab87f9bec..e34939abac1 100644 --- a/src/Compiler/Driver/GraphChecking/TrieMapping.fs +++ b/src/Compiler/Driver/GraphChecking/TrieMapping.fs @@ -70,6 +70,14 @@ let mergeTrieNodes (defaultChildSize: int) (tries: TrieNode array) = TrieNodeInfo.Namespace (filesThatExposeTypes = otherFiles; filesDefiningNamespaceWithoutTypes = otherFilesWithoutTypes) -> currentFilesThatExposeTypes.UnionWith otherFiles currentFilesWithoutTypes.UnionWith otherFilesWithoutTypes + // Edge case scenario detected in https://github.com/dotnet/fsharp/issues/15985 + | TrieNodeInfo.Namespace (filesThatExposeTypes = currentFilesThatExposeTypes), TrieNodeInfo.Module (_name, file) -> + // Keep the namespace (as it can still have nested children). + currentFilesThatExposeTypes.Add file |> ignore + | TrieNodeInfo.Module (_name, file), TrieNodeInfo.Namespace (filesThatExposeTypes = currentFilesThatExposeTypes) -> + currentFilesThatExposeTypes.Add file |> ignore + // Replace the module in favour of the namespace (which can hold nested children). + root.Children[ k ] <- v | _ -> () for kv in v.Children do diff --git a/src/Compiler/Facilities/TextLayoutRender.fs b/src/Compiler/Facilities/TextLayoutRender.fs index 0768e699df1..a0b218dab77 100644 --- a/src/Compiler/Facilities/TextLayoutRender.fs +++ b/src/Compiler/Facilities/TextLayoutRender.fs @@ -60,6 +60,9 @@ module WordL = let keywordOverride = wordL TaggedText.keywordOverride let keywordEnum = wordL TaggedText.keywordEnum let keywordInline = wordL TaggedText.keywordInline + let leftAngle = wordL TaggedText.leftAngle + let keywordModule = wordL TaggedText.keywordModule + let keywordNamespace = wordL TaggedText.keywordNamespace module LeftL = let leftParen = leftL TaggedText.leftParen @@ -78,6 +81,7 @@ module RightL = let rightAngle = rightL TaggedText.rightAngle let rightBracketAngle = rightL TaggedText.rightBracketAngle let rightBracketBar = rightL TaggedText.rightBracketBar + let semicolon = rightL TaggedText.semicolon type LayoutRenderer<'a, 'b> = abstract Start: unit -> 'b diff --git a/src/Compiler/Facilities/TextLayoutRender.fsi b/src/Compiler/Facilities/TextLayoutRender.fsi index 48f874a0d3b..0e52b9998f2 100644 --- a/src/Compiler/Facilities/TextLayoutRender.fsi +++ b/src/Compiler/Facilities/TextLayoutRender.fsi @@ -99,6 +99,9 @@ module internal WordL = val keywordOverride: Layout val keywordEnum: Layout val keywordInline: Layout + val leftAngle: Layout + val keywordModule: Layout + val keywordNamespace: Layout module internal LeftL = val leftParen: Layout @@ -117,3 +120,4 @@ module internal RightL = val rightAngle: Layout val rightBracketAngle: Layout val rightBracketBar: Layout + val semicolon: Layout diff --git a/src/Compiler/Utilities/sformat.fs b/src/Compiler/Utilities/sformat.fs index 7281286dfd6..217b527f871 100644 --- a/src/Compiler/Utilities/sformat.fs +++ b/src/Compiler/Utilities/sformat.fs @@ -253,6 +253,9 @@ module TaggedText = let star = tagOperator "*" let keywordNew = tagKeyword "new" let keywordInline = tagKeyword "inline" + let keywordModule = tagKeyword "module" + let keywordNamespace = tagKeyword "namespace" + let punctuationUnit = tagPunctuation "()" #endif [] diff --git a/src/Compiler/Utilities/sformat.fsi b/src/Compiler/Utilities/sformat.fsi index e4e8412495f..1c740a38dce 100644 --- a/src/Compiler/Utilities/sformat.fsi +++ b/src/Compiler/Utilities/sformat.fsi @@ -211,6 +211,9 @@ module internal TaggedText = val internal star: TaggedText val internal keywordNew: TaggedText val internal keywordInline: TaggedText + val internal keywordModule: TaggedText + val internal keywordNamespace: TaggedText + val internal punctuationUnit: TaggedText type internal IEnvironment = /// Return to the layout-generation diff --git a/src/FSharp.Core/ILLink.LinkAttributes.xml b/src/FSharp.Core/ILLink.LinkAttributes.xml index e4493298d41..70eba54ff4e 100644 --- a/src/FSharp.Core/ILLink.LinkAttributes.xml +++ b/src/FSharp.Core/ILLink.LinkAttributes.xml @@ -122,6 +122,9 @@ + + + diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs index 7ebec39786f..06dc7d44671 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs @@ -345,9 +345,9 @@ let f4 = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 193, Line 6, Col 9, Line 6, Col 16, "Type constraint mismatch. The type \n 'string' \nis not compatible with type\n 'int' \n") - (Error 193, Line 12, Col 13, Line 12, Col 16, "Type constraint mismatch. The type \n 'string' \nis not compatible with type\n 'int' \n") + (Error 1, Line 6, Col 9, Line 6, Col 16, "This expression was expected to have type\n 'int' \nbut here has type\n 'string' ") + (Error 1, Line 12, Col 13, Line 12, Col 16, "This expression was expected to have type\n 'int' \nbut here has type\n 'string' ") (Error 193, Line 21, Col 9, Line 21, Col 24, "Type constraint mismatch. The type \n 'int list' \nis not compatible with type\n 'string seq' \n") - (Error 193, Line 28, Col 9, Line 28, Col 12, "Type constraint mismatch. The type \n 'float' \nis not compatible with type\n 'int64' \n") + (Error 1, Line 28, Col 9, Line 28, Col 12, "This expression was expected to have type\n 'int64' \nbut here has type\n 'float' ") ] diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 111ba0c94e5..aefeb44cc50 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -226,6 +226,7 @@ + diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs index 4ad6a5cafe2..2f90f8963c6 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs @@ -414,8 +414,8 @@ let typedSeq = |> withLangVersion80 |> typecheck |> shouldFail - |> withErrorCode 193 - |> withDiagnosticMessageMatches "Type constraint mismatch" + |> withErrorCode 1 + |> withDiagnosticMessageMatches "This expression was expected to have type" [] diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/Scenarios.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/Scenarios.fs index 7931861dcfb..a60e8e7c116 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/Scenarios.fs +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/Scenarios.fs @@ -688,4 +688,66 @@ module ColdTasks = """ (set [| 0; 2 |]) ] + scenario + "ModuleSuffix clash" + [ + sourceFile + "A.fs" + """ +namespace F.General +""" + Set.empty + sourceFile + "B.fs" + """ +[] +module F + +let br () = () +""" + Set.empty + + sourceFile + "C.fs" + """ +module S + +[] +let main _ = + F.br () + 0 +""" + (set [| 1 |]) + ] + scenario + "ModuleSuffix clash, module before namespace" + [ + sourceFile + "A.fs" + """ +[] +module F + +let br () = () +""" + Set.empty + sourceFile + "B.fs" + """ +namespace F.General +""" + Set.empty + + sourceFile + "C.fs" + """ +module S + +[] +let main _ = + F.br () + 0 +""" + (set [| 0 |]) + ] ] diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/SeqTypeCheckTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/SeqTypeCheckTests.fs new file mode 100644 index 00000000000..a0b78d83d1c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/SeqTypeCheckTests.fs @@ -0,0 +1,17 @@ +module TypeChecks.SeqTypeCheckTests + +open Xunit +open FSharp.Test.Compiler + +[] +let ``Seq expr with impicit yield type checks correctly when two identical record types are present`` () = + FSharp """ +module SeqInference + +type A = { X: int } +type B = { X: int } + +let l: A list = [ if true then { X = 42 } ] +""" + |> typecheck + |> shouldSucceed \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg24.bsl b/tests/fsharp/typecheck/sigs/neg24.bsl index 94167197aa1..f2e3feb2d54 100644 --- a/tests/fsharp/typecheck/sigs/neg24.bsl +++ b/tests/fsharp/typecheck/sigs/neg24.bsl @@ -21,11 +21,15 @@ neg24.fs(302,33,302,34): typecheck error FS0001: All elements of a list must be neg24.fs(302,36,302,37): typecheck error FS0001: All elements of a list must be implicitly convertible to the type of the first element, which here is 'unit'. This element has type 'int'. -neg24.fs(305,24,305,25): typecheck error FS0193: Type constraint mismatch. The type - 'int' -is not compatible with type +neg24.fs(305,24,305,25): typecheck error FS0001: This expression was expected to have type 'unit' +but here has type + 'int' +neg24.fs(305,31,305,32): typecheck error FS0001: This expression was expected to have type + 'unit' +but here has type + 'int' neg24.fs(308,30,308,31): typecheck error FS0020: The result of this expression has type 'int' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'. diff --git a/tests/fsharp/typecheck/sigs/version47/neg24.bsl b/tests/fsharp/typecheck/sigs/version47/neg24.bsl index 4825319243d..192de09f93d 100644 --- a/tests/fsharp/typecheck/sigs/version47/neg24.bsl +++ b/tests/fsharp/typecheck/sigs/version47/neg24.bsl @@ -21,11 +21,15 @@ neg24.fs(302,33,302,34): typecheck error FS0001: All elements of a list must be neg24.fs(302,36,302,37): typecheck error FS0001: All elements of a list must be implicitly convertible to the type of the first element, which here is 'unit'. This element has type 'int'. -neg24.fs(305,24,305,25): typecheck error FS0193: Type constraint mismatch. The type - 'int' -is not compatible with type +neg24.fs(305,24,305,25): typecheck error FS0001: This expression was expected to have type 'unit' +but here has type + 'int' +neg24.fs(305,31,305,32): typecheck error FS0001: This expression was expected to have type + 'unit' +but here has type + 'int' neg24.fs(308,30,308,31): typecheck error FS0020: The result of this expression has type 'int' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'. diff --git a/tests/walkthroughs/sdk-script-manual-tests/README.md.txt b/tests/walkthroughs/sdk-script-manual-tests/README.md similarity index 99% rename from tests/walkthroughs/sdk-script-manual-tests/README.md.txt rename to tests/walkthroughs/sdk-script-manual-tests/README.md index 643fece6fe5..67cc030882d 100644 --- a/tests/walkthroughs/sdk-script-manual-tests/README.md.txt +++ b/tests/walkthroughs/sdk-script-manual-tests/README.md @@ -82,4 +82,4 @@ dotnet artifacts\bin\fsi\Debug\netcoreapp3.1\fsi.exe c:\misc\tests\neutral-scrip dotnet artifacts\bin\fsi\Debug\netcoreapp3.1\fsi.exe c:\misc\tests\neutral-script-reference-netfx-script.fsx dotnet artifacts\bin\fsi\Debug\netcoreapp3.1\fsi.exe c:\misc\tests\neutral-script-reference-neutral-script.fsx -``` \ No newline at end of file +``` diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs new file mode 100644 index 00000000000..eb77d13c355 --- /dev/null +++ b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReference.fs @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.VisualStudio.FSharp.Editor + +open System +open System.Composition +open System.Collections.Immutable +open System.IO + +open Microsoft.CodeAnalysis +open Microsoft.CodeAnalysis.CodeFixes +open Microsoft.CodeAnalysis.CodeActions + +open CancellableTasks + +type private ReferenceType = + | AddProjectRef of ProjectReference + | AddMetadataRef of MetadataReference + +// This code fix only works for the legacy, non-SDK projects. +// In SDK projects, transitive references do this trick. +// See: https://github.com/dotnet/fsharp/pull/2743 + +// Because this code fix is barely applicable anymore +// and because it's very different from other code fixes +// (applies to the projects files, not code itself), +// it's not implemented via IFSharpCodeFix interfaces +// and not tested automatically either. +// If we happen to create similar code fixes, +// it'd make sense to create some testing framework for them. +[] +type internal MissingReferenceCodeFixProvider() = + inherit CodeFixProvider() + + let createCodeFix (title: string, context: CodeFixContext, addReference: ReferenceType) = + CodeAction.Create( + title, + (fun cancellationToken -> + cancellableTask { + let project = context.Document.Project + let solution = project.Solution + + match addReference with + | AddProjectRef projectRef -> + let references = project.AllProjectReferences + let newReferences = references |> Seq.append [ projectRef ] + return solution.WithProjectReferences(project.Id, newReferences) + + | AddMetadataRef metadataRef -> + let references = project.MetadataReferences + let newReferences = references |> Seq.append [ metadataRef ] + return solution.WithProjectMetadataReferences(project.Id, newReferences) + } + |> CancellableTask.start cancellationToken) + ) + + override _.FixableDiagnosticIds = ImmutableArray.Create "FS0074" + + override _.RegisterCodeFixesAsync context = + cancellableTask { + let solution = context.Document.Project.Solution + + let diagnostic = context.Diagnostics[0] + let message = diagnostic.GetMessage() + let parts = message.Split([| '\'' |], StringSplitOptions.None) + + match parts with + | [| _; _type; _; assemblyName; _ |] -> + + let exactProjectMatches = + solution.Projects + |> Seq.tryFindV (fun project -> + String.Compare(project.AssemblyName, assemblyName, StringComparison.OrdinalIgnoreCase) = 0) + + match exactProjectMatches with + | ValueSome refProject -> + let codefix = + createCodeFix ( + String.Format(SR.AddProjectReference(), refProject.Name), + context, + AddProjectRef(ProjectReference refProject.Id) + ) + + context.RegisterCodeFix(codefix, ImmutableArray.Create diagnostic) + | ValueNone -> + let metadataReferences = + solution.Projects + |> Seq.collect (fun project -> project.MetadataReferences) + |> Seq.tryFindV (fun ref -> + let referenceAssemblyName = Path.GetFileNameWithoutExtension(ref.Display) + String.Compare(referenceAssemblyName, assemblyName, StringComparison.OrdinalIgnoreCase) = 0) + + match metadataReferences with + | ValueSome metadataRef -> + let codefix = + createCodeFix (String.Format(SR.AddAssemblyReference(), assemblyName), context, AddMetadataRef metadataRef) + + context.RegisterCodeFix(codefix, ImmutableArray.Create diagnostic) + | ValueNone -> () + | _ -> () + } + |> CancellableTask.startAsTask context.CancellationToken diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs b/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs deleted file mode 100644 index eabc0cd2880..00000000000 --- a/vsintegration/src/FSharp.Editor/CodeFixes/MissingReferenceCodeFixProvider.fs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace Microsoft.VisualStudio.FSharp.Editor - -open System -open System.Composition -open System.Collections.Immutable -open System.Threading -open System.Threading.Tasks -open System.IO - -open Microsoft.CodeAnalysis -open Microsoft.CodeAnalysis.CodeFixes -open Microsoft.CodeAnalysis.CodeActions - -type private ReferenceType = - | AddProjectRef of ProjectReference - | AddMetadataRef of MetadataReference - -[] -type internal MissingReferenceCodeFixProvider() = - inherit CodeFixProvider() - - let fixableDiagnosticId = "FS0074" - - let createCodeFix (title: string, context: CodeFixContext, addReference: ReferenceType) = - CodeAction.Create( - title, - (fun (cancellationToken: CancellationToken) -> - async { - let project = context.Document.Project - let solution = project.Solution - - match addReference with - | AddProjectRef projectRef -> - let references = project.AllProjectReferences - let newReferences = references |> Seq.append [ projectRef ] - return solution.WithProjectReferences(project.Id, newReferences) - - | AddMetadataRef metadataRef -> - let references = project.MetadataReferences - let newReferences = references |> Seq.append [ metadataRef ] - return solution.WithProjectMetadataReferences(project.Id, newReferences) - } - |> RoslynHelpers.StartAsyncAsTask(cancellationToken)), - title - ) - - override _.FixableDiagnosticIds = Seq.toImmutableArray [ fixableDiagnosticId ] - - override _.RegisterCodeFixesAsync context : Task = - async { - let solution = context.Document.Project.Solution - - context.Diagnostics - |> Seq.filter (fun x -> x.Id = fixableDiagnosticId) - |> Seq.iter (fun diagnostic -> - let message = diagnostic.GetMessage() - let parts = message.Split([| '\'' |], StringSplitOptions.None) - - match parts with - | [| _; _type; _; assemblyName; _ |] -> - - let exactProjectMatches = - solution.Projects - |> Seq.tryFindV (fun project -> - String.Compare(project.AssemblyName, assemblyName, StringComparison.OrdinalIgnoreCase) = 0) - - match exactProjectMatches with - | ValueSome refProject -> - let codefix = - createCodeFix ( - String.Format(SR.AddProjectReference(), refProject.Name), - context, - AddProjectRef(ProjectReference refProject.Id) - ) - - context.RegisterCodeFix(codefix, ImmutableArray.Create diagnostic) - | ValueNone -> - let metadataReferences = - solution.Projects - |> Seq.collect (fun project -> project.MetadataReferences) - |> Seq.tryFindV (fun ref -> - let referenceAssemblyName = Path.GetFileNameWithoutExtension(ref.Display) - String.Compare(referenceAssemblyName, assemblyName, StringComparison.OrdinalIgnoreCase) = 0) - - match metadataReferences with - | ValueSome metadataRef -> - let codefix = - createCodeFix (String.Format(SR.AddAssemblyReference(), assemblyName), context, AddMetadataRef metadataRef) - - context.RegisterCodeFix(codefix, ImmutableArray.Create diagnostic) - | ValueNone -> () - | _ -> ()) - } - |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken) diff --git a/vsintegration/src/FSharp.Editor/CodeFixes/ReplaceWithSuggestion.fs b/vsintegration/src/FSharp.Editor/CodeFixes/ReplaceWithSuggestion.fs index 31b0b84d374..1678f89c1d5 100644 --- a/vsintegration/src/FSharp.Editor/CodeFixes/ReplaceWithSuggestion.fs +++ b/vsintegration/src/FSharp.Editor/CodeFixes/ReplaceWithSuggestion.fs @@ -19,7 +19,7 @@ open CancellableTasks type internal ReplaceWithSuggestionCodeFixProvider [] () = inherit CodeFixProvider() - override _.FixableDiagnosticIds = ImmutableArray.Create("FS0039", "FS0495") + override _.FixableDiagnosticIds = ImmutableArray.Create("FS0039", "FS0495", "FS1129") override this.RegisterCodeFixesAsync context = if context.Document.Project.IsFSharpCodeFixesSuggestNamesForErrorsEnabled then diff --git a/vsintegration/src/FSharp.Editor/Common/Constants.fs b/vsintegration/src/FSharp.Editor/Common/Constants.fs index d59b241b44e..8e529cf0319 100644 --- a/vsintegration/src/FSharp.Editor/Common/Constants.fs +++ b/vsintegration/src/FSharp.Editor/Common/Constants.fs @@ -163,6 +163,9 @@ module internal CodeFix = [] let MakeDeclarationMutable = "MakeDeclarationMutable" + [] + let MissingReference = "MissingReference" + [] let ChangePrefixNegationToInfixSubtraction = "ChangePrefixNegationToInfixSubtraction" diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index b73a33b690d..b2a685d2347 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -133,7 +133,7 @@ - + diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.resx b/vsintegration/src/FSharp.Editor/FSharp.Editor.resx index 251cd02d780..8db6c37e401 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.resx +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.resx @@ -211,7 +211,7 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) diff --git a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs index b8856c24259..ad5156e3082 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs @@ -145,10 +145,6 @@ type internal FSharpWorkspaceServiceFactory [] let enableBackgroundItemKeyStoreAndSemanticClassification = editorOptions.LanguageServicePerformance.EnableBackgroundItemKeyStoreAndSemanticClassification - // Default should be true - let captureIdentifiersWhenParsing = - editorOptions.LanguageServicePerformance.CaptureIdentifiersWhenParsing - // Default is false here let solutionCrawler = editorOptions.Advanced.SolutionBackgroundAnalysis @@ -169,7 +165,7 @@ type internal FSharpWorkspaceServiceFactory [] nameof keepAllBackgroundSymbolUses, keepAllBackgroundSymbolUses nameof enableBackgroundItemKeyStoreAndSemanticClassification, enableBackgroundItemKeyStoreAndSemanticClassification - nameof captureIdentifiersWhenParsing, captureIdentifiersWhenParsing + "captureIdentifiersWhenParsing", enableFastFindReferences nameof solutionCrawler, solutionCrawler |], TelemetryThrottlingStrategy.NoThrottling @@ -186,7 +182,7 @@ type internal FSharpWorkspaceServiceFactory [] enableBackgroundItemKeyStoreAndSemanticClassification, enablePartialTypeChecking = enablePartialTypeChecking, parallelReferenceResolution = enableParallelReferenceResolution, - captureIdentifiersWhenParsing = captureIdentifiersWhenParsing, + captureIdentifiersWhenParsing = enableFastFindReferences, documentSource = (if enableLiveBuffers then DocumentSource.Custom getSource diff --git a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs index 905919f4ce9..1199b14477d 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs @@ -252,7 +252,12 @@ type internal GoToDefinition(metadataAsSource: FSharpMetadataAsSourceService) = |> liftAsync let symbolUses = checkFileResults.GetUsesOfSymbolInFile targetSymbolUse.Symbol - let! implSymbol = symbolUses |> Array.tryHead + + let! implSymbol = + symbolUses + |> Array.sortByDescending (fun x -> x.IsFromDefinition) + |> Array.tryHead + return implSymbol.Range } diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs index fae67f36e32..5137bb8596c 100644 --- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs +++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs @@ -88,7 +88,6 @@ type LanguageServicePerformanceOptions = KeepAllBackgroundResolutions: bool KeepAllBackgroundSymbolUses: bool EnableBackgroundItemKeyStoreAndSemanticClassification: bool - CaptureIdentifiersWhenParsing: bool } static member Default = @@ -103,7 +102,6 @@ type LanguageServicePerformanceOptions = KeepAllBackgroundResolutions = false KeepAllBackgroundSymbolUses = false EnableBackgroundItemKeyStoreAndSemanticClassification = true - CaptureIdentifiersWhenParsing = true } [] diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf index fa6aa6fd4cc..0e588b5cd47 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.cs.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - Možnosti výkonu projektu F# a ukládání do mezipaměti; + Možnosti výkonu projektu F# a ukládání do mezipaměti; Povolit odkazy mezi projekty v paměti; Enable_partial_type_checking; Možnosti výkonu IntelliSense; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf index e3cc881854d..b276297b1b0 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.de.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - F#-Projekt- und Cacheleistungsoptionen; + F#-Projekt- und Cacheleistungsoptionen; Projektübergreifende Verweise im Arbeitsspeicher aktivieren; Enable_partial_type_checking; IntelliSense-Leistungsoptionen; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf index 83074b9f703..f6bdf050f6f 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.es.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - Opciones de rendimiento de proyectos y caché de F#; + Opciones de rendimiento de proyectos y caché de F#; Habilitar referencias cruzadas de proyecto en memoria; Enable_partial_type_checking; Opciones de rendimiento de IntelliSense; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf index 1aea7681a66..f32d4765e14 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.fr.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - Options de performances du projet F # et de la mise en cache ; + Options de performances du projet F # et de la mise en cache ; Activer les références de projets croisés en mémoire ; Enable_partial_type_checking ; Options de performances IntelliSense ; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf index 4b74d02fdf8..fcf9afb2bf2 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.it.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - Opzioni prestazioni progetto F# e memorizzazione nella cache; + Opzioni prestazioni progetto F# e memorizzazione nella cache; Abilita riferimenti tra progetti in memoria; Enable_partial_type_checking; Opzioni prestazioni IntelliSense; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf index 4cfbba3fb49..893c213c3bc 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ja.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - F# プロジェクトとキャッシュのパフォーマンス オプション; + F# プロジェクトとキャッシュのパフォーマンス オプション; メモリ内のプロジェクト間参照を有効にする。 Enable_partial_type_checking; IntelliSense パフォーマンス オプション; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf index 6eb8c0f3ec1..ab917a9a565 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ko.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - F# 프로젝트 및 캐싱 성능 옵션; + F# 프로젝트 및 캐싱 성능 옵션; 메모리 내 프로젝트 간 참조 활성화; Enable_partial_type_checking; IntelliSense 성능 옵션; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf index f4d5ad66fa9..9fba8c3fd08 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pl.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - Opcje wydajności projektów i buforowania języka F#; + Opcje wydajności projektów i buforowania języka F#; Włącz odwołania między projektami w pamięci; Enable_partial_type_checking; Opcje wydajności funkcji IntelliSense; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf index 34d03fefbe9..38c78de1849 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.pt-BR.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - Opções de desempenho de projeto e cache do F#; + Opções de desempenho de projeto e cache do F#; Habilitar referências de projeto cruzado na memória; Enable_partial_type_checking; Opções de desempenho do IntelliSense; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf index 97331156092..5dee3aa17ce 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.ru.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - Параметры производительности проекта F# и кэширования; + Параметры производительности проекта F# и кэширования; Включить перекрестные ссылки проекта в памяти; Enable_partial_type_checking; Параметры производительности IntelliSense; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf index 52608a483ae..a9a33f92557 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.tr.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - F# Proje ve Önbelleğe Alma Performans Seçenekleri; + F# Proje ve Önbelleğe Alma Performans Seçenekleri; Bellek içi çapraz proje başvurularını etkinleştir; Enable_partial_type_checking; IntelliSense Performans Seçenekleri; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf index 207e0a9470b..a8b8ed8bd89 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hans.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - F# 项目和缓存性能选项; + F# 项目和缓存性能选项; 启用内存中的跨项目引用; 启用部分类型检查; IntelliSense 性能选项; diff --git a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf index d6cd3abe0e2..1a649a0b03a 100644 --- a/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf +++ b/vsintegration/src/FSharp.Editor/xlf/FSharp.Editor.zh-Hant.xlf @@ -167,9 +167,9 @@ Time until stale results are used (in milliseconds); Parallelization (requires restart); Enable parallel type checking with signature files; Enable parallel reference resolution; -Enable fast find references & rename (experimental); +Enable fast find references & rename (restart required); Cache parsing results (experimental) - F# 專案和快取效能選項; + F# 專案和快取效能選項; 啟用記憶體內跨專案參考; Enable_partial_type_checking; IntelliSense 效能選項; diff --git a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml index 074bc7febc8..96b8915b80e 100644 --- a/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml +++ b/vsintegration/src/FSharp.UIResources/LanguageServicePerformanceOptionControl.xaml @@ -85,9 +85,6 @@ - diff --git a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs index 0c8d435f87d..f3490b414a0 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.Designer.cs +++ b/vsintegration/src/FSharp.UIResources/Strings.Designer.cs @@ -105,15 +105,6 @@ public static string Block_Structure { } } - /// - /// Looks up a localized string similar to Capture identifiers while parsing. - /// - public static string Capture_Identifiers_When_Parsing { - get { - return ResourceManager.GetString("Capture_Identifiers_When_Parsing", resourceCulture); - } - } - /// /// Looks up a localized string similar to Code Fixes. /// diff --git a/vsintegration/src/FSharp.UIResources/Strings.resx b/vsintegration/src/FSharp.UIResources/Strings.resx index f0ae6b60146..5bf7260f9cc 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.resx +++ b/vsintegration/src/FSharp.UIResources/Strings.resx @@ -249,9 +249,6 @@ Keep background symbol keys - - Capture identifiers while parsing - Use live (unsaved) buffers for checking (restart required) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf index fc6191d7055..51f813a4903 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf index c9fe10de771..6aa9e6a6686 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf index d2de44fb296..fc73ebc636c 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf index 03ae77ec939..7e1f700e3ea 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf index e3b948f6d8f..3b88428daa1 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf index b0ddce5658d..94126a8eef1 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf index 6d3d8a13a53..e5dd62c28da 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf index b4d2cf145ab..513d580a3b2 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf index ecd4611a48a..86629640ec9 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf index 3fcde247df6..b590dc949a2 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf index b1451e5a571..14a87b14ef3 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf index 1dcbb550d8e..132485ea815 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf index 8f70454be10..624aefbf6cb 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf @@ -22,11 +22,6 @@ Background analysis - - Capture identifiers while parsing - Capture identifiers while parsing - - Keep background symbol keys Keep background symbol keys diff --git a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/ReplaceWithSuggestionTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/ReplaceWithSuggestionTests.fs index 20495583a37..7f5e745b0f3 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/ReplaceWithSuggestionTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CodeFixes/ReplaceWithSuggestionTests.fs @@ -156,3 +156,37 @@ let song = Song(title = "Under The Milky Way") let actual = codeFix |> multiFix code Auto Assert.Equal(expected, actual) + +[] +let ``Fixes FS1129`` () = + let code = + """ +type SomeType = { TheField : string } + +let f x = + match x with + | { TheField = "A" } -> true + | { TheFiedl = "B" } -> true + | _ -> false +""" + + let expected = + [ + { + Message = "Replace with 'TheField'" + FixedCode = + """ +type SomeType = { TheField : string } + +let f x = + match x with + | { TheField = "A" } -> true + | { TheField = "B" } -> true + | _ -> false +""" + } + ] + + let actual = codeFix |> multiFix code Auto + + Assert.Equal(expected, actual)