Skip to content

Commit 132b25c

Browse files
committed
After pair programming session.
1 parent 6dd739e commit 132b25c

File tree

8 files changed

+87
-84
lines changed

8 files changed

+87
-84
lines changed

ReSharper.FSharp/src/FSharp.Psi.Features/src/LanguageService/FSharpElementFactory.fs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -400,18 +400,12 @@ type FSharpElementFactory(languageService: IFSharpLanguageService, sourceFile: I
400400

401401
member this.CreateModule(name) =
402402
let file = createFile $"module {name}"
403-
match file.ModuleDeclarations.[0] with
404-
| :? INamedModuleDeclaration as nmd -> nmd
405-
| _ -> failwith "Could not get named module"
403+
file.ModuleDeclarations.[0] :?> INamedModuleDeclaration
406404

407405
member this.CreateNamespace(name) =
408406
let file = createFile $"namespace {name}"
409-
match file.ModuleDeclarations.[0] with
410-
| :? INamedNamespaceDeclaration as nnd -> nnd
411-
| _ -> failwith "Could not get namespace"
407+
file.ModuleDeclarations.[0] :?> INamespaceDeclaration
412408

413409
member this.CreateNestedModule(name) =
414410
let file = createFile $"module {name} = begin end"
415-
match file.ModuleDeclarations.[0].Members.[0] with
416-
| :? INestedModuleDeclaration as nmd -> nmd
417-
| _ -> failwith "Could not get nested module"
411+
file.ModuleDeclarations.[0].Members.[0] :?> INestedModuleDeclaration

ReSharper.FSharp/src/FSharp.Psi.Features/src/Parsing/FSharpImplTreeBuilder.fs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ type FSharpImplTreeBuilder(lexer, document, decls, lifetime, path, projectedOffs
3434
let (SynModuleOrNamespace(lid, _, moduleKind, decls, XmlDoc xmlDoc, attrs, _, range, _)) = moduleOrNamespace
3535
let mark, elementType = x.StartTopLevelDeclaration(lid, attrs, moduleKind, xmlDoc, range)
3636
for decl in decls do
37-
x.ProcessModuleMemberDeclaration(decl)
37+
x.ProcessModuleMemberDeclaration(decl, moduleOrNamespace.Range)
3838
x.EnsureMembersAreFinished()
3939
x.FinishTopLevelDeclaration(mark, range, elementType)
4040

41-
member x.ProcessModuleMemberDeclaration(moduleMember) =
41+
member x.ProcessModuleMemberDeclaration(moduleMember, parentRange) =
4242
match unfinishedDeclaration with
4343
| None -> ()
4444
| Some(mark, range, elementType) ->
@@ -52,7 +52,12 @@ type FSharpImplTreeBuilder(lexer, document, decls, lifetime, path, projectedOffs
5252
| SynModuleDecl.NestedModule(SynComponentInfo(attrs, _, _, _, XmlDoc xmlDoc, _, _, _), _, decls, _, range, _) ->
5353
let mark = x.MarkAndProcessIntro(attrs, xmlDoc, null, range)
5454
for decl in decls do
55-
x.ProcessModuleMemberDeclaration(decl)
55+
x.ProcessModuleMemberDeclaration(decl, parentRange)
56+
57+
if decls.IsEmpty then
58+
x.AdvanceToTokenOrRangeEnd(FSharpTokenType.END, parentRange)
59+
x.Advance()
60+
5661
x.Done(range, mark, ElementType.NESTED_MODULE_DECLARATION)
5762

5863
| SynModuleDecl.Types(typeDefns, range) ->
Lines changed: 60 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,72 @@
11
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.ContextActions
22

33
open System.IO
4+
open JetBrains.ReSharper.Psi.Tree
5+
open JetBrains.DocumentManagers.Transactions.ProjectHostActions.Ordering
6+
open JetBrains.ProjectModel.ProjectsHost
7+
open JetBrains.RdBackend.Common.Features.ProjectModel
48
open JetBrains.ReSharper.Feature.Services.ContextActions
59
open JetBrains.ReSharper.Plugins.FSharp.Psi
610
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Intentions
7-
open type JetBrains.ReSharper.Psi.PsiSourceFileExtensions
811
open JetBrains.ReSharper.Plugins.FSharp
12+
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
913
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
1014
open JetBrains.ReSharper.Psi
1115
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
1216

13-
type TopLevelModuleOrNamespace =
14-
{
15-
IsModule: bool
16-
Name: string
17-
NestedModules: NestedModule list
18-
}
19-
20-
and NestedModule =
21-
{
22-
Name: string
23-
NestedModules: NestedModule list
24-
}
17+
// extract value -> ctrl alt v
18+
// undo that -> ctrl alt n
2519

2620
[<ContextAction(Group = "F#", Name = "Generate signature file for current file", Priority = 1s,
2721
Description = "Generate signature file for current file.")>]
2822
type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider) =
2923
inherit FSharpContextActionBase(dataProvider)
30-
24+
3125
let mkSignatureFile (fsharpFile: IFSharpFile) : IFSharpFile =
3226
let factory : IFSharpElementFactory = fsharpFile.CreateElementFactory()
3327
let signatureFile : IFSharpFile = factory.CreateEmptyFile()
34-
35-
let rec processModuleMembers (parent: IFSharpTreeNode) (members: IModuleMember seq) =
36-
for m in members do
37-
match m with
38-
| :? INestedModuleDeclaration as nmd ->
39-
let nestedModuleNode = factory.CreateNestedModule(nmd.NameIdentifier.Name)
40-
// TODO: if the nested module has nested modules, clear the content (`begin end`) and process them.
41-
ModificationUtil.AddChild(parent, nestedModuleNode) |> ignore
42-
| _ -> ()
28+
let lineEnding = fsharpFile.GetLineEnding()
29+
30+
let rec processModuleLikeDeclaration (indentation: int) (moduleDecl: IModuleLikeDeclaration) (moduleSig: IModuleLikeDeclaration) : IFSharpTreeNode =
31+
for moduleMember in moduleDecl.Members do
32+
// newline + indentation whitespace
33+
addNodesAfter moduleSig.LastChild [
34+
NewLine(lineEnding)
35+
Whitespace(indentation)
36+
match moduleMember with
37+
| :? INestedModuleDeclaration as nestedNestedModule ->
38+
let nestedSigModule = factory.CreateNestedModule(nestedNestedModule.NameIdentifier.Name)
39+
let members = nestedNestedModule.Members
40+
let shouldEmptyContent =
41+
not members.IsEmpty
42+
&& members |> Seq.forall (function | :? IExpressionStatement -> false | _ -> true)
43+
44+
if shouldEmptyContent then
45+
ModificationUtil.DeleteChildRange (nestedSigModule.EqualsToken.NextSibling, nestedSigModule.LastChild)
46+
processModuleLikeDeclaration (indentation + moduleDecl.GetIndentSize()) nestedNestedModule nestedSigModule
47+
| :? IOpenStatement as openStatement ->
48+
openStatement.Copy()
49+
| _ -> ()
50+
]
51+
|> ignore
52+
53+
moduleSig
4354

4455
for decl in fsharpFile.ModuleDeclarations do
45-
match decl with
46-
| :? INamedModuleDeclaration as nmd ->
47-
let moduleNode = factory.CreateModule(nmd.NameIdentifier.Name)
48-
processModuleMembers moduleNode nmd.Members
49-
ModificationUtil.AddChild(signatureFile, moduleNode) |> ignore
50-
| :? INamedNamespaceDeclaration as nnd ->
51-
let namespaceNode = factory.CreateModule(nnd.NameIdentifier.Name)
52-
processModuleMembers namespaceNode nnd.Members
53-
ModificationUtil.AddChild(signatureFile, namespaceNode) |> ignore
54-
| _ -> ()
56+
let signatureModule : IModuleLikeDeclaration =
57+
match decl with
58+
| :? INamedModuleDeclaration as nmd ->
59+
factory.CreateModule(nmd.DeclaredElement.GetClrName().FullName)
60+
| :? IGlobalNamespaceDeclaration ->
61+
factory.CreateNamespace("global") :?> _
62+
| :? INamedNamespaceDeclaration as nnd ->
63+
// TODO: add an interface that could unify named and global namespace.
64+
factory.CreateNamespace(nnd.QualifiedName) :?> _
65+
| decl -> failwithf $"Unexpected declaration, got: %A{decl}"
66+
67+
ModificationUtil.AddChildAfter(signatureModule.LastChild, NewLine(lineEnding)) |> ignore
68+
let signatureModule = processModuleLikeDeclaration 0 decl signatureModule
69+
ModificationUtil.AddChild(signatureFile, signatureModule) |> ignore
5570

5671
signatureFile
5772

@@ -71,30 +86,18 @@ type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider)
7186
let fsharpFile = projectFile.GetPrimaryPsiFile().AsFSharpFile()
7287
let physicalPath = dataProvider.SourceFile.ToProjectFile().Location.FileAccessPath
7388
let fsiFile = Path.ChangeExtension(physicalPath, ".fsi")
74-
7589
let signatureFile = mkSignatureFile fsharpFile
76-
// try
77-
// let currentFSharpFile = dataProvider.PsiFile
78-
// let fcsService = currentFSharpFile.FcsCheckerService
79-
// let checkResult = fcsService.ParseAndCheckFile(currentFSharpFile.GetSourceFile(), "for signature file", true)
80-
// do
81-
// match checkResult with
82-
// | None -> ()
83-
// | Some { CheckResults = checkResult } ->
84-
//
85-
// match checkResult.GenerateSignature() with
86-
// | None -> ()
87-
// | Some signatureSourceText ->
88-
// let content = string signatureSourceText
89-
// File.WriteAllText(fsiFile, content)
90-
// with ex ->
91-
// // TODO: show some balloon thing?
92-
// ()
90+
File.WriteAllText(fsiFile, signatureFile.GetText())
9391

94-
// solution.InvokeUnderTransaction(fun transactionCookie ->
95-
// let virtualPath = FileSystemPath.TryParse(fsiFile).ToVirtualFileSystemPath()
96-
// let relativeTo = RelativeTo(projectFile, RelativeToType.Before)
97-
// transactionCookie.AddFile(projectFile.ParentFolder, virtualPath, context = OrderingContext(relativeTo))
98-
// |> ignore)
92+
solution.InvokeUnderTransaction(fun transactionCookie ->
93+
let virtualPath = FileSystemPath.TryParse(fsiFile).ToVirtualFileSystemPath()
94+
let relativeTo = RelativeTo(projectFile, RelativeToType.Before)
95+
transactionCookie.AddFile(projectFile.ParentFolder, virtualPath, context = OrderingContext(relativeTo))
96+
|> ignore)
9997

100-
null
98+
// TODO: it would be nice if we opened the signature file that was just created. Maybe split?
99+
null
100+
101+
// First test name would be: ``ModuleStructure 01`` , ``NamespaceStructure 01``
102+
103+
// TODO: raise parser issue.

ReSharper.FSharp/src/FSharp.Psi/src/FSharp.psi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ namedNamespaceDeclaration options { stubBase="FSharpDeclarationBase"; }:
9999
topLevelNamedDeclarationName
100100
moduleMember<MODULE_MEMBER, Members>*;
101101

102-
globalNamespaceDeclaration options { stubBase="FSharpDeclarationBase"; }:
102+
globalNamespaceDeclaration options { stubBase="NamedNamespaceDeclaration"; }:
103103
NAMESPACE<NAMESPACE, ModuleOrNamespaceKeyword>
104104
REC<REC, RecKeyword>?
105105
GLOBAL<GLOBAL, GlobalKeyword>

ReSharper.FSharp/src/FSharp.Psi/src/IFSharpElementFactory.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using FSharp.Compiler.Symbols;
33
using JetBrains.ReSharper.Plugins.FSharp.Psi.Tree;
4+
using JetBrains.ReSharper.Psi.Tree;
45
using Microsoft.FSharp.Collections;
56

67
namespace JetBrains.ReSharper.Plugins.FSharp.Psi
@@ -67,7 +68,7 @@ public interface IFSharpElementFactory
6768

6869
IFSharpFile CreateEmptyFile();
6970
INamedModuleDeclaration CreateModule(string name);
70-
INamedNamespaceDeclaration CreateNamespace(string name);
71+
INamespaceDeclaration CreateNamespace(string name);
7172
INestedModuleDeclaration CreateNestedModule(string name);
7273
}
7374
}
Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using JetBrains.Diagnostics;
2-
using JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing;
3-
using JetBrains.ReSharper.Plugins.FSharp.Psi.Tree;
1+
using JetBrains.ReSharper.Plugins.FSharp.Psi.Tree;
42
using JetBrains.ReSharper.Psi;
53
using JetBrains.ReSharper.Psi.ExtensionsAPI;
64

