From 289236769df6b807a364ba985cfae4fd1c038de2 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 26 Jan 2021 13:27:36 -0800 Subject: [PATCH 01/17] lexx/yacc warnings (#10950) --- src/buildtools/fslex/Arg.fs | 28 ++++++++++++++-------------- src/buildtools/fsyacc/Arg.fs | 28 ++++++++++++++-------------- src/buildtools/fsyacc/Parsing.fsi | 2 +- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/buildtools/fslex/Arg.fs b/src/buildtools/fslex/Arg.fs index a1f63bd9638..b1131625cf3 100644 --- a/src/buildtools/fslex/Arg.fs +++ b/src/buildtools/fslex/Arg.fs @@ -52,13 +52,13 @@ type ArgParser() = sbuf.ToString() - static member ParsePartial(cursor,argv,argSpecs:seq,?other,?usageText) = - let other = defaultArg other (fun _ -> ()) + static member ParsePartial(cursor,argv,arguments:seq,?otherArgs,?usageText) = + let otherArgs = defaultArg otherArgs (fun _ -> ()) let usageText = defaultArg usageText "" let nargs = Array.length argv incr cursor; - let argSpecs = argSpecs |> Seq.toList - let specs = argSpecs |> List.map (fun (arg:ArgInfo) -> arg.Name, arg.ArgType) + let arguments = arguments |> Seq.toList + let specs = arguments |> List.map (fun (arg:ArgInfo) -> arg.Name, arg.ArgType) while !cursor < nargs do let arg = argv.[!cursor] let rec findMatchingArg args = @@ -66,7 +66,7 @@ type ArgParser() = | ((s, action) :: _) when s = arg -> let getSecondArg () = if !cursor + 1 >= nargs then - raise(Bad("option "+s+" needs an argument.\n"+getUsage argSpecs usageText)); + raise(Bad("option "+s+" needs an argument.\n"+getUsage arguments usageText)); argv.[!cursor+1] match action with @@ -85,12 +85,12 @@ type ArgParser() = cursor := !cursor + 2 | IntArg f -> let arg2 = getSecondArg () - let arg2 = try int32 arg2 with _ -> raise(Bad(getUsage argSpecs usageText)) in + let arg2 = try int32 arg2 with _ -> raise(Bad(getUsage arguments usageText)) in f arg2; cursor := !cursor + 2; | FloatArg f -> let arg2 = getSecondArg() - let arg2 = try float arg2 with _ -> raise(Bad(getUsage argSpecs usageText)) in + let arg2 = try float arg2 with _ -> raise(Bad(getUsage arguments usageText)) in f arg2; cursor := !cursor + 2; | RestArg f -> @@ -102,26 +102,26 @@ type ArgParser() = | (_ :: more) -> findMatchingArg more | [] -> if arg = "-help" || arg = "--help" || arg = "/help" || arg = "/help" || arg = "/?" then - raise (HelpText (getUsage argSpecs usageText)) + raise (HelpText (getUsage arguments usageText)) // Note: for '/abc/def' does not count as an argument // Note: '/abc' does elif arg.Length>0 && (arg.[0] = '-' || (arg.[0] = '/' && not (arg.Length > 1 && arg.[1..].Contains ("/")))) then - raise (Bad ("unrecognized argument: "+ arg + "\n" + getUsage argSpecs usageText)) + raise (Bad ("unrecognized argument: "+ arg + "\n" + getUsage arguments usageText)) else - other arg; + otherArgs arg; incr cursor findMatchingArg specs - static member Usage (specs,?usage) = + static member Usage (arguments,?usage) = let usage = defaultArg usage "" - System.Console.Error.WriteLine (getUsage (Seq.toList specs) usage) + System.Console.Error.WriteLine (getUsage (Seq.toList arguments) usage) #if FX_NO_COMMAND_LINE_ARGS #else - static member Parse (specs,?other,?usageText) = + static member Parse (arguments,?otherArgs,?usageText) = let current = ref 0 let argv = System.Environment.GetCommandLineArgs() - try ArgParser.ParsePartial (current, argv, specs, ?other=other, ?usageText=usageText) + try ArgParser.ParsePartial (current, argv, arguments, ?otherArgs=otherArgs, ?usageText=usageText) with | Bad h | HelpText h -> diff --git a/src/buildtools/fsyacc/Arg.fs b/src/buildtools/fsyacc/Arg.fs index a1f63bd9638..b1131625cf3 100644 --- a/src/buildtools/fsyacc/Arg.fs +++ b/src/buildtools/fsyacc/Arg.fs @@ -52,13 +52,13 @@ type ArgParser() = sbuf.ToString() - static member ParsePartial(cursor,argv,argSpecs:seq,?other,?usageText) = - let other = defaultArg other (fun _ -> ()) + static member ParsePartial(cursor,argv,arguments:seq,?otherArgs,?usageText) = + let otherArgs = defaultArg otherArgs (fun _ -> ()) let usageText = defaultArg usageText "" let nargs = Array.length argv incr cursor; - let argSpecs = argSpecs |> Seq.toList - let specs = argSpecs |> List.map (fun (arg:ArgInfo) -> arg.Name, arg.ArgType) + let arguments = arguments |> Seq.toList + let specs = arguments |> List.map (fun (arg:ArgInfo) -> arg.Name, arg.ArgType) while !cursor < nargs do let arg = argv.[!cursor] let rec findMatchingArg args = @@ -66,7 +66,7 @@ type ArgParser() = | ((s, action) :: _) when s = arg -> let getSecondArg () = if !cursor + 1 >= nargs then - raise(Bad("option "+s+" needs an argument.\n"+getUsage argSpecs usageText)); + raise(Bad("option "+s+" needs an argument.\n"+getUsage arguments usageText)); argv.[!cursor+1] match action with @@ -85,12 +85,12 @@ type ArgParser() = cursor := !cursor + 2 | IntArg f -> let arg2 = getSecondArg () - let arg2 = try int32 arg2 with _ -> raise(Bad(getUsage argSpecs usageText)) in + let arg2 = try int32 arg2 with _ -> raise(Bad(getUsage arguments usageText)) in f arg2; cursor := !cursor + 2; | FloatArg f -> let arg2 = getSecondArg() - let arg2 = try float arg2 with _ -> raise(Bad(getUsage argSpecs usageText)) in + let arg2 = try float arg2 with _ -> raise(Bad(getUsage arguments usageText)) in f arg2; cursor := !cursor + 2; | RestArg f -> @@ -102,26 +102,26 @@ type ArgParser() = | (_ :: more) -> findMatchingArg more | [] -> if arg = "-help" || arg = "--help" || arg = "/help" || arg = "/help" || arg = "/?" then - raise (HelpText (getUsage argSpecs usageText)) + raise (HelpText (getUsage arguments usageText)) // Note: for '/abc/def' does not count as an argument // Note: '/abc' does elif arg.Length>0 && (arg.[0] = '-' || (arg.[0] = '/' && not (arg.Length > 1 && arg.[1..].Contains ("/")))) then - raise (Bad ("unrecognized argument: "+ arg + "\n" + getUsage argSpecs usageText)) + raise (Bad ("unrecognized argument: "+ arg + "\n" + getUsage arguments usageText)) else - other arg; + otherArgs arg; incr cursor findMatchingArg specs - static member Usage (specs,?usage) = + static member Usage (arguments,?usage) = let usage = defaultArg usage "" - System.Console.Error.WriteLine (getUsage (Seq.toList specs) usage) + System.Console.Error.WriteLine (getUsage (Seq.toList arguments) usage) #if FX_NO_COMMAND_LINE_ARGS #else - static member Parse (specs,?other,?usageText) = + static member Parse (arguments,?otherArgs,?usageText) = let current = ref 0 let argv = System.Environment.GetCommandLineArgs() - try ArgParser.ParsePartial (current, argv, specs, ?other=other, ?usageText=usageText) + try ArgParser.ParsePartial (current, argv, arguments, ?otherArgs=otherArgs, ?usageText=usageText) with | Bad h | HelpText h -> diff --git a/src/buildtools/fsyacc/Parsing.fsi b/src/buildtools/fsyacc/Parsing.fsi index 2fef45975a8..f4d12606462 100644 --- a/src/buildtools/fsyacc/Parsing.fsi +++ b/src/buildtools/fsyacc/Parsing.fsi @@ -100,7 +100,7 @@ type Tables<'tok> = /// Interpret the parser table taking input from the given lexer, using the given lex buffer, and the given start state. /// Returns an object indicating the final synthesized value for the parse. - member Interpret : lexer:(LexBuffer<'char> -> 'tok) * lexbuf:LexBuffer<'char> * startState:int -> obj + member Interpret : lexer:(LexBuffer<'char> -> 'tok) * lexbuf:LexBuffer<'char> * initialState:int -> obj #if INTERNALIZED_FSLEXYACC_RUNTIME exception internal Accept of obj From fe4a61a6245226833ec0cecfbc7a2f83b96b70b9 Mon Sep 17 00:00:00 2001 From: Phillip Carter Date: Wed, 27 Jan 2021 08:52:56 -0800 Subject: [PATCH 02/17] Fix triggering the outer application's signature help when triggering an inner application inside a lambda (#10954) * Fix issue where sighelp triggered in lambda gave outer signature help * Updates --- src/fsharp/service/ServiceUntypedParse.fs | 33 ++++++++++++++++----- tests/service/ServiceUntypedParseTests.fs | 35 +++++++++++++++++++++++ 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/fsharp/service/ServiceUntypedParse.fs b/src/fsharp/service/ServiceUntypedParse.fs index 9a9d83f059a..626898a9db2 100755 --- a/src/fsharp/service/ServiceUntypedParse.fs +++ b/src/fsharp/service/ServiceUntypedParse.fs @@ -170,14 +170,18 @@ type FSharpParseFileResults(errors: FSharpDiagnostic[], input: ParsedInput optio member _.VisitExpr(_, _, defaultTraverse, expr) = match expr with | SynExpr.App (_, _, SynExpr.App(_, true, SynExpr.Ident ident, _, _), argExpr, _) when rangeContainsPos argExpr.Range pos -> - if ident.idText = "op_PipeRight" then - Some (ident, 1) - elif ident.idText = "op_PipeRight2" then - Some (ident, 2) - elif ident.idText = "op_PipeRight3" then - Some (ident, 3) - else + match argExpr with + | SynExpr.App(_, _, _, SynExpr.Paren(expr, _, _, _), _) when rangeContainsPos expr.Range pos -> None + | _ -> + if ident.idText = "op_PipeRight" then + Some (ident, 1) + elif ident.idText = "op_PipeRight2" then + Some (ident, 2) + elif ident.idText = "op_PipeRight3" then + Some (ident, 3) + else + None | _ -> defaultTraverse expr }) | None -> None @@ -216,6 +220,10 @@ type FSharpParseFileResults(errors: FSharpDiagnostic[], input: ParsedInput optio match argExpr with | SynExpr.App (_, _, _, _, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr argExpr pos + + | SynExpr.Paren(SynExpr.Lambda(_, _, _args, body, _, _), _, _, _) when rangeContainsPos body.Range pos -> + getIdentRangeForFuncExprInApp traverseSynExpr body pos + | _ -> match funcExpr with | SynExpr.App (_, true, _, _, _) when rangeContainsPos argExpr.Range pos -> @@ -227,6 +235,17 @@ type FSharpParseFileResults(errors: FSharpDiagnostic[], input: ParsedInput optio // Generally, we want to dive into the func expr to get the range // of the identifier of the function we're after getIdentRangeForFuncExprInApp traverseSynExpr funcExpr pos + + | SynExpr.LetOrUse(_, _, bindings, body, range) when rangeContainsPos range pos -> + let binding = + bindings + |> List.tryFind (fun x -> rangeContainsPos x.RangeOfBindingAndRhs pos) + match binding with + | Some(SynBinding.Binding(_, _, _, _, _, _, _, _, _, expr, _, _)) -> + getIdentRangeForFuncExprInApp traverseSynExpr expr pos + | None -> + getIdentRangeForFuncExprInApp traverseSynExpr body pos + | expr -> traverseSynExpr expr |> Option.map (fun expr -> expr) diff --git a/tests/service/ServiceUntypedParseTests.fs b/tests/service/ServiceUntypedParseTests.fs index 3c87e8f7973..5d00a4f4400 100644 --- a/tests/service/ServiceUntypedParseTests.fs +++ b/tests/service/ServiceUntypedParseTests.fs @@ -835,6 +835,26 @@ async { |> tups |> shouldEqual ((4, 11), (4, 16)) + [] + let ``TryRangeOfFunctionOrMethodBeingApplied - inside lambda``() = + let source = """ +let add n1 n2 = n1 + n2 +let lst = [1; 2; 3] +let mapped = + lst |> List.map (fun n -> + let sum = add + n.ToString() + ) +""" + let parseFileResults, _ = getParseAndCheckResults source + let res = parseFileResults.TryRangeOfFunctionOrMethodBeingApplied (mkPos 6 21) + match res with + | None -> Assert.Fail("Expected 'add' but got nothing") + | Some range -> + range + |> tups + |> shouldEqual ((6, 18), (6, 21)) + module PipelinesAndArgs = [] let ``TryIdentOfPipelineContainingPosAndNumArgsApplied - No pipeline, no infix app``() = @@ -897,6 +917,21 @@ let square x = x * | None -> Assert.Fail("No pipeline found") + [] + let ``TryIdentOfPipelineContainingPosAndNumArgsApplied - none when inside lambda``() = + let source = """ +let add n1 n2 = n1 + n2 +let lst = [1; 2; 3] +let mapped = + lst |> List.map (fun n -> + let sum = add 1 + n.ToString() + ) + """ + let parseFileResults, _ = getParseAndCheckResults source + let res = parseFileResults.TryIdentOfPipelineContainingPosAndNumArgsApplied (mkPos 6 22) + Assert.IsTrue(res.IsNone, "Inside a lambda but counted the pipeline outside of that lambda.") + [] let ``TryRangeOfExprInYieldOrReturn - not contained``() = let source = """ From ae2ab7ddb5caf7346be5f06061478c5a135bc4ee Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Wed, 27 Jan 2021 10:53:44 -0800 Subject: [PATCH 03/17] Fix #10893 - FSI: Could not load file or assembly Azure.ResourceManager.Resources (#10953) --- src/fsharp/fsi/fsi.fs | 9 ++++----- .../FSharpScriptTests.fs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 0e9cf33fbee..788c3d006eb 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1880,11 +1880,10 @@ module internal MagicAssemblyResolution = // Special case: Mono Windows Forms attempts to load an assembly called something like "Windows.Forms.resources" // We can't resolve this, so don't try. // REVIEW: Suggest 4481, delete this special case. - if simpleAssemName.EndsWith(".resources",StringComparison.OrdinalIgnoreCase) || - // See F# 1.0 Product Studio bug 1171 - simpleAssemName.EndsWith(".XmlSerializers",StringComparison.OrdinalIgnoreCase) || - (runningOnMono && simpleAssemName = "UIAutomationWinforms") then null else - + if (runningOnMono && simpleAssemName.EndsWith(".resources",StringComparison.OrdinalIgnoreCase)) || + simpleAssemName.EndsWith(".XmlSerializers", StringComparison.OrdinalIgnoreCase) || + (runningOnMono && simpleAssemName = "UIAutomationWinforms") then null + else // Special case: Is this the global unique dynamic assembly for FSI code? In this case just // return the dynamic assembly itself. if fsiDynamicCompiler.DynamicAssemblyName = simpleAssemName then fsiDynamicCompiler.DynamicAssembly else diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs index c218cc2f408..431ac983ec4 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs @@ -317,6 +317,19 @@ typeof.Assembly.Location // Only Windows/Linux supported. () + [] + member _.``Reference -- Azure.ResourceManager.Resources``() = + let code = """ +#r "nuget: Azure.Identity, 1.3.0" +#r "nuget: Azure.ResourceManager.Resources, 1.0.0-preview.2" +let creds = Azure.Identity.DefaultAzureCredential() +let client = Azure.ResourceManager.Resources.ResourcesManagementClient("mySubscriptionId", creds) +true""" + use script = new FSharpScript(additionalArgs=[|"/langversion:preview"|]) + let opt = script.Eval(code) |> getValue + let value = opt.Value + Assert.True(true = downcast value.ReflectionValue) + [] member _.``Simple pinvoke should not be impacted by native resolver``() = let code = @" From 61710ca341dad68f3ac5312c56e077a3a84aec99 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 28 Jan 2021 08:28:47 -0800 Subject: [PATCH 04/17] [main] Update dependencies from dotnet/arcade (#10964) Microsoft.DotNet.Arcade.Sdk From Version 6.0.0-beta.21072.6 -> To Version 6.0.0-beta.21076.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/common/templates/post-build/post-build.yml | 18 +++++++++++++++++- global.json | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a02baf65fee..0fed70a5eec 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - c313ff83e84445094fa5463498d5c94c29f27e1d + d7da80d96daf724706aafa450e00222fe659af13 diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 375e91acdf3..b9aa5b6052c 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -61,6 +61,7 @@ parameters: VS167ChannelId: 1011 VS168ChannelId: 1154 VSMasterChannelId: 1012 + VS169ChannelId: 1473 stages: - ${{ if or(and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')), eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: @@ -90,7 +91,7 @@ stages: inputs: filePath: $(Build.SourcesDirectory)/eng/common/post-build/check-channel-consistency.ps1 arguments: -PromoteToChannels "$(TargetChannels)" - -AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.NetDev6ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}},${{parameters.VS166ChannelId}},${{parameters.VS167ChannelId}},${{parameters.VS168ChannelId}},${{parameters.VSMasterChannelId}} + -AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.NetDev6ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}},${{parameters.VS166ChannelId}},${{parameters.VS167ChannelId}},${{parameters.VS168ChannelId}},${{parameters.VSMasterChannelId}},${{parameters.VS169ChannelId}} - job: displayName: NuGet Validation @@ -552,3 +553,18 @@ stages: transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' + + - template: \eng\common\templates\post-build\channels\generic-public-channel.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} + dependsOn: ${{ parameters.publishDependsOn }} + publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} + symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} + stageName: 'VS_16_9_Publishing' + channelName: 'VS 16.9' + channelId: ${{ parameters.VS169ChannelId }} + transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' + shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' + symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' diff --git a/global.json b/global.json index 8b1cead1aea..b82dff7bac2 100644 --- a/global.json +++ b/global.json @@ -13,7 +13,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21072.6", + "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21076.1", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 909276598d6c235f52b125437ee9120f61ddfee6 Mon Sep 17 00:00:00 2001 From: Phillip Carter Date: Thu, 28 Jan 2021 21:03:11 -0800 Subject: [PATCH 05/17] Track the signaturehelp session kind in signature help (#10970) --- .../FSharp.Editor/Completion/SignatureHelp.fs | 129 ++++++++++++------ 1 file changed, 84 insertions(+), 45 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs index 650d4ab25e4..0be70e446ae 100644 --- a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs +++ b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs @@ -33,12 +33,17 @@ type SignatureHelpItem = Parameters: SignatureHelpParameterInfo[] MainDescription: ResizeArray } +type CurrentSignatureHelpSessionKind = + | FunctionApplication + | MethodCall + type SignatureHelpData = { SignatureHelpItems: SignatureHelpItem[] ApplicableSpan: TextSpan ArgumentIndex: int ArgumentCount: int - ArgumentName: string option } + ArgumentName: string option + CurrentSignatureHelpSessionKind: CurrentSignatureHelpSessionKind } [] [)>] @@ -56,6 +61,8 @@ type internal FSharpSignatureHelpProvider static let oneColAfter (lp: LinePosition) = LinePosition(lp.Line,lp.Character+1) static let oneColBefore (lp: LinePosition) = LinePosition(lp.Line,max 0 (lp.Character-1)) + let mutable possibleCurrentSignatureHelpSessionKind = None + static member internal ProvideMethodsAsyncAux ( caretLinePos: LinePosition, @@ -212,7 +219,8 @@ type internal FSharpSignatureHelpProvider ApplicableSpan = applicableSpan ArgumentIndex = argumentIndex ArgumentCount = argumentCount - ArgumentName = argumentName } + ArgumentName = argumentName + CurrentSignatureHelpSessionKind = MethodCall } return! Some data } @@ -425,7 +433,8 @@ type internal FSharpSignatureHelpProvider ApplicableSpan = TextSpan(symbolSpan.End, caretPosition - symbolSpan.End) ArgumentIndex = argumentIndex ArgumentCount = displayArgs.Count - ArgumentName = None } + ArgumentName = None + CurrentSignatureHelpSessionKind = FunctionApplication } return! Some data | _ -> @@ -443,7 +452,8 @@ type internal FSharpSignatureHelpProvider options: FSharpProjectOptions, filePath: string, textVersionHash: int, - triggerTypedChar: char option + triggerTypedChar: char option, + possibleCurrentSignatureHelpSessionKind: CurrentSignatureHelpSessionKind option ) = asyncMaybe { let textLines = sourceText.Lines @@ -463,11 +473,23 @@ type internal FSharpSignatureHelpProvider let adjustedColumnChar = sourceText.[adjustedColumnInSource] - match triggerTypedChar with + match triggerTypedChar, possibleCurrentSignatureHelpSessionKind with // Generally ' ' indicates a function application, but it's also used commonly after a comma in a method call. // This means that the adjusted position relative to the caret could be a ',' or a '(' or '<', // which would mean we're already inside of a method call - not a function argument. So we bail if that's the case. - | Some ' ' when adjustedColumnChar <> ',' && adjustedColumnChar <> '(' && adjustedColumnChar <> '<' -> + | Some ' ', None when adjustedColumnChar <> ',' && adjustedColumnChar <> '(' && adjustedColumnChar <> '<' -> + return! + FSharpSignatureHelpProvider.ProvideParametersAsyncAux( + parseResults, + checkFileResults, + document.Id, + defines, + documentationBuilder, + sourceText, + caretPosition, + adjustedColumnInSource, + filePath) + | _, Some FunctionApplication when adjustedColumnChar <> ',' && adjustedColumnChar <> '(' && adjustedColumnChar <> '<' -> return! FSharpSignatureHelpProvider.ProvideParametersAsyncAux( parseResults, @@ -510,46 +532,63 @@ type internal FSharpSignatureHelpProvider Some triggerInfo.TriggerCharacter.Value else None - let! signatureHelpData = - FSharpSignatureHelpProvider.ProvideSignatureHelp( - document, - defines, - checker, - documentationBuilder, - sourceText, - position, - projectOptions, - document.FilePath, - textVersion.GetHashCode(), - triggerTypedChar) - let items = - signatureHelpData.SignatureHelpItems - |> Array.map (fun item -> - let parameters = - item.Parameters - |> Array.map (fun paramInfo -> - FSharpSignatureHelpParameter( - paramInfo.ParameterName, - paramInfo.IsOptional, - documentationFactory = (fun _ -> paramInfo.Documentation :> seq<_>), - displayParts = paramInfo.DisplayParts)) + let doWork () = + async { + let! signatureHelpDataOpt = + FSharpSignatureHelpProvider.ProvideSignatureHelp( + document, + defines, + checker, + documentationBuilder, + sourceText, + position, + projectOptions, + document.FilePath, + textVersion.GetHashCode(), + triggerTypedChar, + possibleCurrentSignatureHelpSessionKind) + match signatureHelpDataOpt with + | None -> + possibleCurrentSignatureHelpSessionKind <- None + return None + | Some signatureHelpData -> + let items = + signatureHelpData.SignatureHelpItems + |> Array.map (fun item -> + let parameters = + item.Parameters + |> Array.map (fun paramInfo -> + FSharpSignatureHelpParameter( + paramInfo.ParameterName, + paramInfo.IsOptional, + documentationFactory = (fun _ -> paramInfo.Documentation :> seq<_>), + displayParts = paramInfo.DisplayParts)) - FSharpSignatureHelpItem( - isVariadic=item.HasParamArrayArg, - documentationFactory=(fun _ -> item.Documentation :> seq<_>), - prefixParts=item.PrefixParts, - separatorParts=item.SeparatorParts, - suffixParts=item.SuffixParts, - parameters=parameters, - descriptionParts=item.MainDescription)) - - return - FSharpSignatureHelpItems( - items, - signatureHelpData.ApplicableSpan, - signatureHelpData.ArgumentIndex, - signatureHelpData.ArgumentCount, - Option.toObj signatureHelpData.ArgumentName) + FSharpSignatureHelpItem( + isVariadic=item.HasParamArrayArg, + documentationFactory=(fun _ -> item.Documentation :> seq<_>), + prefixParts=item.PrefixParts, + separatorParts=item.SeparatorParts, + suffixParts=item.SuffixParts, + parameters=parameters, + descriptionParts=item.MainDescription)) + + match signatureHelpData.CurrentSignatureHelpSessionKind with + | MethodCall -> + possibleCurrentSignatureHelpSessionKind <- Some MethodCall + | FunctionApplication -> + possibleCurrentSignatureHelpSessionKind <- Some FunctionApplication + + return + FSharpSignatureHelpItems( + items, + signatureHelpData.ApplicableSpan, + signatureHelpData.ArgumentIndex, + signatureHelpData.ArgumentCount, + Option.toObj signatureHelpData.ArgumentName) + |> Some + } + return! doWork () } |> Async.map Option.toObj |> RoslynHelpers.StartAsyncAsTask cancellationToken From e935115981fc4834a29e5c8290d2303eb2643d57 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Fri, 29 Jan 2021 08:17:47 -0800 Subject: [PATCH 06/17] [VS] Partial implementation of Go to definition for external IL symbols (#10956) * Initial commit * Openining document, but incorrect project association * Partial implementation for go-to-def of external symbols * Feedback --- .../src/FSharp.Editor/FSharp.Editor.fsproj | 1 + .../LanguageService/FSharpCheckerProvider.fs | 4 + .../FSharpProjectOptionsManager.fs | 2 + .../LanguageService/MetadataAsSource.fs | 156 ++++++++++++++++++ .../LanguageService/SingleFileWorkspaceMap.fs | 24 +++ .../Navigation/GoToDefinition.fs | 66 +++++--- .../Navigation/GoToDefinitionService.fs | 63 ++++++- .../Navigation/NavigableSymbolsService.fs | 8 +- 8 files changed, 290 insertions(+), 34 deletions(-) create mode 100644 vsintegration/src/FSharp.Editor/LanguageService/MetadataAsSource.fs diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index 474b952c478..5b81796d8d5 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -46,6 +46,7 @@ + diff --git a/vsintegration/src/FSharp.Editor/LanguageService/FSharpCheckerProvider.fs b/vsintegration/src/FSharp.Editor/LanguageService/FSharpCheckerProvider.fs index 56c074d78b2..f3212db489f 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/FSharpCheckerProvider.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/FSharpCheckerProvider.fs @@ -26,6 +26,8 @@ type internal FSharpCheckerProvider settings: EditorOptions ) = + let metadataAsSource = FSharpMetadataAsSourceService() + let tryGetMetadataSnapshot (path, timeStamp) = try let md = Microsoft.CodeAnalysis.ExternalAccess.FSharp.LanguageServices.FSharpVisualStudioWorkspaceExtensions.GetMetadata(workspace, path, timeStamp) @@ -85,3 +87,5 @@ type internal FSharpCheckerProvider member this.Checker = checker.Value + member _.MetadataAsSource = metadataAsSource + diff --git a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs index a35323f9de2..c077def059a 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/FSharpProjectOptionsManager.fs @@ -433,3 +433,5 @@ type internal FSharpProjectOptionsManager reactor.SetCpsCommandLineOptions(projectId, sourcePaths, options.ToArray()) member _.Checker = checkerProvider.Checker + + member _.MetadataAsSource = checkerProvider.MetadataAsSource diff --git a/vsintegration/src/FSharp.Editor/LanguageService/MetadataAsSource.fs b/vsintegration/src/FSharp.Editor/LanguageService/MetadataAsSource.fs new file mode 100644 index 00000000000..b1e0df38153 --- /dev/null +++ b/vsintegration/src/FSharp.Editor/LanguageService/MetadataAsSource.fs @@ -0,0 +1,156 @@ +// 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.Threading +open System.Collections.Immutable +open System.Diagnostics +open System.IO +open System.Linq +open System.Text +open System.Runtime.InteropServices +open System.Reflection.PortableExecutable + +open Microsoft.CodeAnalysis +open Microsoft.CodeAnalysis.FindSymbols +open Microsoft.CodeAnalysis.Text +open Microsoft.CodeAnalysis.Navigation +open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Navigation +open Microsoft.VisualStudio.ComponentModelHost + +open Microsoft.VisualStudio +open Microsoft.VisualStudio.Editor +open Microsoft.VisualStudio.Threading +open Microsoft.VisualStudio.Shell +open Microsoft.VisualStudio.Shell.Interop +open Microsoft.VisualStudio.TextManager.Interop + +open FSharp.Compiler.SourceCodeServices +open FSharp.Compiler.Text + +module internal MetadataAsSource = + + open Microsoft.CodeAnalysis.CSharp + open ICSharpCode.Decompiler + open ICSharpCode.Decompiler.CSharp + open ICSharpCode.Decompiler.Metadata + open ICSharpCode.Decompiler.CSharp.Transforms + open ICSharpCode.Decompiler.TypeSystem + + let generateTemporaryCSharpDocument (asmIdentity: AssemblyIdentity, name: string, metadataReferences) = + let rootPath = Path.Combine(Path.GetTempPath(), "MetadataAsSource") + let extension = ".cs" + let directoryName = Guid.NewGuid().ToString("N") + let temporaryFilePath = Path.Combine(rootPath, directoryName, name + extension) + + let projectId = ProjectId.CreateNewId() + + let parseOptions = CSharpParseOptions.Default.WithLanguageVersion(Microsoft.CodeAnalysis.CSharp.LanguageVersion.Preview) + // Just say it's always a DLL since we probably won't have a Main method + let compilationOptions = Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + + // We need to include the version information of the assembly so InternalsVisibleTo and stuff works + let assemblyInfoDocumentId = DocumentId.CreateNewId(projectId) + let assemblyInfoFileName = "AssemblyInfo" + extension + let assemblyInfoString = String.Format(@"[assembly: System.Reflection.AssemblyVersion(""{0}"")]", asmIdentity.Version) + + let assemblyInfoSourceTextContainer = SourceText.From(assemblyInfoString, Encoding.UTF8).Container + + let assemblyInfoDocument = + DocumentInfo.Create( + assemblyInfoDocumentId, + assemblyInfoFileName, + loader = TextLoader.From(assemblyInfoSourceTextContainer, VersionStamp.Default)) + + let generatedDocumentId = DocumentId.CreateNewId(projectId) + let documentInfo = + DocumentInfo.Create( + generatedDocumentId, + Path.GetFileName(temporaryFilePath), + filePath = temporaryFilePath, + loader = FileTextLoader(temporaryFilePath, Encoding.UTF8)) + + let projectInfo = + ProjectInfo.Create( + projectId, + VersionStamp.Default, + name = asmIdentity.Name, + assemblyName = asmIdentity.Name, + language = LanguageNames.CSharp, + compilationOptions = compilationOptions, + parseOptions = parseOptions, + documents = [|assemblyInfoDocument;documentInfo|], + metadataReferences = metadataReferences) + + (projectInfo, documentInfo) + + let decompileCSharp (symbolFullTypeName: string, assemblyLocation: string) = + let logger = new StringBuilder() + + // Initialize a decompiler with default settings. + let decompiler = CSharpDecompiler(assemblyLocation, DecompilerSettings()) + // Escape invalid identifiers to prevent Roslyn from failing to parse the generated code. + // (This happens for example, when there is compiler-generated code that is not yet recognized/transformed by the decompiler.) + decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()) + + let fullTypeName = FullTypeName(symbolFullTypeName) + + // Try to decompile; if an exception is thrown the caller will handle it + let text = decompiler.DecompileTypeAsString(fullTypeName) + + let text = text + "#if false // " + Environment.NewLine + let text = text + logger.ToString() + let text = text + "#endif" + Environment.NewLine + + SourceText.From(text) + + let showDocument (filePath, name, serviceProvider: IServiceProvider) = + let vsRunningDocumentTable4 = serviceProvider.GetService() + let fileAlreadyOpen = vsRunningDocumentTable4.IsMonikerValid(filePath) + + let openDocumentService = serviceProvider.GetService() + + let (_, _, _, _, windowFrame) = openDocumentService.OpenDocumentViaProject(filePath, ref VSConstants.LOGVIEWID.TextView_guid) + + let componentModel = serviceProvider.GetService() + let editorAdaptersFactory = componentModel.GetService(); + let documentCookie = vsRunningDocumentTable4.GetDocumentCookie(filePath) + let vsTextBuffer = vsRunningDocumentTable4.GetDocumentData(documentCookie) :?> IVsTextBuffer + let textBuffer = editorAdaptersFactory.GetDataBuffer(vsTextBuffer) + + if not fileAlreadyOpen then + ErrorHandler.ThrowOnFailure(windowFrame.SetProperty(int __VSFPROPID5.VSFPROPID_IsProvisional, true)) |> ignore + ErrorHandler.ThrowOnFailure(windowFrame.SetProperty(int __VSFPROPID5.VSFPROPID_OverrideCaption, name)) |> ignore + ErrorHandler.ThrowOnFailure(windowFrame.SetProperty(int __VSFPROPID5.VSFPROPID_OverrideToolTip, name)) |> ignore + + windowFrame.Show() |> ignore + + let textContainer = textBuffer.AsTextContainer() + let mutable workspace = Unchecked.defaultof<_> + if Workspace.TryGetWorkspace(textContainer, &workspace) then + let solution = workspace.CurrentSolution + let documentId = workspace.GetDocumentIdInCurrentContext(textContainer) + match box documentId with + | null -> None + | _ -> solution.GetDocument(documentId) |> Some + else + None + +[] +type internal FSharpMetadataAsSourceService() = + + member val CSharpFiles = System.Collections.Concurrent.ConcurrentDictionary(StringComparer.OrdinalIgnoreCase) + + member this.ShowCSharpDocument(projInfo: ProjectInfo, docInfo: DocumentInfo, text: Text.SourceText) = + let _ = + let directoryName = Path.GetDirectoryName(docInfo.FilePath) + if Directory.Exists(directoryName) |> not then + Directory.CreateDirectory(directoryName) |> ignore + use fileStream = new FileStream(docInfo.FilePath, IO.FileMode.Create) + use writer = new StreamWriter(fileStream) + text.Write(writer) + + this.CSharpFiles.[docInfo.FilePath] <- (projInfo, docInfo) + + MetadataAsSource.showDocument(docInfo.FilePath, docInfo.Name, ServiceProvider.GlobalProvider) \ No newline at end of file diff --git a/vsintegration/src/FSharp.Editor/LanguageService/SingleFileWorkspaceMap.fs b/vsintegration/src/FSharp.Editor/LanguageService/SingleFileWorkspaceMap.fs index 5947c59b8ae..0e565801fd3 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/SingleFileWorkspaceMap.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/SingleFileWorkspaceMap.fs @@ -33,11 +33,33 @@ type internal SingleFileWorkspaceMap(workspace: VisualStudioWorkspace, projectContext.AddSourceFile(filePath, sourceCodeKind = createSourceCodeKind filePath) projectContext + let createCSharpMetadataProjectContext (projInfo: ProjectInfo) (docInfo: DocumentInfo) = + let projectContext = projectContextFactory.CreateProjectContext(LanguageNames.CSharp, projInfo.Id.ToString(), projInfo.FilePath, Guid.NewGuid(), null, null) + projectContext.DisplayName <- projInfo.Name + projectContext.AddSourceFile(docInfo.FilePath, sourceCodeKind = SourceCodeKind.Regular) + + for metaRef in projInfo.MetadataReferences do + match metaRef with + | :? PortableExecutableReference as peRef -> + projectContext.AddMetadataReference(peRef.FilePath, MetadataReferenceProperties.Assembly) + | _ -> + () + + projectContext + do miscFilesWorkspace.DocumentOpened.Add(fun args -> let document = args.Document + if document.Project.Language = FSharpConstants.FSharpLanguageName && workspace.CurrentSolution.GetDocumentIdsWithFilePath(document.FilePath).Length = 0 then files.[document.FilePath] <- createProjectContext document.FilePath + + if optionsManager.MetadataAsSource.CSharpFiles.ContainsKey(document.FilePath) && workspace.CurrentSolution.GetDocumentIdsWithFilePath(document.FilePath).Length = 0 then + match optionsManager.MetadataAsSource.CSharpFiles.TryGetValue(document.FilePath) with + | true, (projInfo, docInfo) -> + files.[document.FilePath] <- createCSharpMetadataProjectContext projInfo docInfo + | _ -> + () ) workspace.DocumentOpened.Add(fun args -> @@ -57,6 +79,8 @@ type internal SingleFileWorkspaceMap(workspace: VisualStudioWorkspace, optionsManager.ClearSingleFileOptionsCache(document.Id) projectContext.Dispose() | _ -> () + + optionsManager.MetadataAsSource.CSharpFiles.TryRemove(document.FilePath) |> ignore ) do diff --git a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs index 00b8152934f..d5166440213 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinition.fs @@ -8,19 +8,28 @@ open System.Collections.Immutable open System.Diagnostics open System.IO open System.Linq +open System.Text open System.Runtime.InteropServices +open System.Reflection.PortableExecutable open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.FindSymbols open Microsoft.CodeAnalysis.Text open Microsoft.CodeAnalysis.Navigation open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Navigation +open Microsoft.VisualStudio.ComponentModelHost +open Microsoft.VisualStudio +open Microsoft.VisualStudio.Editor +open Microsoft.VisualStudio.Threading +open Microsoft.VisualStudio.Shell open Microsoft.VisualStudio.Shell.Interop +open Microsoft.VisualStudio.TextManager.Interop open FSharp.Compiler.SourceCodeServices open FSharp.Compiler.Text + module private Symbol = let fullName (root: ISymbol) : string = let rec inner parts (sym: ISymbol) = @@ -145,6 +154,11 @@ type internal StatusBar(statusBar: IVsStatusbar) = type internal FSharpGoToDefinitionNavigableItem(document, sourceSpan) = inherit FSharpNavigableItem(Glyph.BasicFile, ImmutableArray.Empty, document, sourceSpan) +[] +type internal FSharpGoToDefinitionResult = + | NavigableItem of FSharpNavigableItem + | ExternalAssembly of ProjectInfo * DocumentInfo * FSharpSymbolUse * FSharpExternalSymbol + type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpProjectOptionsManager) = let userOpName = "GoToDefinition" @@ -241,23 +255,28 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP match declarations with | FSharpFindDeclResult.ExternalDecl (assembly, targetExternalSym) -> - let! project = originDocument.Project.Solution.Projects |> Seq.tryFind (fun p -> p.AssemblyName.Equals(assembly, StringComparison.OrdinalIgnoreCase)) - let! symbols = SymbolFinder.FindSourceDeclarationsAsync(project, fun _ -> true) - - let roslynSymbols = - symbols - |> Seq.collect ExternalSymbol.ofRoslynSymbol - |> Array.ofSeq - - let! symbol = - roslynSymbols - |> Seq.tryPick (fun (sym, externalSym) -> - if externalSym = targetExternalSym then Some sym - else None - ) - - let! location = symbol.Locations |> Seq.tryHead - return (FSharpGoToDefinitionNavigableItem(project.GetDocument(location.SourceTree), location.SourceSpan), idRange) + let projectOpt = originDocument.Project.Solution.Projects |> Seq.tryFind (fun p -> p.AssemblyName.Equals(assembly, StringComparison.OrdinalIgnoreCase)) + match projectOpt with + | Some project -> + let! symbols = SymbolFinder.FindSourceDeclarationsAsync(project, fun _ -> true) + + let roslynSymbols = + symbols + |> Seq.collect ExternalSymbol.ofRoslynSymbol + |> Array.ofSeq + + let! symbol = + roslynSymbols + |> Seq.tryPick (fun (sym, externalSym) -> + if externalSym = targetExternalSym then Some sym + else None + ) + + let! location = symbol.Locations |> Seq.tryHead + return (FSharpGoToDefinitionResult.NavigableItem(FSharpGoToDefinitionNavigableItem(project.GetDocument(location.SourceTree), location.SourceSpan)), idRange) + | _ -> + let tmpProjInfo, tmpDocId = MetadataAsSource.generateTemporaryCSharpDocument(AssemblyIdentity(targetSymbolUse.Symbol.Assembly.QualifiedName), targetSymbolUse.Symbol.DisplayName, originDocument.Project.MetadataReferences) + return (FSharpGoToDefinitionResult.ExternalAssembly(tmpProjInfo, tmpDocId, targetSymbolUse, targetExternalSym), idRange) | FSharpFindDeclResult.DeclFound targetRange -> // if goto definition is called at we are alread at the declaration location of a symbol in @@ -275,7 +294,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP let! implTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (implSourceText, targetRange) let navItem = FSharpGoToDefinitionNavigableItem (implDocument, implTextSpan) - return (navItem, idRange) + return (FSharpGoToDefinitionResult.NavigableItem(navItem), idRange) else // jump from implementation to the corresponding signature let declarations = checkFileResults.GetDeclarationLocation (fcsTextLineNumber, lexerSymbol.Ident.idRange.EndColumn, textLineString, lexerSymbol.FullIsland, true) match declarations with @@ -284,7 +303,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP let! sigSourceText = sigDocument.GetTextAsync () |> liftTaskAsync let! sigTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (sigSourceText, targetRange) let navItem = FSharpGoToDefinitionNavigableItem (sigDocument, sigTextSpan) - return (navItem, idRange) + return (FSharpGoToDefinitionResult.NavigableItem(navItem), idRange) | _ -> return! None // when the target range is different follow the navigation convention of @@ -297,7 +316,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP // if the gotodef call originated from a signature and the returned target is a signature, navigate there if isSignatureFile targetRange.FileName && preferSignature then let navItem = FSharpGoToDefinitionNavigableItem (sigDocument, sigTextSpan) - return (navItem, idRange) + return (FSharpGoToDefinitionResult.NavigableItem(navItem), idRange) else // we need to get an FSharpSymbol from the targetRange found in the signature // that symbol will be used to find the destination in the corresponding implementation file let implFilePath = @@ -314,7 +333,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP let! implTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (implSourceText, targetRange) let navItem = FSharpGoToDefinitionNavigableItem (implDocument, implTextSpan) - return (navItem, idRange) + return (FSharpGoToDefinitionResult.NavigableItem(navItem), idRange) | _ -> return! None } @@ -330,8 +349,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP member this.FindDefinitionsForPeekTask(originDocument: Document, position: int, cancellationToken: CancellationToken) = this.FindDefinitionAtPosition(originDocument, position) |> Async.map ( - Option.map (fun (navItem, _) -> navItem :> FSharpNavigableItem) - >> Option.toArray + Option.toArray >> Array.toSeq) |> RoslynHelpers.StartAsyncAsTask cancellationToken @@ -343,7 +361,7 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: FSharpP /// Navigate to the positon of the textSpan in the provided document /// used by quickinfo link navigation when the tooltip contains the correct destination range. - member _.TryNavigateToTextSpan(document: Document, textSpan: TextSpan, statusBar: StatusBar) = + member _.TryNavigateToTextSpan(document: Document, textSpan: Microsoft.CodeAnalysis.Text.TextSpan, statusBar: StatusBar) = let navigableItem = FSharpGoToDefinitionNavigableItem(document, textSpan) let workspace = document.Project.Solution.Workspace let navigationService = workspace.Services.GetService() diff --git a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs index e8bb0d1fdc9..ba377a3929a 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/GoToDefinitionService.fs @@ -2,18 +2,24 @@ namespace Microsoft.VisualStudio.FSharp.Editor +open System open System.Composition +open System.IO open System.Threading open System.Threading.Tasks open Microsoft.CodeAnalysis +open Microsoft.CodeAnalysis.Text open Microsoft.CodeAnalysis.Editor open Microsoft.CodeAnalysis.Host.Mef open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Editor +open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Navigation open Microsoft.VisualStudio.Shell open Microsoft.VisualStudio.Shell.Interop -open System +open Microsoft.VisualStudio.LanguageServices + +open FSharp.Compiler.SourceCodeServices [)>] [)>] @@ -25,12 +31,22 @@ type internal FSharpGoToDefinitionService ) = let gtd = GoToDefinition(checkerProvider.Checker, projectInfoManager) - let statusBar = StatusBar(ServiceProvider.GlobalProvider.GetService()) + let statusBar = StatusBar(ServiceProvider.GlobalProvider.GetService()) + let metadataAsSourceService = checkerProvider.MetadataAsSource interface IFSharpGoToDefinitionService with /// Invoked with Peek Definition. member _.FindDefinitionsAsync (document: Document, position: int, cancellationToken: CancellationToken) = - gtd.FindDefinitionsForPeekTask(document, position, cancellationToken) + let task = gtd.FindDefinitionsForPeekTask(document, position, cancellationToken) + task.Wait(cancellationToken) + let results = task.Result + results + |> Seq.choose(fun (result, _) -> + match result with + | FSharpGoToDefinitionResult.NavigableItem(navItem) -> Some navItem + | _ -> None + ) + |> Task.FromResult /// Invoked with Go to Definition. /// Try to navigate to the definiton of the symbol at the symbolRange in the originDocument @@ -44,13 +60,44 @@ type internal FSharpGoToDefinitionService // Task.Wait throws an exception if the task is cancelled, so be sure to catch it. try // This call to Wait() is fine because we want to be able to provide the error message in the status bar. - gtdTask.Wait() + gtdTask.Wait(cancellationToken) if gtdTask.Status = TaskStatus.RanToCompletion && gtdTask.Result.IsSome then - let item, _ = gtdTask.Result.Value - gtd.NavigateToItem(item, statusBar) + let result, _ = gtdTask.Result.Value + match result with + | FSharpGoToDefinitionResult.NavigableItem(navItem) -> + gtd.NavigateToItem(navItem, statusBar) + // 'true' means do it, like Sheev Palpatine would want us to. + true + | FSharpGoToDefinitionResult.ExternalAssembly(tmpProjInfo, tmpDocInfo, targetSymbolUse, targetExternalSymbol) -> + match targetSymbolUse.Symbol.Assembly.FileName with + | Some targetSymbolAssemblyFileName -> + try + let symbolFullTypeName = + match targetExternalSymbol with + | FSharpExternalSymbol.Constructor(tyName, _) + | FSharpExternalSymbol.Event(tyName, _) + | FSharpExternalSymbol.Field(tyName, _) + | FSharpExternalSymbol.Method(tyName, _, _, _) + | FSharpExternalSymbol.Property(tyName, _) + | FSharpExternalSymbol.Type(tyName) -> tyName - // 'true' means do it, like Sheev Palpatine would want us to. - true + let text = MetadataAsSource.decompileCSharp(symbolFullTypeName, targetSymbolAssemblyFileName) + let tmpShownDocOpt = metadataAsSourceService.ShowCSharpDocument(tmpProjInfo, tmpDocInfo, text) + match tmpShownDocOpt with + | Some tmpShownDoc -> + let navItem = FSharpGoToDefinitionNavigableItem(tmpShownDoc, TextSpan()) + gtd.NavigateToItem(navItem, statusBar) + true + | _ -> + statusBar.TempMessage (SR.CannotDetermineSymbol()) + false + with + | _ -> + statusBar.TempMessage (SR.CannotDetermineSymbol()) + false + | _ -> + statusBar.TempMessage (SR.CannotDetermineSymbol()) + false else statusBar.TempMessage (SR.CannotDetermineSymbol()) false diff --git a/vsintegration/src/FSharp.Editor/Navigation/NavigableSymbolsService.fs b/vsintegration/src/FSharp.Editor/Navigation/NavigableSymbolsService.fs index 2c7b1b7a894..941a9c30e6e 100644 --- a/vsintegration/src/FSharp.Editor/Navigation/NavigableSymbolsService.fs +++ b/vsintegration/src/FSharp.Editor/Navigation/NavigableSymbolsService.fs @@ -58,13 +58,17 @@ type internal FSharpNavigableSymbolSource(checkerProvider: FSharpCheckerProvider statusBar.Clear() if gtdTask.Status = TaskStatus.RanToCompletion && gtdTask.Result.IsSome then - let navigableItem, range = gtdTask.Result.Value + let result, range = gtdTask.Result.Value let declarationTextSpan = RoslynHelpers.FSharpRangeToTextSpan(sourceText, range) let declarationSpan = Span(declarationTextSpan.Start, declarationTextSpan.Length) let symbolSpan = SnapshotSpan(snapshot, declarationSpan) - return FSharpNavigableSymbol(navigableItem, symbolSpan, gtd, statusBar) :> INavigableSymbol + match result with + | FSharpGoToDefinitionResult.NavigableItem(navItem) -> + return FSharpNavigableSymbol(navItem, symbolSpan, gtd, statusBar) :> INavigableSymbol + | _ -> + return null else statusBar.TempMessage(SR.CannotDetermineSymbol()) From 494bc60e85a0cccb5848fb020330be31d4f3beb1 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 29 Jan 2021 20:34:43 +0300 Subject: [PATCH 07/17] SyntaxTree: always keep parsed implicit constructors (#10967) --- src/fsharp/CheckDeclarations.fs | 6 +++--- src/fsharp/SyntaxTree.fs | 1 + src/fsharp/pars.fsy | 12 ++++++------ src/fsharp/service/ServiceAssemblyContent.fs | 2 +- src/fsharp/service/ServiceInterfaceStubGenerator.fs | 2 +- src/fsharp/service/ServiceNavigation.fs | 4 ++-- src/fsharp/service/ServiceParseTreeWalk.fs | 2 +- src/fsharp/service/ServiceStructure.fs | 2 +- src/fsharp/service/ServiceUntypedParse.fs | 6 +++--- src/fsharp/service/ServiceXmlDocParser.fs | 2 +- .../SurfaceArea.netstandard.fs | 4 +++- tests/service/InteractiveCheckerTests.fs | 2 +- tests/service/ServiceUntypedParseTests.fs | 2 +- 13 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/fsharp/CheckDeclarations.fs b/src/fsharp/CheckDeclarations.fs index 6d2d38ef198..7ef13ee1000 100644 --- a/src/fsharp/CheckDeclarations.fs +++ b/src/fsharp/CheckDeclarations.fs @@ -3165,7 +3165,7 @@ module EstablishTypeDefinitionCores = [ for def in defs do match def with | SynModuleDecl.Types (typeSpecs, _) -> - for (TypeDefn(ComponentInfo(_, typars, _, ids, _, _, _, _), trepr, _, _)) in typeSpecs do + for (TypeDefn(ComponentInfo(_, typars, _, ids, _, _, _, _), trepr, _, _, _)) in typeSpecs do if isNil typars then match trepr with | SynTypeDefnRepr.ObjectModel(TyconAugmentation, _, _) -> () @@ -4642,7 +4642,7 @@ module TcDeclarations = /// where simpleRepr can contain inherit type, declared fields and virtual slots. /// body = members /// where members contain methods/overrides, also implicit ctor, inheritCall and local definitions. - let rec private SplitTyconDefn (TypeDefn(synTyconInfo, trepr, extraMembers, _)) = + let rec private SplitTyconDefn (TypeDefn(synTyconInfo, trepr, extraMembers, _, _)) = let implements1 = List.choose (function SynMemberDefn.Interface (ty, _, _) -> Some(ty, ty.Range) | _ -> None) extraMembers match trepr with | SynTypeDefnRepr.ObjectModel(kind, cspec, m) -> @@ -5528,7 +5528,7 @@ and TcModuleOrNamespaceElementsMutRec (cenv: cenv) parent typeNames m envInitial | SynModuleDecl.Exception (SynExceptionDefn(repr, members, _), _m) -> let (SynExceptionDefnRepr(synAttrs, UnionCase(_, id, _args, _, _, _), _repr, doc, vis, m)) = repr let compInfo = ComponentInfo(synAttrs, [], [], [id], doc, false, vis, id.idRange) - let decls = [ MutRecShape.Tycon(SynTypeDefn.TypeDefn(compInfo, SynTypeDefnRepr.Exception repr, members, m)) ] + let decls = [ MutRecShape.Tycon(SynTypeDefn.TypeDefn(compInfo, SynTypeDefnRepr.Exception repr, members, None, m)) ] decls, (false, false, attrs) | SynModuleDecl.HashDirective _ -> diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index 6e9b68280c6..b1d210ebabb 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -1877,6 +1877,7 @@ type SynTypeDefn = typeInfo: SynComponentInfo * typeRepr: SynTypeDefnRepr * members: SynMemberDefns * + implicitConstructor: SynMemberDefn option * range: range /// Gets the syntax range of this construct diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index cfce563057b..daac933cc9a 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -1271,8 +1271,8 @@ moduleDefn: /* 'type' definitions */ | opt_attributes opt_declVisibility typeKeyword tyconDefn tyconDefnList { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) - let (TypeDefn(ComponentInfo(cas, a, cs, b, c, d, d2, d3), e, f, g)) = $4 - let tc = (TypeDefn(ComponentInfo($1@cas, a, cs, b, c, d, d2, d3), e, f, g)) + let (TypeDefn(ComponentInfo(cas, a, cs, b, c, d, d2, d3), e, f, g, h)) = $4 + let tc = (TypeDefn(ComponentInfo($1@cas, a, cs, b, c, d, d2, d3), e, f, g, h)) let types = tc :: $5 [ SynModuleDecl.Types(types, (rhs parseState 3, types) ||> unionRangeWithListBy (fun t -> t.Range) ) ] } @@ -1499,7 +1499,7 @@ tyconDefnList: /* A type definition */ tyconDefn: | typeNameInfo - { TypeDefn($1, SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None($1.Range), $1.Range), [], $1.Range) } + { TypeDefn($1, SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.None($1.Range), $1.Range), [], None, $1.Range) } | typeNameInfo opt_equals tyconDefnRhsBlock { if not $2 then ( @@ -1512,11 +1512,11 @@ tyconDefn: let (tcDefRepr:SynTypeDefnRepr), members = $3 nameRange let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range let mWhole = (declRange, members) ||> unionRangeWithListBy (fun (mem:SynMemberDefn) -> mem.Range) - TypeDefn($1, tcDefRepr, members, mWhole) } + TypeDefn($1, tcDefRepr, members, None, mWhole) } | typeNameInfo tyconDefnAugmentation { let m = (rhs parseState 1, $2) ||> unionRangeWithListBy (fun mem -> mem.Range) - TypeDefn($1, SynTypeDefnRepr.ObjectModel(TyconAugmentation, [], m), $2, m) } + TypeDefn($1, SynTypeDefnRepr.ObjectModel(TyconAugmentation, [], m), $2, None, m) } | typeNameInfo opt_attributes opt_declVisibility opt_HIGH_PRECEDENCE_APP simplePatterns optAsSpec EQUALS tyconDefnRhsBlock { let vis, spats, az = $3, $5, $6 @@ -1533,7 +1533,7 @@ tyconDefn: let declRange = unionRanges (rhs parseState 1) tcDefRepr.Range let mWhole = (declRange, members) ||> unionRangeWithListBy (fun (mem:SynMemberDefn) -> mem.Range) - TypeDefn($1, tcDefRepr, members, mWhole) } + TypeDefn($1, tcDefRepr, members, Some memberCtorPattern, mWhole) } /* The right-hand-side of a type definition */ diff --git a/src/fsharp/service/ServiceAssemblyContent.fs b/src/fsharp/service/ServiceAssemblyContent.fs index 69865f77f40..f7689520678 100644 --- a/src/fsharp/service/ServiceAssemblyContent.fs +++ b/src/fsharp/service/ServiceAssemblyContent.fs @@ -753,7 +753,7 @@ module ParsedInput = | SynTypeDefnSigRepr.Simple(defn, _) -> walkTypeDefnSimple defn | SynTypeDefnSigRepr.Exception _ -> () - and walkTypeDefn (TypeDefn (info, repr, members, _)) = + and walkTypeDefn (TypeDefn (info, repr, members, _, _)) = let isTypeExtensionOrAlias = match repr with | SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.TyconAugmentation, _, _) diff --git a/src/fsharp/service/ServiceInterfaceStubGenerator.fs b/src/fsharp/service/ServiceInterfaceStubGenerator.fs index 85b284773a4..9b560ee58d4 100644 --- a/src/fsharp/service/ServiceInterfaceStubGenerator.fs +++ b/src/fsharp/service/ServiceInterfaceStubGenerator.fs @@ -702,7 +702,7 @@ module InterfaceStubGenerator = | SynModuleDecl.Open _ -> None - and walkSynTypeDefn(TypeDefn(_componentInfo, representation, members, range)) = + and walkSynTypeDefn(TypeDefn(_componentInfo, representation, members, _, range)) = if not <| rangeContainsPos range pos then None else diff --git a/src/fsharp/service/ServiceNavigation.fs b/src/fsharp/service/ServiceNavigation.fs index 06165e3220b..42b5f1acaa7 100755 --- a/src/fsharp/service/ServiceNavigation.fs +++ b/src/fsharp/service/ServiceNavigation.fs @@ -173,7 +173,7 @@ module NavigationImpl = let nested = processMembers membDefns FSharpEnclosingEntityKind.Exception |> snd processExnDefnRepr baseName nested repr - and processTycon baseName (TypeDefn(ComponentInfo(_, _, _, lid, _, _, access, _), repr, membDefns, m)) = + and processTycon baseName (TypeDefn(ComponentInfo(_, _, _, lid, _, _, access, _), repr, membDefns, _, m)) = let topMembers = processMembers membDefns FSharpEnclosingEntityKind.Class |> snd match repr with | SynTypeDefnRepr.Exception repr -> processExnDefnRepr baseName [] repr @@ -686,7 +686,7 @@ module NavigateTo = | SynModuleDecl.HashDirective _ | SynModuleDecl.Open _ -> () - and walkSynTypeDefn(TypeDefn(componentInfo, representation, members, _)) container = + and walkSynTypeDefn(TypeDefn(componentInfo, representation, members, _, _)) container = let container = addComponentInfo ContainerType.Type NavigableItemKind.Type componentInfo false container walkSynTypeDefnRepr representation container for m in members do diff --git a/src/fsharp/service/ServiceParseTreeWalk.fs b/src/fsharp/service/ServiceParseTreeWalk.fs index e7748415c3c..086a2998923 100755 --- a/src/fsharp/service/ServiceParseTreeWalk.fs +++ b/src/fsharp/service/ServiceParseTreeWalk.fs @@ -653,7 +653,7 @@ module public AstTraversal = #endif ) - and traverseSynTypeDefn path (SynTypeDefn.TypeDefn(synComponentInfo, synTypeDefnRepr, synMemberDefns, tRange) as tydef) = + and traverseSynTypeDefn path (SynTypeDefn.TypeDefn(synComponentInfo, synTypeDefnRepr, synMemberDefns, _, tRange) as tydef) = let path = TraverseStep.TypeDefn tydef :: path match visitor.VisitComponentInfo synComponentInfo with diff --git a/src/fsharp/service/ServiceStructure.fs b/src/fsharp/service/ServiceStructure.fs index 9294d1b609f..9cd2877c6db 100644 --- a/src/fsharp/service/ServiceStructure.fs +++ b/src/fsharp/service/ServiceStructure.fs @@ -537,7 +537,7 @@ module Structure = parseAttributes attrs | _ -> () - and parseTypeDefn (TypeDefn(ComponentInfo(_, typeArgs, _, _, _, _, _, r), objectModel, members, fullrange)) = + and parseTypeDefn (TypeDefn(ComponentInfo(_, typeArgs, _, _, _, _, _, r), objectModel, members, _, fullrange)) = let typeArgsRange = rangeOfTypeArgsElse r typeArgs let collapse = Range.endToEnd (Range.modEnd 1 typeArgsRange) fullrange match objectModel with diff --git a/src/fsharp/service/ServiceUntypedParse.fs b/src/fsharp/service/ServiceUntypedParse.fs index 626898a9db2..9a11ab9eca3 100755 --- a/src/fsharp/service/ServiceUntypedParse.fs +++ b/src/fsharp/service/ServiceUntypedParse.fs @@ -600,7 +600,7 @@ type FSharpParseFileResults(errors: FSharpDiagnostic[], input: ParsedInput optio yield! walkExpr true e ] // Process a class declaration or F# type declaration - let rec walkTycon (TypeDefn(ComponentInfo(_, _, _, _, _, _, _, _), repr, membDefns, m)) = + let rec walkTycon (TypeDefn(ComponentInfo(_, _, _, _, _, _, _, _), repr, membDefns, _, m)) = if not (isMatchRange m) then [] else [ for memb in membDefns do yield! walkMember memb match repr with @@ -1236,7 +1236,7 @@ module UntypedParseImpl = | SynTypeDefnSigRepr.Simple(defn, _) -> walkTypeDefnSimple defn | SynTypeDefnSigRepr.Exception(_) -> None - and walkTypeDefn (TypeDefn (info, repr, members, _)) = + and walkTypeDefn (TypeDefn (info, repr, members, _, _)) = walkComponentInfo false info |> Option.orElse (walkTypeDefnRepr repr) |> Option.orElse (List.tryPick walkMember members) @@ -1489,7 +1489,7 @@ module UntypedParseImpl = let contextFromTreePath completionPath = // detect records usage in constructor match path with - | TS.Expr(_) :: TS.Binding(_) :: TS.MemberDefn(_) :: TS.TypeDefn(SynTypeDefn.TypeDefn(ComponentInfo(_, _, _, [id], _, _, _, _), _, _, _)) :: _ -> + | TS.Expr(_) :: TS.Binding(_) :: TS.MemberDefn(_) :: TS.TypeDefn(SynTypeDefn.TypeDefn(ComponentInfo(_, _, _, [id], _, _, _, _), _, _, _, _)) :: _ -> RecordContext.Constructor(id.idText) | _ -> RecordContext.New completionPath match field with diff --git a/src/fsharp/service/ServiceXmlDocParser.fs b/src/fsharp/service/ServiceXmlDocParser.fs index 222ebdfa2b4..7c1342eb050 100644 --- a/src/fsharp/service/ServiceXmlDocParser.fs +++ b/src/fsharp/service/ServiceXmlDocParser.fs @@ -96,7 +96,7 @@ module XmlDocParsing = and getXmlDocablesSynModuleOrNamespace (SynModuleOrNamespace(_, _, _, synModuleDecls, _, _, _, _)) = (synModuleDecls |> List.collect getXmlDocablesSynModuleDecl) - and getXmlDocablesSynTypeDefn (SynTypeDefn.TypeDefn(ComponentInfo(synAttributes, _, _, _, preXmlDoc, _, _, compRange), synTypeDefnRepr, synMemberDefns, tRange)) = + and getXmlDocablesSynTypeDefn (SynTypeDefn.TypeDefn(ComponentInfo(synAttributes, _, _, _, preXmlDoc, _, _, compRange), synTypeDefnRepr, synMemberDefns, _, tRange)) = let stuff = match synTypeDefnRepr with | SynTypeDefnRepr.ObjectModel(_, synMemberDefns, _) -> (synMemberDefns |> List.collect getXmlDocablesSynMemberDefn) diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index a20fead0753..fcb169c868a 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -8870,7 +8870,9 @@ FSharp.Compiler.SyntaxTree+SynTypeDefn: Microsoft.FSharp.Collections.FSharpList` FSharp.Compiler.SyntaxTree+SynTypeDefn: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynMemberDefn] members FSharp.Compiler.SyntaxTree+SynTypeDefn: SynComponentInfo get_typeInfo() FSharp.Compiler.SyntaxTree+SynTypeDefn: SynComponentInfo typeInfo -FSharp.Compiler.SyntaxTree+SynTypeDefn: SynTypeDefn NewTypeDefn(SynComponentInfo, SynTypeDefnRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynMemberDefn], FSharp.Compiler.Text.Range) +FSharp.Compiler.SyntaxTree+SynTypeDefn: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTree+SynMemberDefn] get_implicitConstructor() +FSharp.Compiler.SyntaxTree+SynTypeDefn: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTree+SynMemberDefn] implicitConstructor +FSharp.Compiler.SyntaxTree+SynTypeDefn: SynTypeDefn NewTypeDefn(SynComponentInfo, SynTypeDefnRepr, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynMemberDefn], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTree+SynMemberDefn], FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTree+SynTypeDefn: SynTypeDefnRepr get_typeRepr() FSharp.Compiler.SyntaxTree+SynTypeDefn: SynTypeDefnRepr typeRepr FSharp.Compiler.SyntaxTree+SynTypeDefn: System.String ToString() diff --git a/tests/service/InteractiveCheckerTests.fs b/tests/service/InteractiveCheckerTests.fs index 3f24bd79df7..fbaed2c1bf7 100644 --- a/tests/service/InteractiveCheckerTests.fs +++ b/tests/service/InteractiveCheckerTests.fs @@ -31,7 +31,7 @@ let internal identsAndRanges (input: ParsedInput) = // TODO : attrs, typarDecls and typarConstraints [identAndRange (longIdentToString longIdent) range] let extractFromTypeDefn (typeDefn: SynTypeDefn) = - let (SynTypeDefn.TypeDefn(componentInfo, _repr, _members, _)) = typeDefn + let (SynTypeDefn.TypeDefn(componentInfo, _repr, _members, _, _)) = typeDefn // TODO : repr and members extractFromComponentInfo componentInfo let rec extractFromModuleDecl (moduleDecl: SynModuleDecl) = diff --git a/tests/service/ServiceUntypedParseTests.fs b/tests/service/ServiceUntypedParseTests.fs index 5d00a4f4400..edf8d9235f9 100644 --- a/tests/service/ServiceUntypedParseTests.fs +++ b/tests/service/ServiceUntypedParseTests.fs @@ -199,7 +199,7 @@ module TypeMemberRanges = let getTypeMemberRange source = let (SynModuleOrNamespace (decls = decls)) = parseSourceCodeAndGetModule source match decls with - | [ SynModuleDecl.Types ([ TypeDefn (_, SynTypeDefnRepr.ObjectModel (_, memberDecls, _), _, _) ], _) ] -> + | [ SynModuleDecl.Types ([ TypeDefn (_, SynTypeDefnRepr.ObjectModel (_, memberDecls, _), _, _, _) ], _) ] -> memberDecls |> List.map (fun memberDecl -> getRangeCoords memberDecl.Range) | _ -> failwith "Could not get member" From 3b447ad40e39d2ed26531ff04c40050720f7cbdc Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Sat, 30 Jan 2021 06:23:41 -0800 Subject: [PATCH 08/17] ToString('N') precision has changed for net5.0 (#10981) --- .../Compiler/Language/StringInterpolation.fs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/fsharp/Compiler/Language/StringInterpolation.fs b/tests/fsharp/Compiler/Language/StringInterpolation.fs index fed6b2aeb76..a0ba57ea51c 100644 --- a/tests/fsharp/Compiler/Language/StringInterpolation.fs +++ b/tests/fsharp/Compiler/Language/StringInterpolation.fs @@ -325,16 +325,16 @@ check "fwejwflpej2" (fmt $"abc") "abc" check "fwejwflpej3" (fmt $"abc{1}") "abc1" check "fwejwflpej6" (fmt_us $"abc {30000} def") "abc 30000 def" check "fwejwflpej7" (fmt_de $"abc {30000} def") "abc 30000 def" -check "fwejwflpej8" (fmt_us $"abc {30000:N} def") "abc 30,000.00 def" -check "fwejwflpej9" (fmt_de $"abc {30000:N} def") "abc 30.000,00 def" +check "fwejwflpej8" (fmt_us $"abc {30000:N2} def") "abc 30,000.00 def" +check "fwejwflpej9" (fmt_de $"abc {30000:N2} def") "abc 30.000,00 def" check "fwejwflpej10" (fmt_us $"abc {30000} def {40000} hij") "abc 30000 def 40000 hij" check "fwejwflpej11" (fmt_us $"abc {30000,-10} def {40000} hij") "abc 30000 def 40000 hij" check "fwejwflpej12" (fmt_us $"abc {30000,10} def {40000} hij") "abc 30000 def 40000 hij" check "fwejwflpej13" (fmt_de $"abc {30000} def {40000} hij") "abc 30000 def 40000 hij" -check "fwejwflpej14" (fmt_us $"abc {30000:N} def {40000:N} hij") "abc 30,000.00 def 40,000.00 hij" -check "fwejwflpej15" (fmt_de $"abc {30000:N} def {40000:N} hij") "abc 30.000,00 def 40.000,00 hij" -check "fwejwflpej16" (fmt_de $"abc {30000,10:N} def {40000:N} hij") "abc 30.000,00 def 40.000,00 hij" -check "fwejwflpej17" (fmt_de $"abc {30000,-10:N} def {40000:N} hij") "abc 30.000,00 def 40.000,00 hij" +check "fwejwflpej14" (fmt_us $"abc {30000:N2} def {40000:N2} hij") "abc 30,000.00 def 40,000.00 hij" +check "fwejwflpej15" (fmt_de $"abc {30000:N2} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" +check "fwejwflpej16" (fmt_de $"abc {30000,10:N} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" +check "fwejwflpej17" (fmt_de $"abc {30000,-10:N} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" """ @@ -354,16 +354,16 @@ check "fwejwflpej2" (fmt $"abc") "abc" check "fwejwflpej3" (fmt $"abc{1}") "abc1" check "fwejwflpej6" (fmt_us $"abc {30000} def") "abc 30000 def" check "fwejwflpej7" (fmt_de $"abc {30000} def") "abc 30000 def" -check "fwejwflpej8" (fmt_us $"abc {30000:N} def") "abc 30,000.00 def" -check "fwejwflpej9" (fmt_de $"abc {30000:N} def") "abc 30.000,00 def" +check "fwejwflpej8" (fmt_us $"abc {30000:N2} def") "abc 30,000.00 def" +check "fwejwflpej9" (fmt_de $"abc {30000:N2} def") "abc 30.000,00 def" check "fwejwflpej10" (fmt_us $"abc {30000} def {40000} hij") "abc 30000 def 40000 hij" check "fwejwflpej11" (fmt_us $"abc {30000,-10} def {40000} hij") "abc 30000 def 40000 hij" check "fwejwflpej12" (fmt_us $"abc {30000,10} def {40000} hij") "abc 30000 def 40000 hij" check "fwejwflpej13" (fmt_de $"abc {30000} def {40000} hij") "abc 30000 def 40000 hij" -check "fwejwflpej14" (fmt_us $"abc {30000:N} def {40000:N} hij") "abc 30,000.00 def 40,000.00 hij" -check "fwejwflpej15" (fmt_de $"abc {30000:N} def {40000:N} hij") "abc 30.000,00 def 40.000,00 hij" -check "fwejwflpej16" (fmt_de $"abc {30000,10:N} def {40000:N} hij") "abc 30.000,00 def 40.000,00 hij" -check "fwejwflpej17" (fmt_de $"abc {30000,-10:N} def {40000:N} hij") "abc 30.000,00 def 40.000,00 hij" +check "fwejwflpej14" (fmt_us $"abc {30000:N2} def {40000:N2} hij") "abc 30,000.00 def 40,000.00 hij" +check "fwejwflpej15" (fmt_de $"abc {30000:N2} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" +check "fwejwflpej16" (fmt_de $"abc {30000,10:N2} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" +check "fwejwflpej17" (fmt_de $"abc {30000,-10:N2} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" """ From b0999f9b9bca840461e7855e0ba791d0512f0833 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 30 Jan 2021 14:47:23 +0000 Subject: [PATCH 09/17] Update dependencies from https://github.com/dotnet/arcade build 20210128.12 (#10982) [main] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 4 ++-- eng/common/sdl/init-sdl.ps1 | 13 +------------ global.json | 2 +- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0fed70a5eec..f68c0362fd5 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - d7da80d96daf724706aafa450e00222fe659af13 + 3233c41c837f72827efd8f827b538e047334847d diff --git a/eng/common/sdl/init-sdl.ps1 b/eng/common/sdl/init-sdl.ps1 index a68bf0b88ea..bb6a4297110 100644 --- a/eng/common/sdl/init-sdl.ps1 +++ b/eng/common/sdl/init-sdl.ps1 @@ -29,18 +29,7 @@ $zipFile = "$WorkingDirectory/gdn.zip" Add-Type -AssemblyName System.IO.Compression.FileSystem $gdnFolder = (Join-Path $WorkingDirectory '.gdn') -try { - # We try to download the zip; if the request fails (e.g. the file doesn't exist), we catch it and init guardian instead - Write-Host 'Downloading gdn folder from internal config repostiory...' - Invoke-WebRequest -Headers @{ "Accept"="application/zip"; "Authorization"="Basic $encodedPat" } -Uri $uri -OutFile $zipFile - if (Test-Path $gdnFolder) { - # Remove the gdn folder if it exists (it shouldn't unless there's too much caching; this is just in case) - Remove-Item -Force -Recurse $gdnFolder - } - [System.IO.Compression.ZipFile]::ExtractToDirectory($zipFile, $WorkingDirectory) - Write-Host $gdnFolder - ExitWithExitCode 0 -} catch [System.Net.WebException] { } # Catch and ignore webexception + try { # if the folder does not exist, we'll do a guardian init and push it to the remote repository Write-Host 'Initializing Guardian...' diff --git a/global.json b/global.json index b82dff7bac2..258015e7901 100644 --- a/global.json +++ b/global.json @@ -13,7 +13,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21076.1", + "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21078.12", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 2c1c29d496d2604cc071ed863b0124f0351ef280 Mon Sep 17 00:00:00 2001 From: Scott Hutchinson Date: Sat, 30 Jan 2021 13:49:12 -0800 Subject: [PATCH 10/17] Prevent tests from attempting to write to C:\Windows\System32 (#10888) --- tests/FSharp.Test.Utilities/TestFramework.fs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Test.Utilities/TestFramework.fs b/tests/FSharp.Test.Utilities/TestFramework.fs index f2f8b2c5679..9aa5ea0a40d 100644 --- a/tests/FSharp.Test.Utilities/TestFramework.fs +++ b/tests/FSharp.Test.Utilities/TestFramework.fs @@ -5,6 +5,7 @@ module TestFramework open Microsoft.Win32 open System open System.IO +open System.Reflection open System.Text.RegularExpressions open System.Diagnostics open Scripting @@ -55,8 +56,17 @@ module Commands = else p.WaitForExit() #if DEBUG - File.WriteAllLines(Path.Combine(workingDir, "StandardOutput.txt"), outputList) - File.WriteAllLines(Path.Combine(workingDir, "StandardError.txt"), errorsList) + let workingDir' = + if workingDir = "" + then + // Assign working dir to prevent default to C:\Windows\System32 + let executionLocation = Assembly.GetExecutingAssembly().Location + Path.GetDirectoryName executionLocation + else + workingDir + + File.WriteAllLines(Path.Combine(workingDir', "StandardOutput.txt"), outputList) + File.WriteAllLines(Path.Combine(workingDir', "StandardError.txt"), errorsList) #endif p.ExitCode, outputList.ToArray(), errorsList.ToArray() | None -> -1, Array.empty, Array.empty From 15390be98b33fb2f430edb95d367db4fe206cebd Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 1 Feb 2021 08:18:39 -0800 Subject: [PATCH 11/17] Two more Formatted Ns (#10985) --- tests/fsharp/Compiler/Language/StringInterpolation.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fsharp/Compiler/Language/StringInterpolation.fs b/tests/fsharp/Compiler/Language/StringInterpolation.fs index a0ba57ea51c..f448704f978 100644 --- a/tests/fsharp/Compiler/Language/StringInterpolation.fs +++ b/tests/fsharp/Compiler/Language/StringInterpolation.fs @@ -333,8 +333,8 @@ check "fwejwflpej12" (fmt_us $"abc {30000,10} def {40000} hij") "abc 30000 check "fwejwflpej13" (fmt_de $"abc {30000} def {40000} hij") "abc 30000 def 40000 hij" check "fwejwflpej14" (fmt_us $"abc {30000:N2} def {40000:N2} hij") "abc 30,000.00 def 40,000.00 hij" check "fwejwflpej15" (fmt_de $"abc {30000:N2} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" -check "fwejwflpej16" (fmt_de $"abc {30000,10:N} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" -check "fwejwflpej17" (fmt_de $"abc {30000,-10:N} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" +check "fwejwflpej16" (fmt_de $"abc {30000,10:N2} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" +check "fwejwflpej17" (fmt_de $"abc {30000,-10:N2} def {40000:N2} hij") "abc 30.000,00 def 40.000,00 hij" """ From 11a2c71e2af14a18d5d713cdc05a69e6ccfeb0ad Mon Sep 17 00:00:00 2001 From: Phillip Carter Date: Mon, 1 Feb 2021 10:32:29 -0800 Subject: [PATCH 12/17] Account for properties and qualified items in the 'Use <- to mutate' codefix (#10977) --- .../CodeFix/UseMutationWhenValueIsMutable.fs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/vsintegration/src/FSharp.Editor/CodeFix/UseMutationWhenValueIsMutable.fs b/vsintegration/src/FSharp.Editor/CodeFix/UseMutationWhenValueIsMutable.fs index 3a3ea50cb5d..a0d423ca149 100644 --- a/vsintegration/src/FSharp.Editor/CodeFix/UseMutationWhenValueIsMutable.fs +++ b/vsintegration/src/FSharp.Editor/CodeFix/UseMutationWhenValueIsMutable.fs @@ -2,6 +2,7 @@ namespace Microsoft.VisualStudio.FSharp.Editor +open System open System.Composition open System.Threading open System.Threading.Tasks @@ -36,20 +37,29 @@ type internal FSharpUseMutationWhenValueIsMutableFixProvider let document = context.Document do! Option.guard (not(isSignatureFile document.FilePath)) - let position = context.Span.Start let checker = checkerProvider.Checker let! parsingOptions, projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document, CancellationToken.None, userOpName) let! sourceText = document.GetTextAsync () |> liftTaskAsync let defines = CompilerEnvironment.GetCompilationDefinesForEditing parsingOptions - let textLine = sourceText.Lines.GetLineFromPosition position - let textLinePos = sourceText.Lines.GetLinePosition position + + let adjustedPosition = + let rec loop ch pos = + if Char.IsWhiteSpace(ch) then + pos + else + loop sourceText.[pos + 1] (pos + 1) + + loop sourceText.[context.Span.Start] context.Span.Start + + let textLine = sourceText.Lines.GetLineFromPosition adjustedPosition + let textLinePos = sourceText.Lines.GetLinePosition adjustedPosition let fcsTextLineNumber = Line.fromZ textLinePos.Line let! _, _, checkFileResults = checker.ParseAndCheckDocument (document, projectOptions, sourceText=sourceText, userOpName=userOpName) - let! lexerSymbol = Tokenizer.getSymbolAtPosition (document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy, false, false) + let! lexerSymbol = Tokenizer.getSymbolAtPosition (document.Id, sourceText, adjustedPosition, document.FilePath, defines, SymbolLookupKind.Greedy, false, false) let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, lexerSymbol.Ident.idRange.EndColumn, textLine.ToString(), lexerSymbol.FullIsland) match symbolUse.Symbol with - | :? FSharpMemberOrFunctionOrValue as mfv when mfv.IsValue && mfv.IsMutable -> + | :? FSharpMemberOrFunctionOrValue as mfv when mfv.IsMutable || mfv.HasSetterMethod -> let title = SR.UseMutationWhenValueIsMutable() let! symbolSpan = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate) let mutable pos = symbolSpan.End From d6629e5261079fe0a504bcb20d65e56eda126181 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 1 Feb 2021 11:16:03 -0800 Subject: [PATCH 13/17] Disable - LargeRecordDoesNotStackOverflow due to: https://github.com/dotnet/runtime/issues/47663 (#10979) --- FSharpBuild.Directory.Build.props | 3 ++- src/buildtools/fslex/Parsing.fsi | 2 +- src/fsharp/fsi/fsi.fsproj | 2 +- tests/fsharp/Compiler/Stress/LargeExprTests.fs | 3 +++ tests/service/data/TestTP/TestTP.fsproj | 2 +- .../DummyProviderForLanguageServiceTesting.fsproj | 2 +- 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index ff7a1b670da..080077bc21e 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -15,7 +15,8 @@ $(ArtifactsDir)\Bootstrap 4.4.0 1182;0025;$(WarningsAsErrors) - + $(OtherFlags) --nowarn:3384 + diff --git a/src/buildtools/fslex/Parsing.fsi b/src/buildtools/fslex/Parsing.fsi index 2fef45975a8..f4d12606462 100644 --- a/src/buildtools/fslex/Parsing.fsi +++ b/src/buildtools/fslex/Parsing.fsi @@ -100,7 +100,7 @@ type Tables<'tok> = /// Interpret the parser table taking input from the given lexer, using the given lex buffer, and the given start state. /// Returns an object indicating the final synthesized value for the parse. - member Interpret : lexer:(LexBuffer<'char> -> 'tok) * lexbuf:LexBuffer<'char> * startState:int -> obj + member Interpret : lexer:(LexBuffer<'char> -> 'tok) * lexbuf:LexBuffer<'char> * initialState:int -> obj #if INTERNALIZED_FSLEXYACC_RUNTIME exception internal Accept of obj diff --git a/src/fsharp/fsi/fsi.fsproj b/src/fsharp/fsi/fsi.fsproj index 900a5fb4e30..b390ca63921 100644 --- a/src/fsharp/fsi/fsi.fsproj +++ b/src/fsharp/fsi/fsi.fsproj @@ -9,7 +9,7 @@ netcoreapp3.1 $(NoWarn);45;55;62;75;1204 true - --warnon:1182 --maxerrors:20 --extraoptimizationloops:1 + $(OtherFlags) --warnon:1182 --maxerrors:20 --extraoptimizationloops:1 fsi.res true true diff --git a/tests/fsharp/Compiler/Stress/LargeExprTests.fs b/tests/fsharp/Compiler/Stress/LargeExprTests.fs index 9be3574c000..5eaf926ef6d 100644 --- a/tests/fsharp/Compiler/Stress/LargeExprTests.fs +++ b/tests/fsharp/Compiler/Stress/LargeExprTests.fs @@ -9,6 +9,9 @@ open FSharp.Test.Utilities module LargeExprTests = [] +#if NETCOREAPP + [] +#endif let LargeRecordDoesNotStackOverflow() = CompilerAssert.CompileExe """ diff --git a/tests/service/data/TestTP/TestTP.fsproj b/tests/service/data/TestTP/TestTP.fsproj index 4343a1d8a4a..442fc909f7a 100644 --- a/tests/service/data/TestTP/TestTP.fsproj +++ b/tests/service/data/TestTP/TestTP.fsproj @@ -5,7 +5,7 @@ net472 true nunit - --nowarn:3390 --nowarn:3218 + $(OtherFlags) --nowarn:3390 --nowarn:3218 diff --git a/vsintegration/tests/MockTypeProviders/DummyProviderForLanguageServiceTesting/DummyProviderForLanguageServiceTesting.fsproj b/vsintegration/tests/MockTypeProviders/DummyProviderForLanguageServiceTesting/DummyProviderForLanguageServiceTesting.fsproj index 5bdfd8af56f..84b50e8a6a7 100644 --- a/vsintegration/tests/MockTypeProviders/DummyProviderForLanguageServiceTesting/DummyProviderForLanguageServiceTesting.fsproj +++ b/vsintegration/tests/MockTypeProviders/DummyProviderForLanguageServiceTesting/DummyProviderForLanguageServiceTesting.fsproj @@ -5,7 +5,7 @@ net472 true - --nowarn:3390 --nowarn:3218 + $(OtherFlags) --nowarn:3390 --nowarn:3218 From 3119ef91d5eb1b9a8b2f8d01044abe83eb807702 Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Mon, 1 Feb 2021 20:11:35 -0800 Subject: [PATCH 14/17] add .NET 3.1 SDK to CI machines (#10986) --- azure-pipelines.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 37979ac6b9c..22cc0b32eff 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -56,6 +56,8 @@ variables: value: .NETCore - name: VisualStudioDropName value: Products/$(System.TeamProject)/$(Build.Repository.Name)/$(Build.SourceBranchName)/$(Build.BuildNumber) + - name: LegacyDotNetSdkVersion + value: 3.1.405 - name: DotNetSdkVersion value: '5.0.100' - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: @@ -103,6 +105,12 @@ stages: steps: - checkout: self clean: true + - task: UseDotNet@2 + displayName: Add legacy .NET SDK + inputs: + packageType: sdk + version: $(LegacyDotNetSdkVersion) + installationPath: $(Agent.ToolsDirectory)/dotnet - script: eng\CIBuild.cmd -configuration $(_BuildConfig) -prepareMachine @@ -211,6 +219,12 @@ stages: steps: - checkout: self clean: true + - task: UseDotNet@2 + displayName: Add legacy .NET SDK + inputs: + packageType: sdk + version: $(LegacyDotNetSdkVersion) + installationPath: $(Agent.ToolsDirectory)/dotnet - script: eng\CIBuild.cmd -configuration $(_configuration) -$(_testKind) displayName: Build / Test - task: PublishTestResults@2 @@ -261,6 +275,12 @@ stages: steps: - checkout: self clean: true + - task: UseDotNet@2 + displayName: Add legacy .NET SDK + inputs: + packageType: sdk + version: $(LegacyDotNetSdkVersion) + installationPath: $(Agent.ToolsDirectory)/dotnet - script: ./eng/cibuild.sh --configuration $(_BuildConfig) --testcoreclr displayName: Build / Test - task: PublishTestResults@2 @@ -293,6 +313,12 @@ stages: steps: - checkout: self clean: true + - task: UseDotNet@2 + displayName: Add legacy .NET SDK + inputs: + packageType: sdk + version: $(LegacyDotNetSdkVersion) + installationPath: $(Agent.ToolsDirectory)/dotnet - script: ./eng/cibuild.sh --configuration $(_BuildConfig) --testcoreclr displayName: Build / Test - task: PublishTestResults@2 From bc1375d321d5cb645f72a300b14f00370c3bfbb7 Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Tue, 2 Feb 2021 17:17:54 +0100 Subject: [PATCH 15/17] Verbatim string ast (#10769) --- src/fsharp/CheckComputationExpressions.fs | 2 +- src/fsharp/CheckExpressions.fs | 14 +- src/fsharp/SyntaxTree.fs | 20 ++- src/fsharp/SyntaxTreeOps.fs | 2 +- src/fsharp/lex.fsl | 51 ++++--- src/fsharp/lexhelp.fs | 44 ++++-- src/fsharp/lexhelp.fsi | 9 +- src/fsharp/pars.fsy | 48 ++++--- src/fsharp/service/ServiceLexing.fs | 15 ++- src/fsharp/service/ServiceParseTreeWalk.fs | 2 +- src/fsharp/service/ServiceUntypedParse.fs | 2 +- .../SurfaceArea.netstandard.fs | 63 ++++++++- tests/service/Symbols.fs | 125 +++++++++++++++++- 13 files changed, 324 insertions(+), 73 deletions(-) diff --git a/src/fsharp/CheckComputationExpressions.fs b/src/fsharp/CheckComputationExpressions.fs index a8bd308b7ed..31ca729a399 100644 --- a/src/fsharp/CheckComputationExpressions.fs +++ b/src/fsharp/CheckComputationExpressions.fs @@ -1917,7 +1917,7 @@ let TcArrayOrListSequenceExpression (cenv: cenv) env overallTy tpenv (isArray, c if nelems > 0 && List.forall (function SynExpr.Const (SynConst.UInt16 _, _) -> true | _ -> false) elems then SynExpr.Const (SynConst.UInt16s (Array.ofList (List.map (function SynExpr.Const (SynConst.UInt16 x, _) -> x | _ -> failwith "unreachable") elems)), m) elif nelems > 0 && List.forall (function SynExpr.Const (SynConst.Byte _, _) -> true | _ -> false) elems - then SynExpr.Const (SynConst.Bytes (Array.ofList (List.map (function SynExpr.Const (SynConst.Byte x, _) -> x | _ -> failwith "unreachable") elems), m), m) + then SynExpr.Const (SynConst.Bytes (Array.ofList (List.map (function SynExpr.Const (SynConst.Byte x, _) -> x | _ -> failwith "unreachable") elems), SynByteStringKind.Regular, m), m) else SynExpr.ArrayOrList (isArray, elems, m) else if elems.Length > 500 then diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index b30ae9cd30c..8be4fa32aa5 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -810,7 +810,7 @@ let TcConst cenv ty m env c = | SynConst.Measure(SynConst.UInt64 i, _) when expandedMeasurablesEnabled -> unifyMeasureArg (i=0UL) cenv.g.puint64_tcr c; Const.UInt64 i | SynConst.Measure(SynConst.UIntPtr i, _) when expandedMeasurablesEnabled -> unifyMeasureArg (i=0UL) cenv.g.punativeint_tcr c; Const.UIntPtr i | SynConst.Char c -> unif cenv.g.char_ty; Const.Char c - | SynConst.String (s, _) -> unif cenv.g.string_ty; Const.String s + | SynConst.String (s, _, _) -> unif cenv.g.string_ty; Const.String s | SynConst.UserNum _ -> error (InternalError(FSComp.SR.tcUnexpectedBigRationalConstant(), m)) | SynConst.Measure _ -> error (Error(FSComp.SR.tcInvalidTypeForUnitsOfMeasure(), m)) | SynConst.UInt16s _ -> error (InternalError(FSComp.SR.tcUnexpectedConstUint16Array(), m)) @@ -4414,7 +4414,7 @@ and TcStaticConstantParameter cenv (env: TcEnv) tpenv kind (StripParenTypes v) i | SynConst.Single n when typeEquiv g g.float32_ty kind -> record(g.float32_ty); box (n: single) | SynConst.Double n when typeEquiv g g.float_ty kind -> record(g.float_ty); box (n: double) | SynConst.Char n when typeEquiv g g.char_ty kind -> record(g.char_ty); box (n: char) - | SynConst.String (s, _) when s <> null && typeEquiv g g.string_ty kind -> record(g.string_ty); box (s: string) + | SynConst.String (s, _, _) when s <> null && typeEquiv g g.string_ty kind -> record(g.string_ty); box (s: string) | SynConst.Bool b when typeEquiv g g.bool_ty kind -> record(g.bool_ty); box (b: bool) | _ -> fail() v, tpenv @@ -4794,7 +4794,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p match pat with | SynPat.Const (c, m) -> match c with - | SynConst.Bytes (bytes, m) -> + | SynConst.Bytes (bytes, _, m) -> UnifyTypes cenv env m ty (mkByteArrayTy cenv.g) TcPat warnOnUpper cenv env None vFlags (tpenv, names, takenNames) ty (SynPat.ArrayOrList (true, [ for b in bytes -> SynPat.Const(SynConst.Byte b, m) ], m)) @@ -5425,11 +5425,11 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = | SynExpr.DotIndexedGet _ | SynExpr.DotIndexedSet _ | SynExpr.TypeApp _ | SynExpr.Ident _ | SynExpr.LongIdent _ | SynExpr.App _ | SynExpr.DotGet _ -> error(Error(FSComp.SR.tcExprUndelayed(), synExpr.Range)) - | SynExpr.Const (SynConst.String (s, m), _) -> + | SynExpr.Const (SynConst.String (s, _, m), _) -> CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.AccessRights) TcConstStringExpr cenv overallTy env m tpenv s - | SynExpr.InterpolatedString (parts, m) -> + | SynExpr.InterpolatedString (parts, _, m) -> checkLanguageFeatureError cenv.g.langVersion LanguageFeature.StringInterpolation m CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.AccessRights) @@ -6784,7 +6784,7 @@ and TcConstExpr cenv overallTy env m tpenv c = match c with // NOTE: these aren't "really" constants - | SynConst.Bytes (bytes, m) -> + | SynConst.Bytes (bytes, _, m) -> UnifyTypes cenv env m overallTy (mkByteArrayTy cenv.g) Expr.Op (TOp.Bytes bytes, [], [], m), tpenv @@ -6810,7 +6810,7 @@ and TcConstExpr cenv overallTy env m tpenv c = let i64 = int64 s SynExpr.App (ExprAtomicFlag.Atomic, false, mkSynLidGet m [modName] "FromInt64", SynExpr.Const (SynConst.Int64 i64, m), m) with _ -> - SynExpr.App (ExprAtomicFlag.Atomic, false, mkSynLidGet m [modName] "FromString", SynExpr.Const (SynConst.String (s, m), m), m) + SynExpr.App (ExprAtomicFlag.Atomic, false, mkSynLidGet m [modName] "FromString", SynExpr.Const (SynConst.String (s, SynStringKind.Regular, m), m), m) if suffix <> "I" then expr diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index b1d210ebabb..cd3ce7a1a3b 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -81,6 +81,19 @@ type SynTypar = | Typar(id, _, _) -> id.idRange +/// Indicate if the string had a special format +[] +type SynStringKind = + | Regular + | Verbatim + | TripleQuote + +/// Indicate if the byte string had a special format +[] +type SynByteStringKind = + | Regular + | Verbatim + /// The unchecked abstract syntax tree of constants in F# types and expressions. [] type SynConst = @@ -139,13 +152,13 @@ type SynConst = | UserNum of value: string * suffix: string /// F# syntax: verbatim or regular string, e.g. "abc" - | String of text: string * range: range + | String of text: string * synStringKind :SynStringKind * range: range /// F# syntax: verbatim or regular byte string, e.g. "abc"B. /// /// Also used internally in the typechecker once an array of unit16 constants /// is detected, to allow more efficient processing of large arrays of uint16 constants. - | Bytes of bytes: byte[] * range: range + | Bytes of bytes: byte[] * synByteStringKind: SynByteStringKind * range: range /// Used internally in the typechecker once an array of unit16 constants /// is detected, to allow more efficient processing of large arrays of uint16 constants. @@ -157,7 +170,7 @@ type SynConst = /// Gets the syntax range of this construct member c.Range dflt = match c with - | SynConst.String (_, m0) | SynConst.Bytes (_, m0) -> m0 + | SynConst.String (_, _, m0) | SynConst.Bytes (_, _, m0) -> m0 | _ -> dflt /// Represents an unchecked syntax tree of F# unit of measure annotations. @@ -1015,6 +1028,7 @@ type SynExpr = /// Note the string ranges include the quotes, verbatim markers, dollar sign and braces | InterpolatedString of contents: SynInterpolatedStringPart list * + synStringKind :SynStringKind * range: range /// Gets the syntax range of this construct diff --git a/src/fsharp/SyntaxTreeOps.fs b/src/fsharp/SyntaxTreeOps.fs index 3fd1ce32224..c3287c241fd 100644 --- a/src/fsharp/SyntaxTreeOps.fs +++ b/src/fsharp/SyntaxTreeOps.fs @@ -735,7 +735,7 @@ let rec synExprContainsError inpExpr = | SynExpr.LetOrUseBang (rhs=e1;body=e2;andBangs=es) -> walkExpr e1 || walkExprs [ for (_,_,_,_,e,_) in es do yield e ] || walkExpr e2 - | SynExpr.InterpolatedString (parts, _m) -> + | SynExpr.InterpolatedString (parts, _, _m) -> walkExprs (parts |> List.choose (function | SynInterpolatedStringPart.String _ -> None diff --git a/src/fsharp/lex.fsl b/src/fsharp/lex.fsl index 8317f4f5a92..e48cb044552 100644 --- a/src/fsharp/lex.fsl +++ b/src/fsharp/lex.fsl @@ -136,25 +136,35 @@ let startString args (lexbuf: UnicodeLexing.Lexbuf) = let m = lexbuf.LexemeRange let startp = lexbuf.StartPos let fin = - LexerStringFinisher (fun buf kind isPart cont -> + LexerStringFinisher (fun buf kind context cont -> // Adjust the start-of-token mark back to the true start of the token lexbuf.StartPos <- startp - if kind.IsByteString then + let isPart = context.HasFlag(LexerStringFinisherContext.InterpolatedPart) + let isVerbatim = context.HasFlag(LexerStringFinisherContext.Verbatim) + let isTripleQuote = context.HasFlag(LexerStringFinisherContext.TripleQuote) + + if kind.IsByteString then + let synByteStringKind = if isVerbatim then SynByteStringKind.Verbatim else SynByteStringKind.Regular if kind.IsInterpolated then fail args lexbuf (FSComp.SR.lexByteStringMayNotBeInterpolated()) () - BYTEARRAY (Lexhelp.stringBufferAsBytes buf, cont) + BYTEARRAY (Lexhelp.stringBufferAsBytes buf, synByteStringKind, cont) elif Lexhelp.stringBufferIsBytes buf then - BYTEARRAY (Lexhelp.stringBufferAsBytes buf, cont) + BYTEARRAY (Lexhelp.stringBufferAsBytes buf, synByteStringKind, cont) else fail args lexbuf (FSComp.SR.lexByteArrayCannotEncode()) () - BYTEARRAY (Lexhelp.stringBufferAsBytes buf, cont) + BYTEARRAY (Lexhelp.stringBufferAsBytes buf, synByteStringKind, cont) elif kind.IsInterpolated then let s = Lexhelp.stringBufferAsString buf - if kind.IsInterpolatedFirst then + if kind.IsInterpolatedFirst then + let synStringKind = + if isTripleQuote then + SynStringKind.TripleQuote + else + SynStringKind.Regular if isPart then - INTERP_STRING_BEGIN_PART (s, cont) + INTERP_STRING_BEGIN_PART (s, synStringKind, cont) else - INTERP_STRING_BEGIN_END (s, cont) + INTERP_STRING_BEGIN_END (s, synStringKind, cont) else if isPart then INTERP_STRING_PART (s, cont) @@ -162,7 +172,14 @@ let startString args (lexbuf: UnicodeLexing.Lexbuf) = INTERP_STRING_END (s, cont) else let s = Lexhelp.stringBufferAsString buf - STRING (s, cont)) + let synStringKind = + if isVerbatim then + SynStringKind.Verbatim + elif isTripleQuote then + SynStringKind.TripleQuote + else + SynStringKind.Regular + STRING (s, synStringKind, cont)) buf,fin,m @@ -1124,13 +1141,13 @@ and singleQuoteString sargs skip = parse | '"' { let (buf, fin, _m, kind, args) = sargs let cont = LexCont.Token(args.ifdefStack, args.stringNest) - fin.Finish buf kind false cont + fin.Finish buf kind (enum(0)) cont } | '"''B' { let (buf, fin, _m, kind, args) = sargs let cont = LexCont.Token(args.ifdefStack, args.stringNest) - fin.Finish buf { kind with IsByteString = true } false cont + fin.Finish buf { kind with IsByteString = true } (enum(0)) cont } | ("{{" | "}}") @@ -1147,7 +1164,7 @@ and singleQuoteString sargs skip = parse let m2 = lexbuf.LexemeRange args.stringNest <- (1, LexerStringStyle.SingleQuote, m2) :: args.stringNest let cont = LexCont.Token(args.ifdefStack, args.stringNest) - fin.Finish buf kind true cont + fin.Finish buf kind LexerStringFinisherContext.InterpolatedPart cont else addUnicodeString buf (lexeme lexbuf) if not skip then STRING_TEXT (LexCont.String(args.ifdefStack, args.stringNest, LexerStringStyle.SingleQuote, kind, m)) @@ -1214,13 +1231,13 @@ and verbatimString sargs skip = parse | '"' { let (buf, fin, _m, kind, args) = sargs let cont = LexCont.Token(args.ifdefStack, args.stringNest) - fin.Finish buf kind false cont + fin.Finish buf kind LexerStringFinisherContext.Verbatim cont } | '"''B' { let (buf, fin, _m, kind, args) = sargs let cont = LexCont.Token(args.ifdefStack, args.stringNest) - fin.Finish buf { kind with IsByteString = true } false cont + fin.Finish buf { kind with IsByteString = true } LexerStringFinisherContext.Verbatim cont } | newline @@ -1244,7 +1261,7 @@ and verbatimString sargs skip = parse let m2 = lexbuf.LexemeRange args.stringNest <- (1, LexerStringStyle.Verbatim, m2) :: args.stringNest let cont = LexCont.Token(args.ifdefStack, args.stringNest) - fin.Finish buf kind true cont + fin.Finish buf kind (enum(3)) cont else addUnicodeString buf (lexeme lexbuf) if not skip then STRING_TEXT (LexCont.String(args.ifdefStack, args.stringNest, LexerStringStyle.Verbatim, kind, m)) @@ -1297,7 +1314,7 @@ and tripleQuoteString sargs skip = parse | '"' '"' '"' { let (buf, fin, _m, kind, args) = sargs let cont = LexCont.Token(args.ifdefStack, args.stringNest) - fin.Finish buf kind false cont } + fin.Finish buf kind (enum(4)) cont } | newline { let (buf, _fin, m, kind, args) = sargs @@ -1340,7 +1357,7 @@ and tripleQuoteString sargs skip = parse let m2 = lexbuf.LexemeRange args.stringNest <- (1, LexerStringStyle.TripleQuote, m2) :: args.stringNest let cont = LexCont.Token(args.ifdefStack, args.stringNest) - fin.Finish buf kind true cont + fin.Finish buf kind (enum(5)) cont else addUnicodeString buf (lexeme lexbuf) if not skip then STRING_TEXT (LexCont.String(args.ifdefStack, args.stringNest, LexerStringStyle.TripleQuote, kind, m)) diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index 767dcae116f..fe86184e0eb 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -18,6 +18,7 @@ open FSharp.Compiler.SourceCodeServices open FSharp.Compiler.SourceCodeServices.PrettyNaming open FSharp.Compiler.Text open FSharp.Compiler.Text.Range +open FSharp.Compiler.SyntaxTree /// The "mock" filename used by fsi.exe when reading from stdin. /// Has special treatment by the lexer, i.e. __SOURCE_DIRECTORY__ becomes GetCurrentDirectory() @@ -119,31 +120,54 @@ let stringBufferAsBytes (buf: ByteBuffer) = let bytes = buf.Close() Array.init (bytes.Length / 2) (fun i -> bytes.[i*2]) +[] +type LexerStringFinisherContext = + | InterpolatedPart = 1 + | Verbatim = 2 + | TripleQuote = 4 + type LexerStringFinisher = - | LexerStringFinisher of (ByteBuffer -> LexerStringKind -> bool -> LexerContinuation -> token) + | LexerStringFinisher of (ByteBuffer -> LexerStringKind -> LexerStringFinisherContext -> LexerContinuation -> token) - member fin.Finish (buf: ByteBuffer) kind isInterpolatedStringPart cont = + member fin.Finish (buf: ByteBuffer) kind context cont = let (LexerStringFinisher f) = fin - f buf kind isInterpolatedStringPart cont + f buf kind context cont static member Default = - LexerStringFinisher (fun buf kind isPart cont -> + LexerStringFinisher (fun buf kind context cont -> + let isPart = context.HasFlag(LexerStringFinisherContext.InterpolatedPart) + let isVerbatim = context.HasFlag(LexerStringFinisherContext.Verbatim) + let isTripleQuote = context.HasFlag(LexerStringFinisherContext.TripleQuote) + if kind.IsInterpolated then let s = stringBufferAsString buf - if kind.IsInterpolatedFirst then + if kind.IsInterpolatedFirst then + let synStringKind = + if isTripleQuote then + SynStringKind.TripleQuote + else + SynStringKind.Regular if isPart then - INTERP_STRING_BEGIN_PART (s, cont) + INTERP_STRING_BEGIN_PART (s, synStringKind, cont) else - INTERP_STRING_BEGIN_END (s, cont) + INTERP_STRING_BEGIN_END (s, synStringKind, cont) else if isPart then INTERP_STRING_PART (s, cont) else INTERP_STRING_END (s, cont) - elif kind.IsByteString then - BYTEARRAY (stringBufferAsBytes buf, cont) + elif kind.IsByteString then + let synByteStringKind = if isVerbatim then SynByteStringKind.Verbatim else SynByteStringKind.Regular + BYTEARRAY (stringBufferAsBytes buf, synByteStringKind, cont) else - STRING (stringBufferAsString buf, cont) + let synStringKind = + if isVerbatim then + SynStringKind.Verbatim + elif isTripleQuote then + SynStringKind.TripleQuote + else + SynStringKind.Regular + STRING (stringBufferAsString buf, synStringKind, cont) ) let addUnicodeString (buf: ByteBuffer) (x:string) = diff --git a/src/fsharp/lexhelp.fsi b/src/fsharp/lexhelp.fsi index f7cf0b25d6d..e3f1053fb24 100644 --- a/src/fsharp/lexhelp.fsi +++ b/src/fsharp/lexhelp.fsi @@ -54,10 +54,15 @@ val reusingLexbufForParsing: UnicodeLexing.Lexbuf -> (unit -> 'a) -> 'a val usingLexbufForParsing: UnicodeLexing.Lexbuf * string -> (UnicodeLexing.Lexbuf -> 'a) -> 'a +type LexerStringFinisherContext = + | InterpolatedPart = 1 + | Verbatim = 2 + | TripleQuote = 4 + type LexerStringFinisher = - | LexerStringFinisher of (ByteBuffer -> LexerStringKind -> bool -> LexerContinuation -> token) + | LexerStringFinisher of (ByteBuffer -> LexerStringKind -> LexerStringFinisherContext -> LexerContinuation -> token) - member Finish: buf: ByteBuffer -> kind: LexerStringKind -> isInterpolatedStringPart: bool -> cont: LexerContinuation -> token + member Finish: buf: ByteBuffer -> kind: LexerStringKind -> context: LexerStringFinisherContext -> cont: LexerContinuation -> token static member Default: LexerStringFinisher diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index daac933cc9a..507ef9ae5ac 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -195,10 +195,10 @@ let rangeOfLongIdent(lid:LongIdent) = %} // Producing these changes the lex state, e.g. string --> token, or nesting level of braces in interpolated strings -%token BYTEARRAY -%token STRING -%token INTERP_STRING_BEGIN_END -%token INTERP_STRING_BEGIN_PART +%token BYTEARRAY +%token STRING +%token INTERP_STRING_BEGIN_END +%token INTERP_STRING_BEGIN_PART %token INTERP_STRING_PART %token INTERP_STRING_END %token LBRACE RBRACE @@ -647,7 +647,8 @@ hashDirectiveArgs: /* One argument to a #directive */ hashDirectiveArg: | stringOrKeywordString - { $1 } + { let s, _ = $1 + s } /*--------------------------------------------------------------------------*/ @@ -2239,8 +2240,9 @@ braceBarFieldDeclListCore: inlineAssemblyTyconRepr: | HASH stringOrKeywordString HASH { libraryOnlyError (lhs parseState) - let lhsm = lhs parseState - let ilType = ParseAssemblyCodeType $2 parseState.LexBuffer.SupportsFeature (rhs parseState 2) + let lhsm = lhs parseState + let s, _ = $2 + let ilType = ParseAssemblyCodeType s parseState.LexBuffer.SupportsFeature (rhs parseState 2) SynTypeDefnSimpleRepr.LibraryOnlyILAssembly (box ilType, lhsm) } classOrInterfaceOrStruct: @@ -2665,7 +2667,7 @@ cPrototype: let rhsExpr = SynExpr.App (ExprAtomicFlag.NonAtomic, false, SynExpr.Ident (ident("failwith", rhs parseState 6)), - SynExpr.Const (SynConst.String("extern was not given a DllImport attribute", rhs parseState 8), rhs parseState 8), + SynExpr.Const (SynConst.String("extern was not given a DllImport attribute", SynStringKind.Regular, rhs parseState 8), rhs parseState 8), mRhs) (fun attrs _ -> let bindingId = SynPat.LongIdent (LongIdentWithDots([nm], []), None, Some noInferredTypars, SynArgPats.Pats [SynPat.Tuple(false, args, argsm)], vis, nmm) @@ -2909,10 +2911,12 @@ rawConstant: { SynConst.UserNum $1 } | stringOrKeywordString - { SynConst.String ($1, lhs parseState) } + { let s, synStringKind = $1 + SynConst.String (s, synStringKind, lhs parseState) } | BYTEARRAY - { SynConst.Bytes (fst $1, lhs parseState) } + { let (v, synByteStringKind, _) = $1 + SynConst.Bytes (v, synByteStringKind, lhs parseState) } rationalConstant: | INT32 INFIX_STAR_DIV_MOD_OP INT32 @@ -3851,7 +3855,7 @@ declExpr: dynamicArg: | IDENT - { let con = SynConst.String ($1, rhs parseState 1) + { let con = SynConst.String ($1, SynStringKind.Regular, rhs parseState 1) let arg2 = SynExpr.Const (con, con.Range (rhs parseState 1)) arg2 } @@ -4246,7 +4250,8 @@ atomicExprAfterType: { $1 } | interpolatedString - { SynExpr.InterpolatedString($1, rhs parseState 1) } + { let parts, synStringKind = $1 + SynExpr.InterpolatedString(parts, synStringKind, rhs parseState 1) } | NULL { SynExpr.Null (lhs parseState) } @@ -4491,7 +4496,7 @@ forLoopDirection: inlineAssemblyExpr: | HASH stringOrKeywordString opt_inlineAssemblyTypeArg optCurriedArgExprs optInlineAssemblyReturnTypes HASH { libraryOnlyWarning (lhs parseState) - let s, sm = $2, rhs parseState 2 + let (s, _), sm = $2, rhs parseState 2 (fun m -> let ilInstrs = ParseAssemblyCodeInstructions s parseState.LexBuffer.SupportsFeature sm SynExpr.LibraryOnlyILAssembly (box ilInstrs, $3, List.rev $4, $5, m)) } @@ -5072,7 +5077,7 @@ atomType: | NULL { let m = rhs parseState 1 - SynType.StaticConstant(SynConst.String (null, m), m) } + SynType.StaticConstant(SynConst.String (null, SynStringKind.Regular, m), m) } | CONST atomicExpr { let e, _ = $2 @@ -5528,8 +5533,10 @@ colonOrEquals: /* A literal string or a string from a keyword like __SOURCE_FILE__ */ stringOrKeywordString: - | STRING { fst $1 } - | KEYWORD_STRING { $1 } + | STRING + { let (s, synStringKind, _) = $1 + s, synStringKind } + | KEYWORD_STRING { $1, SynStringKind.Regular } interpolatedStringFill: | declExpr @@ -5557,17 +5564,20 @@ interpolatedStringParts: /* INTERP_STRING_BEGIN_PART int32 INTERP_STRING_PART int32 INTERP_STRING_END */ interpolatedString: | INTERP_STRING_BEGIN_PART interpolatedStringFill interpolatedStringParts - { SynInterpolatedStringPart.String (fst $1, rhs parseState 1) :: SynInterpolatedStringPart.FillExpr $2 :: $3 } + { let s, synStringKind, _ = $1 + SynInterpolatedStringPart.String (s, rhs parseState 1) :: SynInterpolatedStringPart.FillExpr $2 :: $3, synStringKind } | INTERP_STRING_BEGIN_END - { [ SynInterpolatedStringPart.String (fst $1, rhs parseState 1) ] } + { let s, synStringKind, _ = $1 + [ SynInterpolatedStringPart.String (s, rhs parseState 1) ], synStringKind } | INTERP_STRING_BEGIN_PART interpolatedStringParts { + let s, synStringKind, _ = $1 let rbrace = parseState.InputEndPosition 1 let lbrace = parseState.InputStartPosition 2 reportParseErrorAt (mkSynRange rbrace lbrace) (FSComp.SR.parsEmptyFillInInterpolatedString()) - SynInterpolatedStringPart.String (fst $1, rhs parseState 1) :: $2 } + SynInterpolatedStringPart.String (s, rhs parseState 1) :: $2, synStringKind } opt_HIGH_PRECEDENCE_APP: | HIGH_PRECEDENCE_BRACK_APP { } diff --git a/src/fsharp/service/ServiceLexing.fs b/src/fsharp/service/ServiceLexing.fs index 2e8931a697e..6747a94ee82 100755 --- a/src/fsharp/service/ServiceLexing.fs +++ b/src/fsharp/service/ServiceLexing.fs @@ -24,6 +24,7 @@ open FSharp.Compiler.SourceCodeServices open FSharp.Compiler.Text open FSharp.Compiler.Text.Pos open FSharp.Compiler.Text.Range +open FSharp.Compiler.SyntaxTree open Internal.Utilities @@ -34,12 +35,12 @@ type Positions = Position * Position module FSharpTokenTag = let Identifier = tagOfToken (IDENT "a") - let String = tagOfToken (STRING ("a", LexCont.Default)) + let String = tagOfToken (STRING ("a", SynStringKind.Regular, LexCont.Default)) let IDENT = tagOfToken (IDENT "a") let STRING = String - let INTERP_STRING_BEGIN_END = tagOfToken (INTERP_STRING_BEGIN_END ("a", LexCont.Default)) - let INTERP_STRING_BEGIN_PART = tagOfToken (INTERP_STRING_BEGIN_PART ("a", LexCont.Default)) + let INTERP_STRING_BEGIN_END = tagOfToken (INTERP_STRING_BEGIN_END ("a", SynStringKind.Regular, LexCont.Default)) + let INTERP_STRING_BEGIN_PART = tagOfToken (INTERP_STRING_BEGIN_PART ("a", SynStringKind.Regular, LexCont.Default)) let INTERP_STRING_PART = tagOfToken (INTERP_STRING_PART ("a", LexCont.Default)) let INTERP_STRING_END = tagOfToken (INTERP_STRING_END ("a", LexCont.Default)) let LPAREN = tagOfToken LPAREN @@ -379,14 +380,14 @@ module internal LexerStateEncoding = | LINE_COMMENT cont | STRING_TEXT cont | EOF cont - | INTERP_STRING_BEGIN_PART (_, cont) + | INTERP_STRING_BEGIN_PART (_, _, cont) | INTERP_STRING_PART (_, cont) - | INTERP_STRING_BEGIN_END (_, cont) + | INTERP_STRING_BEGIN_END (_, _, cont) | INTERP_STRING_END (_, cont) | LBRACE cont | RBRACE cont - | BYTEARRAY (_, cont) - | STRING (_, cont) -> cont + | BYTEARRAY (_, _, cont) + | STRING (_, _, cont) -> cont | _ -> prevLexcont // Note that this will discard all lexcont state, including the ifdefStack. diff --git a/src/fsharp/service/ServiceParseTreeWalk.fs b/src/fsharp/service/ServiceParseTreeWalk.fs index 086a2998923..544c1f859a9 100755 --- a/src/fsharp/service/ServiceParseTreeWalk.fs +++ b/src/fsharp/service/ServiceParseTreeWalk.fs @@ -214,7 +214,7 @@ module public AstTraversal = | SynExpr.Const (_synConst, _range) -> None - | SynExpr.InterpolatedString (parts, _) -> + | SynExpr.InterpolatedString (parts, _, _) -> [ for part in parts do match part with | SynInterpolatedStringPart.String _ -> () diff --git a/src/fsharp/service/ServiceUntypedParse.fs b/src/fsharp/service/ServiceUntypedParse.fs index 9a11ab9eca3..555e868d963 100755 --- a/src/fsharp/service/ServiceUntypedParse.fs +++ b/src/fsharp/service/ServiceUntypedParse.fs @@ -464,7 +464,7 @@ type FSharpParseFileResults(errors: FSharpDiagnostic[], input: ParsedInput optio | SynExpr.Paren (e, _, _, _) -> yield! walkExpr false e - | SynExpr.InterpolatedString (parts, _) -> + | SynExpr.InterpolatedString (parts, _, _) -> yield! walkExprs [ for part in parts do match part with | SynInterpolatedStringPart.String _ -> () diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index fcb169c868a..45885957a63 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -6466,6 +6466,28 @@ FSharp.Compiler.SyntaxTree+SynBindingReturnInfo: SynBindingReturnInfo NewSynBind FSharp.Compiler.SyntaxTree+SynBindingReturnInfo: SynType get_typeName() FSharp.Compiler.SyntaxTree+SynBindingReturnInfo: SynType typeName FSharp.Compiler.SyntaxTree+SynBindingReturnInfo: System.String ToString() +FSharp.Compiler.SyntaxTree+SynByteStringKind+Tags: Int32 Regular +FSharp.Compiler.SyntaxTree+SynByteStringKind+Tags: Int32 Verbatim +FSharp.Compiler.SyntaxTree+SynByteStringKind: Boolean Equals(SynByteStringKind) +FSharp.Compiler.SyntaxTree+SynByteStringKind: Boolean Equals(System.Object) +FSharp.Compiler.SyntaxTree+SynByteStringKind: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.SyntaxTree+SynByteStringKind: Boolean IsRegular +FSharp.Compiler.SyntaxTree+SynByteStringKind: Boolean IsVerbatim +FSharp.Compiler.SyntaxTree+SynByteStringKind: Boolean get_IsRegular() +FSharp.Compiler.SyntaxTree+SynByteStringKind: Boolean get_IsVerbatim() +FSharp.Compiler.SyntaxTree+SynByteStringKind: FSharp.Compiler.SyntaxTree+SynByteStringKind+Tags +FSharp.Compiler.SyntaxTree+SynByteStringKind: Int32 CompareTo(SynByteStringKind) +FSharp.Compiler.SyntaxTree+SynByteStringKind: Int32 CompareTo(System.Object) +FSharp.Compiler.SyntaxTree+SynByteStringKind: Int32 CompareTo(System.Object, System.Collections.IComparer) +FSharp.Compiler.SyntaxTree+SynByteStringKind: Int32 GetHashCode() +FSharp.Compiler.SyntaxTree+SynByteStringKind: Int32 GetHashCode(System.Collections.IEqualityComparer) +FSharp.Compiler.SyntaxTree+SynByteStringKind: Int32 Tag +FSharp.Compiler.SyntaxTree+SynByteStringKind: Int32 get_Tag() +FSharp.Compiler.SyntaxTree+SynByteStringKind: SynByteStringKind Regular +FSharp.Compiler.SyntaxTree+SynByteStringKind: SynByteStringKind Verbatim +FSharp.Compiler.SyntaxTree+SynByteStringKind: SynByteStringKind get_Regular() +FSharp.Compiler.SyntaxTree+SynByteStringKind: SynByteStringKind get_Verbatim() +FSharp.Compiler.SyntaxTree+SynByteStringKind: System.String ToString() FSharp.Compiler.SyntaxTree+SynComponentInfo: Boolean get_preferPostfix() FSharp.Compiler.SyntaxTree+SynComponentInfo: Boolean preferPostfix FSharp.Compiler.SyntaxTree+SynComponentInfo: FSharp.Compiler.Text.Range Range @@ -6496,6 +6518,8 @@ FSharp.Compiler.SyntaxTree+SynConst+Bytes: Byte[] bytes FSharp.Compiler.SyntaxTree+SynConst+Bytes: Byte[] get_bytes() FSharp.Compiler.SyntaxTree+SynConst+Bytes: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.SyntaxTree+SynConst+Bytes: FSharp.Compiler.Text.Range range +FSharp.Compiler.SyntaxTree+SynConst+Bytes: SynByteStringKind get_synByteStringKind() +FSharp.Compiler.SyntaxTree+SynConst+Bytes: SynByteStringKind synByteStringKind FSharp.Compiler.SyntaxTree+SynConst+Char: Char Item FSharp.Compiler.SyntaxTree+SynConst+Char: Char get_Item() FSharp.Compiler.SyntaxTree+SynConst+Decimal: System.Decimal Item @@ -6520,6 +6544,8 @@ FSharp.Compiler.SyntaxTree+SynConst+Single: Single Item FSharp.Compiler.SyntaxTree+SynConst+Single: Single get_Item() FSharp.Compiler.SyntaxTree+SynConst+String: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.SyntaxTree+SynConst+String: FSharp.Compiler.Text.Range range +FSharp.Compiler.SyntaxTree+SynConst+String: SynStringKind get_synStringKind() +FSharp.Compiler.SyntaxTree+SynConst+String: SynStringKind synStringKind FSharp.Compiler.SyntaxTree+SynConst+String: System.String get_text() FSharp.Compiler.SyntaxTree+SynConst+String: System.String text FSharp.Compiler.SyntaxTree+SynConst+Tags: Int32 Bool @@ -6625,7 +6651,7 @@ FSharp.Compiler.SyntaxTree+SynConst: Int32 Tag FSharp.Compiler.SyntaxTree+SynConst: Int32 get_Tag() FSharp.Compiler.SyntaxTree+SynConst: SynConst NewBool(Boolean) FSharp.Compiler.SyntaxTree+SynConst: SynConst NewByte(Byte) -FSharp.Compiler.SyntaxTree+SynConst: SynConst NewBytes(Byte[], FSharp.Compiler.Text.Range) +FSharp.Compiler.SyntaxTree+SynConst: SynConst NewBytes(Byte[], SynByteStringKind, FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTree+SynConst: SynConst NewChar(Char) FSharp.Compiler.SyntaxTree+SynConst: SynConst NewDecimal(System.Decimal) FSharp.Compiler.SyntaxTree+SynConst: SynConst NewDouble(Double) @@ -6636,7 +6662,7 @@ FSharp.Compiler.SyntaxTree+SynConst: SynConst NewIntPtr(Int64) FSharp.Compiler.SyntaxTree+SynConst: SynConst NewMeasure(SynConst, SynMeasure) FSharp.Compiler.SyntaxTree+SynConst: SynConst NewSByte(SByte) FSharp.Compiler.SyntaxTree+SynConst: SynConst NewSingle(Single) -FSharp.Compiler.SyntaxTree+SynConst: SynConst NewString(System.String, FSharp.Compiler.Text.Range) +FSharp.Compiler.SyntaxTree+SynConst: SynConst NewString(System.String, SynStringKind, FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTree+SynConst: SynConst NewUInt16(UInt16) FSharp.Compiler.SyntaxTree+SynConst: SynConst NewUInt16s(UInt16[]) FSharp.Compiler.SyntaxTree+SynConst: SynConst NewUInt32(UInt32) @@ -6890,6 +6916,8 @@ FSharp.Compiler.SyntaxTree+SynExpr+InterpolatedString: FSharp.Compiler.Text.Rang FSharp.Compiler.SyntaxTree+SynExpr+InterpolatedString: FSharp.Compiler.Text.Range range FSharp.Compiler.SyntaxTree+SynExpr+InterpolatedString: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynInterpolatedStringPart] contents FSharp.Compiler.SyntaxTree+SynExpr+InterpolatedString: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynInterpolatedStringPart] get_contents() +FSharp.Compiler.SyntaxTree+SynExpr+InterpolatedString: SynStringKind get_synStringKind() +FSharp.Compiler.SyntaxTree+SynExpr+InterpolatedString: SynStringKind synStringKind FSharp.Compiler.SyntaxTree+SynExpr+JoinIn: FSharp.Compiler.Text.Range get_lhsRange() FSharp.Compiler.SyntaxTree+SynExpr+JoinIn: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.SyntaxTree+SynExpr+JoinIn: FSharp.Compiler.Text.Range lhsRange @@ -7480,7 +7508,7 @@ FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewIfThenElse(SynExpr, SynExpr, Micr FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewImplicitZero(FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewInferredDowncast(SynExpr, FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewInferredUpcast(SynExpr, FSharp.Compiler.Text.Range) -FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewInterpolatedString(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynInterpolatedStringPart], FSharp.Compiler.Text.Range) +FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewInterpolatedString(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynInterpolatedStringPart], SynStringKind, FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewJoinIn(SynExpr, FSharp.Compiler.Text.Range, SynExpr, FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewLambda(Boolean, Boolean, SynSimplePats, SynExpr, Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.SyntaxTree+SynPat],FSharp.Compiler.SyntaxTree+SynExpr]], FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTree+SynExpr: SynExpr NewLazy(SynExpr, FSharp.Compiler.Text.Range) @@ -8536,6 +8564,33 @@ FSharp.Compiler.SyntaxTree+SynStaticOptimizationConstraint: Int32 get_Tag() FSharp.Compiler.SyntaxTree+SynStaticOptimizationConstraint: SynStaticOptimizationConstraint NewWhenTyparIsStruct(SynTypar, FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTree+SynStaticOptimizationConstraint: SynStaticOptimizationConstraint NewWhenTyparTyconEqualsTycon(SynTypar, SynType, FSharp.Compiler.Text.Range) FSharp.Compiler.SyntaxTree+SynStaticOptimizationConstraint: System.String ToString() +FSharp.Compiler.SyntaxTree+SynStringKind+Tags: Int32 Regular +FSharp.Compiler.SyntaxTree+SynStringKind+Tags: Int32 TripleQuote +FSharp.Compiler.SyntaxTree+SynStringKind+Tags: Int32 Verbatim +FSharp.Compiler.SyntaxTree+SynStringKind: Boolean Equals(SynStringKind) +FSharp.Compiler.SyntaxTree+SynStringKind: Boolean Equals(System.Object) +FSharp.Compiler.SyntaxTree+SynStringKind: Boolean Equals(System.Object, System.Collections.IEqualityComparer) +FSharp.Compiler.SyntaxTree+SynStringKind: Boolean IsRegular +FSharp.Compiler.SyntaxTree+SynStringKind: Boolean IsTripleQuote +FSharp.Compiler.SyntaxTree+SynStringKind: Boolean IsVerbatim +FSharp.Compiler.SyntaxTree+SynStringKind: Boolean get_IsRegular() +FSharp.Compiler.SyntaxTree+SynStringKind: Boolean get_IsTripleQuote() +FSharp.Compiler.SyntaxTree+SynStringKind: Boolean get_IsVerbatim() +FSharp.Compiler.SyntaxTree+SynStringKind: FSharp.Compiler.SyntaxTree+SynStringKind+Tags +FSharp.Compiler.SyntaxTree+SynStringKind: Int32 CompareTo(SynStringKind) +FSharp.Compiler.SyntaxTree+SynStringKind: Int32 CompareTo(System.Object) +FSharp.Compiler.SyntaxTree+SynStringKind: Int32 CompareTo(System.Object, System.Collections.IComparer) +FSharp.Compiler.SyntaxTree+SynStringKind: Int32 GetHashCode() +FSharp.Compiler.SyntaxTree+SynStringKind: Int32 GetHashCode(System.Collections.IEqualityComparer) +FSharp.Compiler.SyntaxTree+SynStringKind: Int32 Tag +FSharp.Compiler.SyntaxTree+SynStringKind: Int32 get_Tag() +FSharp.Compiler.SyntaxTree+SynStringKind: SynStringKind Regular +FSharp.Compiler.SyntaxTree+SynStringKind: SynStringKind TripleQuote +FSharp.Compiler.SyntaxTree+SynStringKind: SynStringKind Verbatim +FSharp.Compiler.SyntaxTree+SynStringKind: SynStringKind get_Regular() +FSharp.Compiler.SyntaxTree+SynStringKind: SynStringKind get_TripleQuote() +FSharp.Compiler.SyntaxTree+SynStringKind: SynStringKind get_Verbatim() +FSharp.Compiler.SyntaxTree+SynStringKind: System.String ToString() FSharp.Compiler.SyntaxTree+SynTypar: Boolean get_isCompGen() FSharp.Compiler.SyntaxTree+SynTypar: Boolean isCompGen FSharp.Compiler.SyntaxTree+SynTypar: FSharp.Compiler.Text.Range Range @@ -9269,6 +9324,7 @@ FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynAttributeList FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynBinding FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynBindingKind FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynBindingReturnInfo +FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynByteStringKind FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynComponentInfo FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynConst FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynEnumCase @@ -9297,6 +9353,7 @@ FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynSimplePat FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynSimplePatAlternativeIdInfo FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynSimplePats FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynStaticOptimizationConstraint +FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynStringKind FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynTypar FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynTyparDecl FSharp.Compiler.SyntaxTree: FSharp.Compiler.SyntaxTree+SynType diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index 983d9555c8f..fe957fb4317 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -287,4 +287,127 @@ module SyntaxExpressions = assertRange 2 4 3 14 doRange assertRange 4 4 5 18 doBangRange | _ -> - failwith "Could not find SynExpr.Do" \ No newline at end of file + failwith "Could not find SynExpr.Do" + +module Strings = + let getBindingExpressionValue (parseResults: ParsedInput option) = + parseResults + |> Option.bind + (fun tree -> + match tree with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = modules)) -> + modules + |> List.tryPick + (function + | SynModuleOrNamespace (decls = decls) -> + decls + |> List.tryPick + (function + | SynModuleDecl.Let (bindings = bindings) -> + bindings + |> List.tryPick + (function + | SynBinding.Binding (_, + _, + _, + _, + _, + _, + _, + SynPat.Named _, + _, + e, + _, + _) -> Some e + | _ -> None) + | _ -> None)) + | _ -> None) + + let getBindingConstValue parseResults = + match getBindingExpressionValue parseResults with + | Some (SynExpr.Const(c,_)) -> Some c + | _ -> None + + [] + let ``SynConst.String with SynStringKind.Regular`` () = + let parseResults = + getParseResults + """ + let s = "yo" + """ + + match getBindingConstValue parseResults with + | Some (SynConst.String (_, kind, _)) -> kind |> should equal SynStringKind.Regular + | _ -> failwithf "Couldn't find const" + + [] + let ``SynConst.String with SynStringKind.Verbatim`` () = + let parseResults = + getParseResults + """ + let s = @"yo" + """ + + match getBindingConstValue parseResults with + | Some (SynConst.String (_, kind, _)) -> kind |> should equal SynStringKind.Verbatim + | _ -> failwithf "Couldn't find const" + + [] + let ``SynConst.String with SynStringKind.TripleQuote`` () = + let parseResults = + getParseResults + " + let s = \"\"\"yo\"\"\" + " + + match getBindingConstValue parseResults with + | Some (SynConst.String (_, kind, _)) -> kind |> should equal SynStringKind.TripleQuote + | _ -> failwithf "Couldn't find const" + + [] + let ``SynConst.Bytes with SynByteStringKind.Regular`` () = + let parseResults = + getParseResults + """ +let bytes = "yo"B + """ + + match getBindingConstValue parseResults with + | Some (SynConst.Bytes (_, kind, _)) -> kind |> should equal SynByteStringKind.Regular + | _ -> failwithf "Couldn't find const" + + [] + let ``SynConst.Bytes with SynByteStringKind.Verbatim`` () = + let parseResults = + getParseResults + """ +let bytes = @"yo"B + """ + + match getBindingConstValue parseResults with + | Some (SynConst.Bytes (_, kind, _)) -> kind |> should equal SynByteStringKind.Verbatim + | _ -> failwithf "Couldn't find const" + + [] + let ``SynExpr.InterpolatedString with SynStringKind.TripleQuote`` () = + let parseResults = + getParseResults + " + let s = $\"\"\"yo {42}\"\"\" + " + + match getBindingExpressionValue parseResults with + | Some (SynExpr.InterpolatedString(_, kind, _)) -> kind |> should equal SynStringKind.TripleQuote + | _ -> failwithf "Couldn't find const" + + [] + let ``SynExpr.InterpolatedString with SynStringKind.Regular`` () = + let parseResults = + getParseResults + """ + let s = $"yo {42}" + """ + + match getBindingExpressionValue parseResults with + | Some (SynExpr.InterpolatedString(_, kind, _)) -> kind |> should equal SynStringKind.Regular + | _ -> failwithf "Couldn't find const" \ No newline at end of file From 19abb080e3047e3f0ab8be4a0c2259163ebcb31b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 2 Feb 2021 09:41:03 -0800 Subject: [PATCH 16/17] [main] Update dependencies from dotnet/arcade (#10993) Microsoft.DotNet.Arcade.Sdk From Version 6.0.0-beta.21078.12 -> To Version 6.0.0-beta.21081.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/common/internal-feed-operations.ps1 | 2 -- eng/common/internal-feed-operations.sh | 2 -- global.json | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index f68c0362fd5..38beb569004 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 3233c41c837f72827efd8f827b538e047334847d + f6ed3308865528c56ed26b85004121fce56bf4f4 diff --git a/eng/common/internal-feed-operations.ps1 b/eng/common/internal-feed-operations.ps1 index b8f6529fdc8..418c09930cf 100644 --- a/eng/common/internal-feed-operations.ps1 +++ b/eng/common/internal-feed-operations.ps1 @@ -63,8 +63,6 @@ function SetupCredProvider { } if (($endpoints | Measure-Object).Count -gt 0) { - # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Endpoint code example with no real credentials.")] - # Create the JSON object. It should look like '{"endpointCredentials": [{"endpoint":"http://example.index.json", "username":"optional", "password":"accesstoken"}]}' $endpointCredentials = @{endpointCredentials=$endpoints} | ConvertTo-Json -Compress # Create the environment variables the AzDo way diff --git a/eng/common/internal-feed-operations.sh b/eng/common/internal-feed-operations.sh index a27410f6321..e2233e78122 100755 --- a/eng/common/internal-feed-operations.sh +++ b/eng/common/internal-feed-operations.sh @@ -62,8 +62,6 @@ function SetupCredProvider { endpoints+=']' if [ ${#endpoints} -gt 2 ]; then - # [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Endpoint code example with no real credentials.")] - # Create the JSON object. It should look like '{"endpointCredentials": [{"endpoint":"http://example.index.json", "username":"optional", "password":"accesstoken"}]}' local endpointCredentials="{\"endpointCredentials\": "$endpoints"}" echo "##vso[task.setvariable variable=VSS_NUGET_EXTERNAL_FEED_ENDPOINTS]$endpointCredentials" diff --git a/global.json b/global.json index 258015e7901..4d5a9337911 100644 --- a/global.json +++ b/global.json @@ -13,7 +13,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21078.12", + "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21081.1", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From cf8bf3dec1da42e2fee1ce8e01d8d0870acf1729 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Tue, 2 Feb 2021 10:16:50 -0800 Subject: [PATCH 17/17] net5.0 (#10992) --- src/fsharp/FxResolver.fs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FxResolver.fs b/src/fsharp/FxResolver.fs index 665f142b4d0..31e8307c2fb 100644 --- a/src/fsharp/FxResolver.fs +++ b/src/fsharp/FxResolver.fs @@ -295,7 +295,6 @@ type internal FxResolver(assumeDotNetFramework: bool option, projectDir: string, let startPos = let startPos = file.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) if startPos >= 0 then startPos + (pattern.Length) else startPos - let length = if startPos >= 0 then let ep = file.IndexOf("\"", startPos) @@ -305,16 +304,21 @@ type internal FxResolver(assumeDotNetFramework: bool option, projectDir: string, | -1, _ | _, -1 -> if isRunningOnCoreClr then - // Running on coreclr but no deps.json was deployed with the host so default to 3.1 - Some "netcoreapp3.1" + // Running on coreclr but no deps.json was deployed with the host so default to 5.0 + Some "net5.0" else // Running on desktop None | pos, length -> // use value from the deps.json file - Some ("netcoreapp" + file.Substring(pos, length)) - - // Tries to figure out the tfm for the compiler instance on the Windows desktop. + let suffix = file.Substring(pos, length) + let prefix = + match Double.TryParse(suffix) with + | true, value when value < 5.0 -> "netcoreapp" + | _ -> "net" + Some (prefix + suffix) + + // Tries to figure out the tfm for the compiler instance on the Windows desktop // On full clr it uses the mscorlib version number let getRunningDotNetFrameworkTfm () = let defaultMscorlibVersion = 4,8,3815,0