diff --git a/src/fsharp/CheckDeclarations.fs b/src/fsharp/CheckDeclarations.fs index bb7813857c..b8dfbbb9e4 100644 --- a/src/fsharp/CheckDeclarations.fs +++ b/src/fsharp/CheckDeclarations.fs @@ -454,7 +454,7 @@ module TcRecdUnionAndEnumDeclarations = let ValidateFieldNames (synFields: SynField list, tastFields: RecdField list) = let seen = Dictionary() - for (sf, f) in List.zip synFields tastFields do + (synFields, tastFields) ||> List.iter2 (fun sf f -> match seen.TryGetValue f.Name with | true, synField -> match sf, synField with @@ -465,7 +465,7 @@ module TcRecdUnionAndEnumDeclarations = error(Error(FSComp.SR.tcFieldNameConflictsWithGeneratedNameForAnonymousField(id.idText), id.idRange)) | _ -> assert false | _ -> - seen.Add(f.Name, sf) + seen.Add(f.Name, sf)) let TcUnionCaseDecl cenv env parent thisTy thisTyInst tpenv (SynUnionCase(Attributes synAttrs, id, args, xmldoc, vis, m)) = let attrs = TcAttributes cenv env AttributeTargets.UnionCaseDecl synAttrs // the attributes of a union case decl get attached to the generated "static factory" method diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index 2bd5922080..c38b96e329 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -4023,10 +4023,10 @@ and TcValSpec cenv env declKind newOk containerInfo memFlagsOpt thisTyOpt tpenv if SynInfo.HasOptionalArgs valSynInfo then let curriedArgTys, returnTy = GetTopTauTypeInFSharpForm cenv.g argsData ty' m let curriedArgTys = - (List.zip (List.mapSquared fst curriedArgTys) valSynInfo.CurriedArgInfos) - |> List.map (fun (argTys, argInfos) -> - (List.zip argTys argInfos) - |> List.map (fun (argty, argInfo) -> + ((List.mapSquared fst curriedArgTys), valSynInfo.CurriedArgInfos) + ||> List.map2 (fun argTys argInfos -> + (argTys, argInfos) + ||> List.map2 (fun argty argInfo -> if SynInfo.IsOptionalArg argInfo then mkOptionTy cenv.g argty else argty)) mkIteratedFunTy (List.map (mkRefTupledTy cenv.g) curriedArgTys) returnTy diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index a8b8d2cb8d..8578a9bef2 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -1552,8 +1552,8 @@ type AssemblyBuilder(cenv: cenv, anonTypeTable: AnonTypeGenerationTable) as mgbu tycon.entity_tycon_repr <- TRecdRepr (Construct.MakeRecdFieldsTable - [ for (tp, (propName, _fldName, _fldTy)) in (List.zip tps flds) -> - Construct.NewRecdField false None (mkSynId m propName) false (mkTyparTy tp) true false [] [] XmlDoc.Empty taccessPublic false ]) + ((tps, flds) ||> List.map2 (fun tp (propName, _fldName, _fldTy) -> + Construct.NewRecdField false None (mkSynId m propName) false (mkTyparTy tp) true false [] [] XmlDoc.Empty taccessPublic false))) let tcref = mkLocalTyconRef tycon let _, typ = generalizeTyconRef tcref diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 24d91cbf59..a91660a6bf 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -895,10 +895,9 @@ module private PrintTypes = let typesWithDiscrimants,typarsAndCxs = PrettyTypes.PrettifyDiscriminantAndTypePairs denv.g typesWithDiscrimants let retTy = typesWithDiscrimants |> List.find (function (0, _) -> true | _ -> false) |> snd let argInfos = - typesWithDiscrimants + typesWithDiscrimants |> List.choose (function (1,ty) -> Some ty | _ -> None) - |> List.zip argInfos - |> List.map (fun ((_,argInfo),tTy) -> tTy, argInfo) + |> List.map2 (fun (_, argInfo) tTy -> tTy, argInfo) argInfos let genParamTys = typesWithDiscrimants |> List.choose (function (2,ty) -> Some ty | _ -> None) diff --git a/src/fsharp/ParseAndCheckInputs.fs b/src/fsharp/ParseAndCheckInputs.fs index 3835ae3ec6..1cbc40f20a 100644 --- a/src/fsharp/ParseAndCheckInputs.fs +++ b/src/fsharp/ParseAndCheckInputs.fs @@ -426,7 +426,7 @@ let ParseOneInputFile (tcConfig: TcConfig, lexResourceManager, conditionalCompil let ParseInputFiles (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, sourceFiles, errorLogger: ErrorLogger, exiter: Exiter, createErrorLogger: (Exiter -> CapturingErrorLogger), retryLocked) = try let isLastCompiland, isExe = sourceFiles |> tcConfig.ComputeCanContainEntryPoint - let sourceFiles = isLastCompiland |> List.zip sourceFiles |> Array.ofSeq + let sourceFiles = isLastCompiland |> List.zip sourceFiles |> Array.ofList if tcConfig.concurrentBuild then let mutable exitCode = 0 diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index e307dd27d1..027543d537 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -4933,7 +4933,7 @@ let InferArityOfExpr g allowTypeDirectedDetupling ty partialArgAttribsL retAttri assert (List.length vsl = List.length dtys) let curriedArgInfos = - (List.zip vsl dtys) |> List.mapi (fun i (vs, ty) -> + (vsl, dtys) ||> List.mapi2 (fun i vs ty -> let partialAttribs = if i < partialArgAttribsL.Length then partialArgAttribsL.[i] else [] let tys = match allowTypeDirectedDetupling with diff --git a/src/fsharp/service/FSharpParseFileResults.fs b/src/fsharp/service/FSharpParseFileResults.fs index 923097f807..e2bc5953b7 100644 --- a/src/fsharp/service/FSharpParseFileResults.fs +++ b/src/fsharp/service/FSharpParseFileResults.fs @@ -127,7 +127,7 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, override _.VisitBinding(_path, defaultTraverse, binding) = match binding with - | SynBinding(_, _, _, _, _, _, _, _, _, expr, _range, _) as b when rangeContainsPos b.RangeOfBindingWithRhs pos -> + | SynBinding(_, _, _, _, _, _, SynValData (None, _, _), _, _, expr, _range, _) as b when rangeContainsPos b.RangeOfBindingWithRhs pos -> match tryGetIdentRangeFromBinding b with | Some range -> walkBinding expr range | None -> None @@ -158,6 +158,8 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, SyntaxTraversal.Traverse(pos, input, { new SyntaxVisitorBase<_>() with member _.VisitExpr(_, traverseSynExpr, defaultTraverse, expr) = match expr with + | SynExpr.TypeApp (_, _, _, _, _, _, range) when rangeContainsPos range pos -> + Some range | SynExpr.App(_, _, _, SynExpr.CompExpr (_, _, expr, _), range) when rangeContainsPos range pos -> traverseSynExpr expr | SynExpr.App (_, _, _, _, range) when rangeContainsPos range pos -> @@ -176,6 +178,9 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | SynExpr.Paren (expr, _, _, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos + | SynExpr.TypeApp (expr, _, _, _, _, _, _) -> + getIdentRangeForFuncExprInApp traverseSynExpr expr pos + | SynExpr.App (_, _, funcExpr, argExpr, _) -> match argExpr with | SynExpr.App (_, _, _, _, range) when rangeContainsPos range pos -> @@ -269,6 +274,8 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, SyntaxTraversal.Traverse(pos, input, { new SyntaxVisitorBase<_>() with member _.VisitExpr(_, traverseSynExpr, defaultTraverse, expr) = match expr with + | SynExpr.TypeApp (expr, _, _, _, _, _, range) when rangeContainsPos range pos -> + getIdentRangeForFuncExprInApp traverseSynExpr expr pos | SynExpr.App (_, _, _funcExpr, _, range) as app when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr app pos | _ -> defaultTraverse expr diff --git a/src/fsharp/service/ServiceDeclarationLists.fs b/src/fsharp/service/ServiceDeclarationLists.fs index 73624eb266..8551897cfc 100644 --- a/src/fsharp/service/ServiceDeclarationLists.fs +++ b/src/fsharp/service/ServiceDeclarationLists.fs @@ -580,9 +580,8 @@ module internal DescriptionListsImpl = // Remake the params using the prettified versions let parameters = - (prettyParamTys, prettyParamTysL) - ||> List.zip - |> List.map (fun (tau, tyL) -> + (prettyParamTys, prettyParamTysL) + ||> List.map2 (fun tau tyL -> let display = LayoutRender.toArray tyL MethodGroupItemParameter( name = "", diff --git a/src/fsharp/symbols/SymbolHelpers.fs b/src/fsharp/symbols/SymbolHelpers.fs index ec61645da8..5d9181ad8c 100644 --- a/src/fsharp/symbols/SymbolHelpers.fs +++ b/src/fsharp/symbols/SymbolHelpers.fs @@ -680,17 +680,17 @@ module internal SymbolHelpers = | Item.RecdField(RecdFieldInfo(_, RecdFieldRef(tcref1, n1))), Item.RecdField(RecdFieldInfo(_, RecdFieldRef(tcref2, n2))) -> (tyconRefEq g tcref1 tcref2) && (n1 = n2) // there is no direct function as in the previous case | Item.Property(_, pi1s), Item.Property(_, pi2s) -> - List.zip pi1s pi2s |> List.forall(fun (pi1, pi2) -> PropInfo.PropInfosUseIdenticalDefinitions pi1 pi2) + (pi1s, pi2s) ||> List.forall2 (fun pi1 pi2 -> PropInfo.PropInfosUseIdenticalDefinitions pi1 pi2) | Item.Event evt1, Item.Event evt2 -> EventInfo.EventInfosUseIdenticalDefinitions evt1 evt2 | Item.AnonRecdField(anon1, _, i1, _), Item.AnonRecdField(anon2, _, i2, _) -> anonInfoEquiv anon1 anon2 && i1 = i2 | Item.CtorGroup(_, meths1), Item.CtorGroup(_, meths2) -> - List.zip meths1 meths2 - |> List.forall (fun (minfo1, minfo2) -> MethInfo.MethInfosUseIdenticalDefinitions minfo1 minfo2) + (meths1, meths2) + ||> List.forall2 (fun minfo1 minfo2 -> MethInfo.MethInfosUseIdenticalDefinitions minfo1 minfo2) | Item.UnqualifiedType tcRefs1, Item.UnqualifiedType tcRefs2 -> - List.zip tcRefs1 tcRefs2 - |> List.forall (fun (tcRef1, tcRef2) -> tyconRefEq g tcRef1 tcRef2) + (tcRefs1, tcRefs2) + ||> List.forall2 (fun tcRef1 tcRef2 -> tyconRefEq g tcRef1 tcRef2) | Item.Types(_, [TType.TType_app(tcRef1, _)]), Item.UnqualifiedType([tcRef2]) -> tyconRefEq g tcRef1 tcRef2 | Item.UnqualifiedType([tcRef1]), Item.Types(_, [TType.TType_app(tcRef2, _)]) -> tyconRefEq g tcRef1 tcRef2 | _ -> false) diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index 97af23e4d7..70a0b00123 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -605,8 +605,8 @@ module rec Compiler = // TODO: Check all "categories", collect all results and print alltogether. checkEqual "Errors count" expected.Length errors.Length - List.zip errors expected - |> List.iter (fun (actualError, expectedError) -> + (errors, expected) + ||> List.iter2 (fun actualError expectedError -> let { Error = actualError; Range = actualRange; Message = actualMessage } = actualError let { Error = expectedError; Range = expectedRange; Message = expectedMessage } = expectedError checkEqual "Error" expectedError actualError diff --git a/tests/service/ServiceUntypedParseTests.fs b/tests/service/ServiceUntypedParseTests.fs index d33ca49e82..ae23e2ae02 100644 --- a/tests/service/ServiceUntypedParseTests.fs +++ b/tests/service/ServiceUntypedParseTests.fs @@ -683,7 +683,7 @@ async { Assert.False(parseFileResults.IsPosContainedInApplication (mkPos 2 5), "Pos should not be in application") [] - let ``TryRangeOfFunctionOrMethodBeingApplied - inside CE return - no``() = + let ``IsPosContainedInApplication - inside CE return - no``() = let source = """ async { return sqrt @@ -693,7 +693,7 @@ async { Assert.False(parseFileResults.IsPosContainedInApplication (mkPos 2 5), "Pos should not be in application") [] - let ``TryRangeOfFunctionOrMethodBeingApplied - inside CE - yes``() = + let ``IsPosContainedInApplication - inside CE - yes``() = let source = """ let myAdd x y = x + y async { @@ -703,6 +703,15 @@ async { let parseFileResults, _ = getParseAndCheckResults source Assert.False(parseFileResults.IsPosContainedInApplication (mkPos 3 18), "Pos should not be in application") + [] + let ``IsPosContainedInApplication - inside type application``() = + let source = """ +let f<'x> x = () +f + """ + let parseFileResults, _ = getParseAndCheckResults source + Assert.True(parseFileResults.IsPosContainedInApplication (mkPos 3 6), "A type application is an application, expected True.") + [] let ``TryRangeOfFunctionOrMethodBeingApplied - no application``() = let source = """ @@ -982,6 +991,21 @@ C.Yeet(1, 2, (fun x -> sqrt)) |> tups |> shouldEqual ((3, 23), (3, 27)) + [] + let ``TryRangeOfFunctionOrMethodBeingApplied - generic-typed app``() = + let source = """ +let f<'x> x = () +f +""" + let parseFileResults, _ = getParseAndCheckResults source + let res = parseFileResults.TryRangeOfFunctionOrMethodBeingApplied (mkPos 3 6) + match res with + | None -> Assert.Fail("Expected 'f' but got nothing") + | Some range -> + range + |> tups + |> shouldEqual ((3, 0), (3, 1)) + module PipelinesAndArgs = [] let ``TryIdentOfPipelineContainingPosAndNumArgsApplied - No pipeline, no infix app``() = diff --git a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs index 7e1523ea0b..5baf4bf593 100644 --- a/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs +++ b/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs @@ -476,7 +476,7 @@ type internal FSharpSignatureHelpProvider // 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 ' ', None when adjustedColumnChar <> ',' && adjustedColumnChar <> '(' && adjustedColumnChar <> '<' -> + | Some ' ', _ when adjustedColumnChar <> ',' && adjustedColumnChar <> '(' && adjustedColumnChar <> '<' -> return! FSharpSignatureHelpProvider.ProvideParametersAsyncAux( parseResults,