@@ -12,15 +10,6 @@ internal partial class GlobalNamespaceDeclaration
1210
public override IDeclaredElement DeclaredElement => null;
1311
public override string CompiledName => SharedImplUtil.MISSING_DECLARATION_NAME;
1412
public override IFSharpIdentifierLikeNode NameIdentifier => null;
15-
16-
public bool IsRecursive => RecKeyword != null;
17-
18-
public void SetIsRecursive(bool value)
19-
{
20-
if (!value)
21-
throw new System.NotImplementedException();
22-
23-
ModuleOrNamespaceKeyword.NotNull().AddTokenAfter(FSharpTokenType.REC);
24-
}
13+
public override string DeclaredName => "``global``";
2514
}
2615
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using JetBrains.ReSharper.Psi.Tree;
2+
3+
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
4+
{
5+
public partial interface IGlobalNamespaceDeclaration : INamespaceDeclaration
6+
{
7+
}
8+
}

ReSharper.FSharp/src/FSharp.Psi/src/Tree/IModuleLikeDeclaration.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
22
{
3+
// TODO: add triple slash comment.
4+
// this is either a namespace,module or nested module, global namespace, anon module
5+
// see inherits! (ctrl alt b)
36
public partial interface IModuleLikeDeclaration : IFSharpDeclaration
47
{
58
}

0 commit comments

Comments
 (0)