1
+ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.ContextActions
2
+
3
+ open System.IO
4
+ open JetBrains.ReSharper .Feature .Services .ContextActions
5
+ open JetBrains.ReSharper .Plugins .FSharp .Psi
6
+ open JetBrains.ReSharper .Plugins .FSharp .Psi .Features .Intentions
7
+ open type JetBrains.ReSharper .Psi .PsiSourceFileExtensions
8
+ open JetBrains.ReSharper .Plugins .FSharp
9
+ open JetBrains.ReSharper .Plugins .FSharp .Psi .Tree
10
+ open JetBrains.ReSharper .Psi
11
+ open JetBrains.ReSharper .Psi .ExtensionsAPI .Tree
12
+
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
+ }
25
+
26
+ [<ContextAction( Group = " F#" , Name = " Generate signature file for current file" , Priority = 1 s,
27
+ Description = " Generate signature file for current file." ) >]
28
+ type GenerateSignatureFileAction ( dataProvider : FSharpContextActionDataProvider ) =
29
+ inherit FSharpContextActionBase( dataProvider)
30
+
31
+ let mkSignatureFile ( fsharpFile : IFSharpFile ) : IFSharpFile =
32
+ let factory : IFSharpElementFactory = fsharpFile.CreateElementFactory()
33
+ 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
+ | _ -> ()
43
+
44
+ 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
+ | _ -> ()
55
+
56
+ signatureFile
57
+
58
+ override this.Text = " Generate signature file for current file"
59
+
60
+ override this.IsAvailable _ =
61
+ let solution = dataProvider.Solution
62
+ let isSettingEnabled = solution.IsFSharpExperimentalFeatureEnabled( ExperimentalFeature.GenerateSignatureFile)
63
+ if not isSettingEnabled then false else
64
+ let currentFSharpFile = dataProvider.PsiFile
65
+ let fcsService = currentFSharpFile.FcsCheckerService
66
+ let hasSignature = fcsService.FcsProjectProvider.HasPairFile dataProvider.SourceFile
67
+ not hasSignature
68
+
69
+ override this.ExecutePsiTransaction ( solution , _ ) =
70
+ let projectFile = dataProvider.SourceFile.ToProjectFile()
71
+ let fsharpFile = projectFile.GetPrimaryPsiFile() .AsFSharpFile()
72
+ let physicalPath = dataProvider.SourceFile.ToProjectFile() .Location.FileAccessPath
73
+ let fsiFile = Path.ChangeExtension( physicalPath, " .fsi" )
74
+
75
+ 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
+ // ()
93
+
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)
99
+
100
+ null
0 commit comments