Skip to content

Commit b827329

Browse files
committed
Import type: insert namespace qualifiers where needed
1 parent 5b8c582 commit b827329

File tree

5 files changed

+55
-0
lines changed

5 files changed

+55
-0
lines changed

ReSharper.FSharp/src/FSharp.Psi.Features/src/Util/OpensUtil.fs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ let addOpen (offset: DocumentOffset) (fsFile: IFSharpFile) (settings: IContextBo
170170
|> Seq.tail
171171
|> Seq.tryHead
172172
|> Option.iter insertBeforeModuleMember
173+
174+
| :? IDeclaredModuleDeclaration as moduleDecl when
175+
let keyword = moduleDecl.ModuleOrNamespaceKeyword
176+
isNotNull keyword && keyword.GetTreeStartOffset().Offset > offset.Offset ->
177+
// Don't insert open after the reference.
178+
()
179+
173180
| _ ->
174181

175182
match Seq.tryHead moduleDecl.MembersEnumerable with

ReSharper.FSharp/src/FSharp.Psi/src/Impl/FSharpReferenceBindingUtil.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,55 @@ public static string SuggestShortReferenceName(IDeclaredElement declaredElement,
3838
public static string SuggestShortReferenceName(string sourceName, PsiLanguageType language) =>
3939
NamingManager.GetNamingLanguageService(language).MangleNameIfNecessary(sourceName);
4040

41+
[CanBeNull]
42+
private static INamespace GetNamespace([NotNull] IClrDeclaredElement declaredElement)
43+
{
44+
if (declaredElement is ITypeElement typeElement)
45+
return typeElement.GetContainingNamespace();
46+
47+
if (declaredElement.GetContainingType() is { } containingType)
48+
return containingType.GetContainingNamespace();
49+
50+
if (declaredElement is INamespace ns)
51+
return ns.GetContainingNamespace();
52+
53+
return null;
54+
}
55+
56+
private static bool IsNamespaceQualifierRequired([NotNull] FSharpSymbolReference reference)
57+
{
58+
var attribute = reference.GetTreeNode().GetContainingNode<IAttribute>();
59+
return NamedModuleDeclarationNavigator.GetByAttribute(attribute) != null;
60+
}
61+
62+
private static void SetNamespaceQualifiesIfNeeded([NotNull] FSharpSymbolReference reference,
63+
[NotNull] IClrDeclaredElement declaredElement)
64+
{
65+
if (!IsNamespaceQualifierRequired(reference))
66+
return;
67+
68+
var ns = GetNamespace(declaredElement);
69+
if (ns == null || ns.IsRootNamespace)
70+
return;
71+
72+
reference.SetQualifier(ns);
73+
}
74+
4175
public static void SetRequiredQualifiers([NotNull] FSharpSymbolReference reference,
4276
[NotNull] IClrDeclaredElement declaredElement)
4377
{
4478
var containingType = declaredElement.GetContainingType();
4579
if (containingType == null)
80+
{
81+
SetNamespaceQualifiesIfNeeded(reference, declaredElement);
4682
return;
83+
}
4784

4885
if (containingType.IsModule() && !containingType.RequiresQualifiedAccess())
86+
{
87+
SetNamespaceQualifiesIfNeeded(reference, containingType);
4988
return;
89+
}
5090

5191
reference.SetQualifier(containingType);
5292
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[<Optional{caret}>]
2+
module M
3+
()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[<System.Runtime.InteropServices.Optional{caret}>]
2+
module M
3+
()

ReSharper.FSharp/test/src/FSharp.Tests/QuickFixes/ImportTypeTest.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,6 @@ type ImportTypeTest() =
3939
[<Test>] member x.``Qualifiers - Reference name - Type 01``() = x.DoNamedTest()
4040
[<Test>] member x.``Qualifiers - Type extension 01``() = x.DoNamedTest()
4141

42+
[<Test>] member x.``Qualifiers - Namespace 01``() = x.DoNamedTest()
43+
4244
[<Test; NotAvailable>] member x.``Not available 01 - Open``() = x.DoNamedTest()

0 commit comments

Comments
 (0)