1
- namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.ContextActions
1
+ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features
2
2
3
- open System.IO
4
3
open System.Text
5
4
open FSharp.Compiler .Symbols
5
+ open JetBrains.ReSharper .Feature .Services .Generate
6
+ open JetBrains.ReSharper .Feature .Services .Generate .Workflows
7
+ open JetBrains.ReSharper .Plugins .FSharp .Psi
8
+ open JetBrains.ReSharper .Plugins .FSharp .Psi .Features .Generate
9
+ open JetBrains.ReSharper .Plugins .FSharp .Psi .Tree
10
+ open JetBrains.ReSharper .Psi .Transactions
11
+ open JetBrains.ReSharper .Psi .Tree
12
+ open JetBrains.ReSharper .Plugins .FSharp
13
+ open System.IO
6
14
open JetBrains.Application .UI .PopupLayout
7
15
open JetBrains.ReSharper .Feature .Services .Navigation
8
- open JetBrains.ReSharper .Psi .Naming
9
- open JetBrains.ReSharper .Psi .Tree
10
16
open JetBrains.DocumentManagers .Transactions .ProjectHostActions .Ordering
11
17
open JetBrains.ProjectModel .ProjectsHost
12
18
open JetBrains.RdBackend .Common .Features .ProjectModel
13
- open JetBrains.ReSharper .Feature .Services .ContextActions
14
- open JetBrains.ReSharper .Plugins .FSharp .Psi
15
- open JetBrains.ReSharper .Plugins .FSharp .Psi .Features .Intentions
16
- open JetBrains.ReSharper .Plugins .FSharp
17
- open JetBrains.ReSharper .Plugins .FSharp .Psi .Impl .Tree
18
- open JetBrains.ReSharper .Plugins .FSharp .Psi .Tree
19
19
open JetBrains.ReSharper .Psi
20
- open JetBrains.ReSharper .Psi .ExtensionsAPI .Tree
21
20
open JetBrains.ReSharper .Resources .Shell
21
+ open JetBrains.ReSharper .Feature .Services .Generate .Actions
22
+ open JetBrains.ReSharper .Feature .Services .Resources
23
+ open JetBrains.ReSharper .Psi .Naming
24
+ open JetBrains.ReSharper .Plugins .FSharp .Psi .Impl .Tree
25
+ open JetBrains.ReSharper .Psi .ExtensionsAPI .Tree
22
26
23
- // extract value -> ctrl alt v
24
- // undo that -> ctrl alt n
25
-
26
- // TODO: what about attributes, type parameters, delegates, exceptions
27
-
28
- // FSharpTokenType.AND.CreateLeafElement()
29
-
30
- [<ContextAction( Group = " F#" , Name = " Generate signature file for current file" , Priority = 1 s,
31
- Description = " Generate signature file for current file." ) >]
32
- type GenerateSignatureFileAction ( dataProvider : FSharpContextActionDataProvider ) =
33
- inherit FSharpContextActionBase( dataProvider)
34
-
27
+ module FSharpGeneratorKinds =
28
+ let [<Literal>] SignatureFile = " SignatureFile"
29
+
30
+ type FSharpGeneratorSignatureElement ( fsFile : IFSharpFile ) =
31
+ inherit GeneratorElementBase()
32
+
33
+ override this.GetPresentationObject () = fsFile
34
+ override this.Matches ( _searchText , matcher ) = matcher.Matches( this.TestDescriptor)
35
+ override this.TestDescriptor = " Generate signature file title" // fsFile.GetSourceFile().Name
36
+
37
+ interface IGeneratorElementPresenter with
38
+ member this.InitGeneratorPresenter ( presenter ) =
39
+ presenter.Present< FSharpGeneratorSignatureElement>( fun value item structureelement state ->
40
+ item.RichText <-
41
+ // Text seen in the popup of the selectable item.
42
+ JetBrains.UI.RichText.RichText( fsFile.GetSourceFile() .Name)
43
+ item.Images.Add( PsiServicesThemedIcons.HasImplementations.Id))
44
+
45
+ [<GeneratorElementProvider( FSharpGeneratorKinds.SignatureFile, typeof< FSharpLanguage>) >]
46
+ type FSharpGenerateSignatureProvider () =
47
+ inherit GeneratorProviderBase< FSharpGeneratorContext>()
48
+
49
+ override this.Populate ( context : FSharpGeneratorContext ): unit =
50
+ let node = context.Root :?> IFSharpTreeNode
51
+ context.ProvidedElements.Add( FSharpGeneratorSignatureElement( node.FSharpFile))
52
+
53
+ [<GeneratorBuilder( FSharpGeneratorKinds.SignatureFile, typeof< FSharpLanguage>) >]
54
+ type FSharpGenerateSignatureBuilder () =
55
+ inherit GeneratorBuilderBase< FSharpGeneratorContext>()
56
+
57
+ // TODO: what about attributes, type parameters, delegates, exceptions
58
+
35
59
let mkSignatureFile ( fsharpFile : IFSharpFile ): IFSharpFile =
36
60
let factory : IFSharpElementFactory = fsharpFile.CreateElementFactory( extension = FSharpSignatureProjectFileType.FsiExtension)
37
61
let signatureFile : IFSharpFile = factory.CreateEmptyFile()
@@ -174,26 +198,31 @@ type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider)
174
198
175
199
signatureFile
176
200
177
- override this.Text = " Generate signature file for current file"
178
-
179
- override this.IsAvailable _ =
180
- let solution = dataProvider.Solution
201
+ override this.IsAvailable ( context : FSharpGeneratorContext ): bool =
202
+ let node = context.Root :?> IFSharpTreeNode
203
+ let currentFSharpFile = node.FSharpFile
204
+ if currentFSharpFile.IsFSharpSigFile() then false else
205
+ let solution = node.GetSolution()
181
206
let isSettingEnabled = solution.IsFSharpExperimentalFeatureEnabled( ExperimentalFeature.GenerateSignatureFile)
182
207
if not isSettingEnabled then false else
183
- let currentFSharpFile = dataProvider.PsiFile
184
208
let fcsService = currentFSharpFile.FcsCheckerService
185
209
// TODO: don't check has pair in unit test
186
- let hasSignature = fcsService.FcsProjectProvider.HasPairFile dataProvider.SourceFile
210
+ let hasSignature = fcsService.FcsProjectProvider.HasPairFile ( node.GetSourceFile ())
187
211
not hasSignature
188
212
189
- override this.ExecutePsiTransaction ( solution , _ ) =
190
- let projectFile = dataProvider.SourceFile.ToProjectFile()
191
- let fsharpFile = projectFile.GetPrimaryPsiFile() .AsFSharpFile()
192
- let physicalPath = dataProvider.SourceFile.ToProjectFile() .Location.FileAccessPath
213
+ override this.Process ( context ) =
214
+ let node = context.Root :?> IFSharpTreeNode
215
+ use writeCookie = WriteLockCookie.Create( node.IsPhysical())
216
+ use transactionCookie =
217
+ PsiTransactionCookie.CreateAutoCommitCookieWithCachesUpdate( node.GetPsiServices(), FSharpGeneratorKinds.SignatureFile)
218
+
219
+ let currentFSharpFile = node.FSharpFile
220
+ let projectFile = node.GetSourceFile() .ToProjectFile()
221
+ let physicalPath = projectFile.Location.FileAccessPath
193
222
let fsiFile = Path.ChangeExtension( physicalPath, " .fsi" )
194
- let signatureFile = mkSignatureFile fsharpFile
223
+ let signatureFile = mkSignatureFile currentFSharpFile
195
224
File.WriteAllText( fsiFile, signatureFile.GetText())
196
-
225
+ let solution = node.GetSolution ()
197
226
solution.InvokeUnderTransaction( fun transactionCookie ->
198
227
let virtualPath = FileSystemPath.TryParse( fsiFile) .ToVirtualFileSystemPath()
199
228
let relativeTo = RelativeTo( projectFile, RelativeToType.Before)
@@ -210,8 +239,23 @@ type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider)
210
239
|> ignore
211
240
)
212
241
213
- null
214
-
215
- // First test name would be: ``ModuleStructure 01`` , ``NamespaceStructure 01``
216
-
217
- // TODO: raise parser issue.
242
+ type FSharpGenerateSignatureWorkflow () =
243
+ inherit GenerateCodeWorkflowBase(
244
+ FSharpGeneratorKinds.SignatureFile,
245
+ PsiServicesThemedIcons.Implements.Id,
246
+ // Seen in the dropdown menu when alt + insert is pressed.
247
+ " Generate signature file" ,
248
+ GenerateActionGroup.CLR_ LANGUAGE,
249
+ // Title of the window that opens up when the workflow is started.
250
+ " Generate signature file" ,
251
+ // Description of the window that opens up when the workflow is started.
252
+ $" Generate a signature file for the current file." ,
253
+ FSharpGeneratorKinds.SignatureFile)
254
+
255
+ override this.Order = 10. // See GeneratorStandardOrder.cs
256
+
257
+ [<GenerateProvider>]
258
+ type FSharpGenerateSignatureWorkflowProvider () =
259
+ interface IGenerateImplementationsWorkflowProvider with
260
+ member this.CreateWorkflow _ =
261
+ [| FSharpGenerateSignatureWorkflow() |]
0 commit comments