From 253bc319a4b1d95667e60994862678f050f1d266 Mon Sep 17 00:00:00 2001 From: 0101 <0101@innit.cz> Date: Thu, 5 Oct 2023 15:31:22 +0200 Subject: [PATCH 1/8] fix --- src/Compiler/Checking/NameResolution.fs | 2 +- .../FSharpChecker/FindReferences.fs | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 292343dd223..fb7357f4444 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -3097,7 +3097,7 @@ let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified | false, _ -> NoResultsOrUsefulErrors | true, res -> OneSuccess (ResolutionInfo.Empty, ResolveUnqualifiedItem ncenv nenv m res, rest) - moduleSearch ad () +++ tyconSearch ad +++ envSearch + tyconSearch ad () +++ moduleSearch ad +++ envSearch let res = match AtMostOneResult m search with diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs index 5063db40fef..c8cff9112c2 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/FindReferences.fs @@ -600,3 +600,57 @@ type internal SomeType() = findAllReferences (expectToFind <| method1Locations()) } +[] +let ``Module with the same name as type`` () = + let source = """ +module Foo + +type MyType = + static member Two = 1 + +let x = MyType.Two + +module MyType = do () // <-- Extra module with the same name as the type + +let y = MyType.Two +""" + + let fileName, options, checker = singleFileChecker source + + let symbolUse = getSymbolUse fileName source "MyType" options checker |> Async.RunSynchronously + + checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol, fastCheck = true) + |> Async.RunSynchronously + |> expectToFind [ + fileName, 4, 5, 11 + fileName, 7, 8, 14 + fileName, 11, 8, 14 + ] + +[] +let ``Module with the same name as type part 2`` () = + let source = """ +module Foo + +module MyType = + + let Three = 7 + +type MyType = + static member Two = 1 + +let x = MyType.Two + +let y = MyType.Three +""" + + let fileName, options, checker = singleFileChecker source + + let symbolUse = getSymbolUse fileName source "MyType" options checker |> Async.RunSynchronously + + checker.FindBackgroundReferencesInFile(fileName, options, symbolUse.Symbol, fastCheck = true) + |> Async.RunSynchronously + |> expectToFind [ + fileName, 4, 7, 13 + fileName, 13, 8, 14 + ] \ No newline at end of file From 7db84649f7777477cc51e247100b255f5661278b Mon Sep 17 00:00:00 2001 From: 0101 <0101@innit.cz> Date: Fri, 6 Oct 2023 00:45:40 +0200 Subject: [PATCH 2/8] ... --- src/Compiler/Checking/NameResolution.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index fb7357f4444..9b2e0b167a1 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2432,7 +2432,7 @@ let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m firs modrefs |> List.map (fun modref -> if IsEntityAccessible amap m ad modref then - notifyNameResolution modref id.idRange + //notifyNameResolution modref id.idRange look 1 modref rest else raze (namespaceOrModuleNotFound.Force())) @@ -3097,7 +3097,7 @@ let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified | false, _ -> NoResultsOrUsefulErrors | true, res -> OneSuccess (ResolutionInfo.Empty, ResolveUnqualifiedItem ncenv nenv m res, rest) - tyconSearch ad () +++ moduleSearch ad +++ envSearch + moduleSearch ad () +++ tyconSearch ad +++ envSearch let res = match AtMostOneResult m search with From 309536c6958b421846ba9e5968d56dee7e745e45 Mon Sep 17 00:00:00 2001 From: 0101 <0101@innit.cz> Date: Fri, 6 Oct 2023 13:27:03 +0200 Subject: [PATCH 3/8] :| --- src/Compiler/Checking/CheckDeclarations.fs | 8 +++---- src/Compiler/Checking/CheckExpressions.fs | 4 ++-- src/Compiler/Checking/NameResolution.fs | 25 +++++++++++----------- src/Compiler/Checking/NameResolution.fsi | 1 + 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 8f41152c420..47e7f21f2e4 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -364,7 +364,7 @@ let ImplicitlyOpenOwnNamespace tcSink g amap scopem enclosingNamespacePath (env: match enclosingNamespacePathToOpen with | id :: rest -> let ad = env.AccessRights - match ResolveLongIdentAsModuleOrNamespace tcSink amap scopem true OpenQualified env.eNameResEnv ad id rest true with + match ResolveLongIdentAsModuleOrNamespace tcSink amap scopem true OpenQualified env.eNameResEnv ad id rest true true with | Result modrefs -> let modrefs = List.map p23 modrefs let lid = SynLongIdent(enclosingNamespacePathToOpen, [] , []) @@ -640,7 +640,7 @@ let TcOpenLidAndPermitAutoResolve tcSink (env: TcEnv) amap (longId : Ident list) | [] -> [] | id :: rest -> let m = longId |> List.map (fun id -> id.idRange) |> List.reduce unionRanges - match ResolveLongIdentAsModuleOrNamespace tcSink amap m true OpenQualified env.NameEnv ad id rest true with + match ResolveLongIdentAsModuleOrNamespace tcSink amap m true OpenQualified env.NameEnv ad id rest true true with | Result res -> res | Exception err -> errorR(err); [] @@ -1532,7 +1532,7 @@ module MutRecBindingChecking = let resolved = match p with | [] -> Result [] - | id :: rest -> ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.NameEnv ad id rest false + | id :: rest -> ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.NameEnv ad id rest false true let mvvs = ForceRaise resolved @@ -4732,7 +4732,7 @@ let rec TcSignatureElementNonMutRec (cenv: cenv) parent typeNames endm (env: TcE let resolved = match p with | [] -> Result [] - | id :: rest -> ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.NameEnv ad id rest false + | id :: rest -> ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.NameEnv ad id rest false true let mvvs = ForceRaise resolved let scopem = unionRanges m endm let unfilteredModrefs = mvvs |> List.map p23 diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index c52fb1cf8aa..8de12305844 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -7334,7 +7334,7 @@ and TcConstExpr cenv (overallTy: OverallTy) env m tpenv c = let expr = let modName = "NumericLiteral" + suffix let ad = env.eAccessRights - match ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.eNameResEnv ad (ident (modName, m)) [] false with + match ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.eNameResEnv ad (ident (modName, m)) [] false true with | Result [] | Exception _ -> error(Error(FSComp.SR.tcNumericLiteralRequiresModule modName, m)) | Result ((_, mref, _) :: _) -> @@ -8121,7 +8121,7 @@ and TcNameOfExpr (cenv: cenv) env tpenv (synArg: SynExpr) = let resolvedToModuleOrNamespaceName = if delayed.IsEmpty then let id,rest = List.headAndTail longId - match ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.eNameResEnv ad id rest true with + match ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.eNameResEnv ad id rest true true with | Result modref when delayed.IsEmpty && modref |> List.exists (p23 >> IsEntityAccessible cenv.amap m ad) -> true // resolved to a module or namespace, done with checks | _ -> diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 9b2e0b167a1..6023c9847ee 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2365,13 +2365,13 @@ let CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities //------------------------------------------------------------------------- /// Perform name resolution for an identifier which must resolve to be a module or namespace. -let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m first fullyQualified (nenv: NameResolutionEnv) ad (id:Ident) (rest: Ident list) isOpenDecl = +let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m first fullyQualified (nenv: NameResolutionEnv) ad (id:Ident) (rest: Ident list) isOpenDecl notifySink = if first && id.idText = MangledGlobalName then match rest with | [] -> error (Error(FSComp.SR.nrGlobalUsedOnlyAsFirstName(), id.idRange)) | id2 :: rest2 -> - ResolveLongIdentAsModuleOrNamespace sink amap m false FullyQualified nenv ad id2 rest2 isOpenDecl + ResolveLongIdentAsModuleOrNamespace sink amap m false FullyQualified nenv ad id2 rest2 isOpenDecl notifySink else let notFoundAux (id: Ident) depth error (tcrefs: TyconRef seq) = let suggestNames (addToBuffer: string -> unit) = @@ -2432,7 +2432,8 @@ let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m firs modrefs |> List.map (fun modref -> if IsEntityAccessible amap m ad modref then - //notifyNameResolution modref id.idRange + if notifySink then + notifyNameResolution modref id.idRange look 1 modref rest else raze (namespaceOrModuleNotFound.Force())) @@ -2440,8 +2441,8 @@ let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m firs | _ -> raze (namespaceOrModuleNotFound.Force()) // Note - 'rest' is annotated due to a bug currently in Unity (see: https://github.com/dotnet/fsharp/pull/7427) -let ResolveLongIdentAsModuleOrNamespaceThen sink atMostOne amap m fullyQualified (nenv: NameResolutionEnv) ad id (rest: Ident list) isOpenDecl f = - match ResolveLongIdentAsModuleOrNamespace sink amap m true fullyQualified nenv ad id [] isOpenDecl with +let ResolveLongIdentAsModuleOrNamespaceThen sink atMostOne amap m fullyQualified (nenv: NameResolutionEnv) ad id (rest: Ident list) isOpenDecl notifySink f = + match ResolveLongIdentAsModuleOrNamespace sink amap m true fullyQualified nenv ad id [] isOpenDecl notifySink with | Result modrefs -> match rest with | [] -> error(Error(FSComp.SR.nrUnexpectedEmptyLongId(), id.idRange)) @@ -3067,7 +3068,7 @@ let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified // Otherwise modules are searched first. REVIEW: modules and types should be searched together. // For each module referenced by 'id', search the module as if it were an F# module and/or a .NET namespace. let moduleSearch ad () = - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest isOpenDecl + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest isOpenDecl false (ResolveExprLongIdentInModuleOrNamespace ncenv nenv typeNameResInfo ad) // REVIEW: somewhat surprisingly, this shows up on performance traces, with tcrefs non-nil. @@ -3258,7 +3259,7 @@ let rec ResolvePatternLongIdentPrim sink (ncenv: NameResolver) fullyQualified wa ResolutionInfo.SendEntityPathToSink (sink, ncenv, nenv, ItemOccurence.Pattern, ad, res, ResultTyparChecker(fun () -> true)) Item.Types (id.idText, [ mkAppTy tcref [] ]) | _ -> - match ResolveLongIdentAsModuleOrNamespace sink ncenv.amap id.idRange true fullyQualified nenv ad id [] false with + match ResolveLongIdentAsModuleOrNamespace sink ncenv.amap id.idRange true fullyQualified nenv ad id [] false true with | Result ((_, mref, _) :: _) -> let res = ResolutionInfo.Empty.AddEntity (id.idRange, mref) ResolutionInfo.SendEntityPathToSink (sink, ncenv, nenv, ItemOccurence.Pattern, ad, res, ResultTyparChecker(fun () -> true)) @@ -3271,7 +3272,7 @@ let rec ResolvePatternLongIdentPrim sink (ncenv: NameResolver) fullyQualified wa // Long identifiers in patterns else let moduleSearch ad () = - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest false + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest false true (ResolvePatternLongIdentInModuleOrNamespace ncenv nenv numTyArgsOpt ad) let tyconSearch ad = @@ -3494,12 +3495,12 @@ let rec ResolveTypeLongIdentPrim sink (ncenv: NameResolver) occurence first full NoResultsOrUsefulErrors let modulSearch = - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv ad id rest false + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv ad id rest false true (ResolveTypeLongIdentInModuleOrNamespace sink nenv ncenv typeNameResInfo ad genOk) |?> List.concat let modulSearchFailed() = - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv AccessibleFromSomeFSharpCode id rest false + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv AccessibleFromSomeFSharpCode id rest false true (ResolveTypeLongIdentInModuleOrNamespace sink nenv ncenv typeNameResInfo.DropStaticArgsInfo AccessibleFromSomeFSharpCode genOk) |?> List.concat @@ -3710,7 +3711,7 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi match lid with | [] -> NoResultsOrUsefulErrors | id2 :: rest2 -> - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m OpenQualified nenv ad id2 rest2 false + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m OpenQualified nenv ad id2 rest2 false true (ResolveFieldInModuleOrNamespace ncenv nenv ad) let resInfo, item, rest = @@ -3823,7 +3824,7 @@ let ResolveNestedField sink (ncenv: NameResolver) nenv ad recdTy lid = match lid with | [] -> NoResultsOrUsefulErrors | modOrNsId :: rest -> - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap modOrNsId.idRange OpenQualified nenv ad modOrNsId rest false (ResolveFieldInModuleOrNamespace ncenv nenv ad) + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap modOrNsId.idRange OpenQualified nenv ad modOrNsId rest false true (ResolveFieldInModuleOrNamespace ncenv nenv ad) |?> List.map (fun (_, FieldResolution(rfinfo, _), restAfterField) -> let fieldId = rest.[ rest.Length - restAfterField.Length - 1 ] fieldId, Item.RecdField rfinfo, restAfterField) diff --git a/src/Compiler/Checking/NameResolution.fsi b/src/Compiler/Checking/NameResolution.fsi index 5dcc55efc94..5d165961a0f 100755 --- a/src/Compiler/Checking/NameResolution.fsi +++ b/src/Compiler/Checking/NameResolution.fsi @@ -684,6 +684,7 @@ val internal ResolveLongIdentAsModuleOrNamespace: id: Ident -> rest: Ident list -> isOpenDecl: bool -> + notifySink: bool -> ResultOrException<(int * ModuleOrNamespaceRef * ModuleOrNamespaceType) list> /// Resolve a long identifier to an object constructor. From fe66e94f27a389c930c3ed74c3ec089800ae9ce2 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Thu, 26 Oct 2023 11:32:56 -0400 Subject: [PATCH 4/8] How about this --- src/Compiler/Checking/NameResolution.fs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 026a0f3c794..cfedecc0848 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2076,6 +2076,7 @@ type TcResultsSinkImpl(tcGlobals, ?sourceText: ISourceText) = let remove m = capturedNameResolutions.RemoveAll(fun cnr -> equals cnr.Range m) |> ignore capturedMethodGroupResolutions.RemoveAll(fun cnr -> equals cnr.Range m) |> ignore + capturedModulesAndNamespaces.RemoveWhere(fst >> equals m) |> ignore let formatStringCheckContext = lazy @@ -2278,7 +2279,7 @@ type ResolutionInfo = Item.ModuleOrNamespaces [eref] else Item.Types(eref.DisplayName, [FreshenTycon ncenv m eref]) - CallNameResolutionSink sink (m, nenv, item, emptyTyparInst, occ, ad)) + CallNameResolutionSinkReplacing sink (m, nenv, item, emptyTyparInst, occ, ad)) warnings typarChecker static member Empty = @@ -2365,7 +2366,7 @@ let CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities //------------------------------------------------------------------------- /// Perform name resolution for an identifier which must resolve to be a module or namespace. -let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m first fullyQualified (nenv: NameResolutionEnv) ad (id:Ident) (rest: Ident list) isOpenDecl notifySink = +let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m first fullyQualified (nenv: NameResolutionEnv) ad (id:Ident) (rest: Ident list) isOpenDecl (notifySink: bool) = if first && id.idText = MangledGlobalName then match rest with | [] -> @@ -2432,8 +2433,8 @@ let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m firs modrefs |> List.map (fun modref -> if IsEntityAccessible amap m ad modref then - if notifySink then - notifyNameResolution modref id.idRange + //if notifySink then + notifyNameResolution modref id.idRange look 1 modref rest else raze (namespaceOrModuleNotFound.Force())) From 1c22577376c70ed74d61aa87d6704c4dfa6b5df9 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Thu, 26 Oct 2023 16:58:05 -0400 Subject: [PATCH 5/8] .... --- src/Compiler/Checking/NameResolution.fs | 9 ++++----- tests/service/EditorTests.fs | 2 +- tests/service/ProjectAnalysisTests.fs | 23 +++++++++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index cfedecc0848..026a0f3c794 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2076,7 +2076,6 @@ type TcResultsSinkImpl(tcGlobals, ?sourceText: ISourceText) = let remove m = capturedNameResolutions.RemoveAll(fun cnr -> equals cnr.Range m) |> ignore capturedMethodGroupResolutions.RemoveAll(fun cnr -> equals cnr.Range m) |> ignore - capturedModulesAndNamespaces.RemoveWhere(fst >> equals m) |> ignore let formatStringCheckContext = lazy @@ -2279,7 +2278,7 @@ type ResolutionInfo = Item.ModuleOrNamespaces [eref] else Item.Types(eref.DisplayName, [FreshenTycon ncenv m eref]) - CallNameResolutionSinkReplacing sink (m, nenv, item, emptyTyparInst, occ, ad)) + CallNameResolutionSink sink (m, nenv, item, emptyTyparInst, occ, ad)) warnings typarChecker static member Empty = @@ -2366,7 +2365,7 @@ let CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities //------------------------------------------------------------------------- /// Perform name resolution for an identifier which must resolve to be a module or namespace. -let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m first fullyQualified (nenv: NameResolutionEnv) ad (id:Ident) (rest: Ident list) isOpenDecl (notifySink: bool) = +let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m first fullyQualified (nenv: NameResolutionEnv) ad (id:Ident) (rest: Ident list) isOpenDecl notifySink = if first && id.idText = MangledGlobalName then match rest with | [] -> @@ -2433,8 +2432,8 @@ let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m firs modrefs |> List.map (fun modref -> if IsEntityAccessible amap m ad modref then - //if notifySink then - notifyNameResolution modref id.idRange + if notifySink then + notifyNameResolution modref id.idRange look 1 modref rest else raze (namespaceOrModuleNotFound.Force())) diff --git a/tests/service/EditorTests.fs b/tests/service/EditorTests.fs index 0c88b9cfbc8..c4778cddda7 100644 --- a/tests/service/EditorTests.fs +++ b/tests/service/EditorTests.fs @@ -1574,7 +1574,7 @@ let _ = Threading.Buzz = null su.Symbol.ToString(), (r.StartLine, r.StartColumn, r.EndLine, r.EndColumn)) |> Array.distinct |> shouldEqual - // note: these "System" sysbol uses are not duplications because each of them corresponts to different namespaces + // note: these "System" symbol uses are not duplications because each of them corresponds to different namespaces [|("System", (2, 5, 2, 11)) ("Threading", (2, 12, 2, 21)) ("System", (3, 5, 3, 11)) diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index 156b2bd879e..98ab29039c3 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -1482,10 +1482,11 @@ let ``Test project 5 all symbols`` () = let allUsesOfAllSymbols = wholeProjectResults.GetAllUsesOfAllSymbols() - |> Array.map (fun su -> su.Symbol.ToString(), su.Symbol.FullName, Project5.cleanFileName su.FileName, tupsZ su.Range, attribsOfSymbolUse su) + |> Seq.map (fun su -> su.Symbol.ToString(), su.Symbol.FullName, Project5.cleanFileName su.FileName, tupsZ su.Range, attribsOfSymbolUse su) + |> Set allUsesOfAllSymbols |> shouldEqual - [|("symbol Even", "Even", "file1", ((4, 6), (4, 10)), ["defn"]); + (Set [("symbol Even", "Even", "file1", ((4, 6), (4, 10)), ["defn"]); ("symbol Odd", "Odd", "file1", ((4, 11), (4, 14)), ["defn"]); ("val input", "input", "file1", ((4, 17), (4, 22)), ["defn"]); ("val op_Equality", "Microsoft.FSharp.Core.Operators.(=)", "file1", @@ -1539,7 +1540,7 @@ let ``Test project 5 all symbols`` () = ("val str", "str", "file1", ((22, 38), (22, 41)), []); ("val parseNumeric", "ActivePatterns.parseNumeric", "file1", ((19, 4), (19, 16)), ["defn"]); - ("ActivePatterns", "ActivePatterns", "file1", ((1, 7), (1, 21)), ["defn"])|] + ("ActivePatterns", "ActivePatterns", "file1", ((1, 7), (1, 21)), ["defn"])]) [] let ``Test complete active patterns' exact ranges from uses of symbols`` () = @@ -2764,11 +2765,12 @@ let ``Test Project17 all symbols`` () = let allUsesOfAllSymbols = wholeProjectResults.GetAllUsesOfAllSymbols() - |> Array.map (fun su -> su.Symbol.ToString(), su.Symbol.DisplayName, Project17.cleanFileName su.FileName, tups su.Range, attribsOfSymbolUse su, attribsOfSymbol su.Symbol) + |> Seq.map (fun su -> su.Symbol.ToString(), su.Symbol.DisplayName, Project17.cleanFileName su.FileName, tups su.Range, attribsOfSymbolUse su, attribsOfSymbol su.Symbol) + |> Set allUsesOfAllSymbols - |> shouldEqual - [|("Microsoft", "Microsoft", "file1", ((4, 8), (4, 17)), [], ["namespace"]); + |> shouldEqual (Set + [("Microsoft", "Microsoft", "file1", ((4, 8), (4, 17)), [], ["namespace"]); ("Collections", "Collections", "file1", ((4, 25), (4, 36)), [], ["namespace"]); ("FSharp", "FSharp", "file1", ((4, 18), (4, 24)), [], ["namespace"]); ("FSharpList`1", "List", "file1", ((4, 8), (4, 41)), [], ["union"]); @@ -2808,7 +2810,7 @@ let ``Test Project17 all symbols`` () = ("property HelpLink", "HelpLink", "file1", ((10, 31), (10, 41)), [], ["slot"; "member"; "prop"]); ("val f3", "f3", "file1", ((10, 4), (10, 6)), ["defn"], ["val"]); - ("Impl", "Impl", "file1", ((2, 7), (2, 11)), ["defn"], ["module"])|] + ("Impl", "Impl", "file1", ((2, 7), (2, 11)), ["defn"], ["module"])]) //----------------------------------------------------------------------------------------- @@ -2906,10 +2908,11 @@ let ``Test Project19 all symbols`` () = let allUsesOfAllSymbols = wholeProjectResults.GetAllUsesOfAllSymbols() - |> Array.map (fun su -> su.Symbol.ToString(), su.Symbol.DisplayName, Project19.cleanFileName su.FileName, tups su.Range, attribsOfSymbolUse su, attribsOfSymbol su.Symbol) + |> Seq.map (fun su -> su.Symbol.ToString(), su.Symbol.DisplayName, Project19.cleanFileName su.FileName, tups su.Range, attribsOfSymbolUse su, attribsOfSymbol su.Symbol) + |> Set allUsesOfAllSymbols |> shouldEqual - [|("field EnumCase1", "EnumCase1", "file1", ((4, 14), (4, 23)), ["defn"], + (Set [("field EnumCase1", "EnumCase1", "file1", ((4, 14), (4, 23)), ["defn"], ["field"; "static"; "1"]); ("field EnumCase2", "EnumCase2", "file1", ((4, 30), (4, 39)), ["defn"], ["field"; "static"; "2"]); @@ -2935,7 +2938,7 @@ let ``Test Project19 all symbols`` () = ("field Monday", "Monday", "file1", ((10, 8), (10, 31)), [], ["field"; "static"; "1"]); ("val s", "s", "file1", ((10, 4), (10, 5)), ["defn"], ["val"]); - ("Impl", "Impl", "file1", ((2, 7), (2, 11)), ["defn"], ["module"])|] + ("Impl", "Impl", "file1", ((2, 7), (2, 11)), ["defn"], ["module"])]) From 34c15a98095752d9197a48931efce2541e7c2ab2 Mon Sep 17 00:00:00 2001 From: Petr Pokorny Date: Fri, 27 Oct 2023 09:32:55 -0400 Subject: [PATCH 6/8] test adjustment --- tests/service/EditorTests.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/service/EditorTests.fs b/tests/service/EditorTests.fs index c4778cddda7..dd5c9cb2d29 100644 --- a/tests/service/EditorTests.fs +++ b/tests/service/EditorTests.fs @@ -1582,7 +1582,6 @@ let _ = Threading.Buzz = null ("Threading", (5, 14, 5, 23)) ("Tasks", (5, 24, 5, 29)) ("val op_Equality", (6, 23, 6, 24)) - ("Threading", (6, 8, 6, 17)) ("Test", (1, 0, 1, 0))|] [] From 1b2c92eb720364657c263de6cfa14d2a21876f5b Mon Sep 17 00:00:00 2001 From: Petr Pokorny <0101@innit.cz> Date: Wed, 1 Nov 2023 16:32:18 +0100 Subject: [PATCH 7/8] Update tests/service/EditorTests.fs Co-authored-by: Petr --- tests/service/EditorTests.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/service/EditorTests.fs b/tests/service/EditorTests.fs index dd5c9cb2d29..e665c97904b 100644 --- a/tests/service/EditorTests.fs +++ b/tests/service/EditorTests.fs @@ -1574,7 +1574,7 @@ let _ = Threading.Buzz = null su.Symbol.ToString(), (r.StartLine, r.StartColumn, r.EndLine, r.EndColumn)) |> Array.distinct |> shouldEqual - // note: these "System" symbol uses are not duplications because each of them corresponds to different namespaces + // note: these "System" and "Threading" symbol uses are not duplications because each of them corresponds to different namespaces [|("System", (2, 5, 2, 11)) ("Threading", (2, 12, 2, 21)) ("System", (3, 5, 3, 11)) From c6a1e0eda366c4f070b4f7dc65902367fd30d9d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pokorn=C3=BD=20=28from=20Dev=20Box=29?= Date: Wed, 1 Nov 2023 12:08:46 -0400 Subject: [PATCH 8/8] Changed bool to DU --- src/Compiler/Checking/CheckDeclarations.fs | 8 ++++---- src/Compiler/Checking/CheckExpressions.fs | 4 ++-- src/Compiler/Checking/NameResolution.fs | 21 +++++++++++++-------- src/Compiler/Checking/NameResolution.fsi | 8 +++++++- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index e2d8d5abc75..411de0b07dd 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -363,7 +363,7 @@ let ImplicitlyOpenOwnNamespace tcSink g amap scopem enclosingNamespacePath (env: match enclosingNamespacePathToOpen with | id :: rest -> let ad = env.AccessRights - match ResolveLongIdentAsModuleOrNamespace tcSink amap scopem true OpenQualified env.eNameResEnv ad id rest true true with + match ResolveLongIdentAsModuleOrNamespace tcSink amap scopem true OpenQualified env.eNameResEnv ad id rest true ShouldNotifySink.Yes with | Result modrefs -> let modrefs = List.map p23 modrefs let lid = SynLongIdent(enclosingNamespacePathToOpen, [] , []) @@ -639,7 +639,7 @@ let TcOpenLidAndPermitAutoResolve tcSink (env: TcEnv) amap (longId : Ident list) | [] -> [] | id :: rest -> let m = longId |> List.map (fun id -> id.idRange) |> List.reduce unionRanges - match ResolveLongIdentAsModuleOrNamespace tcSink amap m true OpenQualified env.NameEnv ad id rest true true with + match ResolveLongIdentAsModuleOrNamespace tcSink amap m true OpenQualified env.NameEnv ad id rest true ShouldNotifySink.Yes with | Result res -> res | Exception err -> errorR(err); [] @@ -1531,7 +1531,7 @@ module MutRecBindingChecking = let resolved = match p with | [] -> Result [] - | id :: rest -> ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.NameEnv ad id rest false true + | id :: rest -> ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.NameEnv ad id rest false ShouldNotifySink.Yes let mvvs = ForceRaise resolved @@ -4738,7 +4738,7 @@ let rec TcSignatureElementNonMutRec (cenv: cenv) parent typeNames endm (env: TcE let resolved = match p with | [] -> Result [] - | id :: rest -> ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.NameEnv ad id rest false true + | id :: rest -> ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.NameEnv ad id rest false ShouldNotifySink.Yes let mvvs = ForceRaise resolved let scopem = unionRanges m endm let unfilteredModrefs = mvvs |> List.map p23 diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 2a95e7b7077..527fc3233ae 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -7334,7 +7334,7 @@ and TcConstExpr cenv (overallTy: OverallTy) env m tpenv c = let expr = let modName = "NumericLiteral" + suffix let ad = env.eAccessRights - match ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.eNameResEnv ad (ident (modName, m)) [] false true with + match ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.eNameResEnv ad (ident (modName, m)) [] false ShouldNotifySink.Yes with | Result [] | Exception _ -> error(Error(FSComp.SR.tcNumericLiteralRequiresModule modName, m)) | Result ((_, mref, _) :: _) -> @@ -8121,7 +8121,7 @@ and TcNameOfExpr (cenv: cenv) env tpenv (synArg: SynExpr) = let resolvedToModuleOrNamespaceName = if delayed.IsEmpty then let id,rest = List.headAndTail longId - match ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.eNameResEnv ad id rest true true with + match ResolveLongIdentAsModuleOrNamespace cenv.tcSink cenv.amap m true OpenQualified env.eNameResEnv ad id rest true ShouldNotifySink.Yes with | Result modref when delayed.IsEmpty && modref |> List.exists (p23 >> IsEntityAccessible cenv.amap m ad) -> true // resolved to a module or namespace, done with checks | _ -> diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 026a0f3c794..eb753da44f8 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2364,6 +2364,11 @@ let CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities // Consume ids that refer to a namespace, module, or type //------------------------------------------------------------------------- +[] +type ShouldNotifySink = + | Yes + | No + /// Perform name resolution for an identifier which must resolve to be a module or namespace. let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m first fullyQualified (nenv: NameResolutionEnv) ad (id:Ident) (rest: Ident list) isOpenDecl notifySink = if first && id.idText = MangledGlobalName then @@ -2432,7 +2437,7 @@ let rec ResolveLongIdentAsModuleOrNamespace sink (amap: Import.ImportMap) m firs modrefs |> List.map (fun modref -> if IsEntityAccessible amap m ad modref then - if notifySink then + if notifySink = ShouldNotifySink.Yes then notifyNameResolution modref id.idRange look 1 modref rest else @@ -3068,7 +3073,7 @@ let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified // Otherwise modules are searched first. REVIEW: modules and types should be searched together. // For each module referenced by 'id', search the module as if it were an F# module and/or a .NET namespace. let moduleSearch ad () = - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest isOpenDecl false + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest isOpenDecl ShouldNotifySink.No (ResolveExprLongIdentInModuleOrNamespace ncenv nenv typeNameResInfo ad) // REVIEW: somewhat surprisingly, this shows up on performance traces, with tcrefs non-nil. @@ -3259,7 +3264,7 @@ let rec ResolvePatternLongIdentPrim sink (ncenv: NameResolver) fullyQualified wa ResolutionInfo.SendEntityPathToSink (sink, ncenv, nenv, ItemOccurence.Pattern, ad, res, ResultTyparChecker(fun () -> true)) Item.Types (id.idText, [ mkAppTy tcref [] ]) | _ -> - match ResolveLongIdentAsModuleOrNamespace sink ncenv.amap id.idRange true fullyQualified nenv ad id [] false true with + match ResolveLongIdentAsModuleOrNamespace sink ncenv.amap id.idRange true fullyQualified nenv ad id [] false ShouldNotifySink.Yes with | Result ((_, mref, _) :: _) -> let res = ResolutionInfo.Empty.AddEntity (id.idRange, mref) ResolutionInfo.SendEntityPathToSink (sink, ncenv, nenv, ItemOccurence.Pattern, ad, res, ResultTyparChecker(fun () -> true)) @@ -3272,7 +3277,7 @@ let rec ResolvePatternLongIdentPrim sink (ncenv: NameResolver) fullyQualified wa // Long identifiers in patterns else let moduleSearch ad () = - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest false true + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m fullyQualified nenv ad id rest false ShouldNotifySink.Yes (ResolvePatternLongIdentInModuleOrNamespace ncenv nenv numTyArgsOpt ad) let tyconSearch ad = @@ -3495,12 +3500,12 @@ let rec ResolveTypeLongIdentPrim sink (ncenv: NameResolver) occurence first full NoResultsOrUsefulErrors let modulSearch = - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv ad id rest false true + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv ad id rest false ShouldNotifySink.Yes (ResolveTypeLongIdentInModuleOrNamespace sink nenv ncenv typeNameResInfo ad genOk) |?> List.concat let modulSearchFailed() = - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv AccessibleFromSomeFSharpCode id rest false true + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AllResults ncenv.amap m2 fullyQualified nenv AccessibleFromSomeFSharpCode id rest false ShouldNotifySink.Yes (ResolveTypeLongIdentInModuleOrNamespace sink nenv ncenv typeNameResInfo.DropStaticArgsInfo AccessibleFromSomeFSharpCode genOk) |?> List.concat @@ -3711,7 +3716,7 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi match lid with | [] -> NoResultsOrUsefulErrors | id2 :: rest2 -> - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m OpenQualified nenv ad id2 rest2 false true + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap m OpenQualified nenv ad id2 rest2 false ShouldNotifySink.Yes (ResolveFieldInModuleOrNamespace ncenv nenv ad) let resInfo, item, rest = @@ -3824,7 +3829,7 @@ let ResolveNestedField sink (ncenv: NameResolver) nenv ad recdTy lid = match lid with | [] -> NoResultsOrUsefulErrors | modOrNsId :: rest -> - ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap modOrNsId.idRange OpenQualified nenv ad modOrNsId rest false true (ResolveFieldInModuleOrNamespace ncenv nenv ad) + ResolveLongIdentAsModuleOrNamespaceThen sink ResultCollectionSettings.AtMostOneResult ncenv.amap modOrNsId.idRange OpenQualified nenv ad modOrNsId rest false ShouldNotifySink.Yes (ResolveFieldInModuleOrNamespace ncenv nenv ad) |?> List.map (fun (_, FieldResolution(rfinfo, _), restAfterField) -> let fieldId = rest.[ rest.Length - restAfterField.Length - 1 ] fieldId, Item.RecdField rfinfo, restAfterField) diff --git a/src/Compiler/Checking/NameResolution.fsi b/src/Compiler/Checking/NameResolution.fsi index 5d165961a0f..e7c970c14cb 100755 --- a/src/Compiler/Checking/NameResolution.fsi +++ b/src/Compiler/Checking/NameResolution.fsi @@ -598,6 +598,12 @@ type AfterResolution = (MethInfo * PropInfo option * TyparInstantiation -> unit) * (unit -> unit) +/// Indicates whether we want to report found items to the name resolution sink +[] +type ShouldNotifySink = + | Yes + | No + /// Temporarily redirect reporting of name resolution and type checking results val internal WithNewTypecheckResultsSink: ITypecheckResultsSink * TcResultsSink -> System.IDisposable @@ -684,7 +690,7 @@ val internal ResolveLongIdentAsModuleOrNamespace: id: Ident -> rest: Ident list -> isOpenDecl: bool -> - notifySink: bool -> + notifySink: ShouldNotifySink -> ResultOrException<(int * ModuleOrNamespaceRef * ModuleOrNamespaceType) list> /// Resolve a long identifier to an object constructor.