Skip to content

Commit 90cdf95

Browse files
committed
Refactor TypeDeclarationGroup grouping. Take care of the and keyword.
1 parent 90876d6 commit 90cdf95

File tree

1 file changed

+63
-76
lines changed

1 file changed

+63
-76
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.ContextActions
22

33
open System.IO
4-
open System.Linq
54
open System.Text
65
open FSharp.Compiler.Symbols
76
open JetBrains.Application.UI.PopupLayout
87
open JetBrains.ReSharper.Feature.Services.Navigation
9-
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
108
open JetBrains.ReSharper.Psi.Naming
119
open JetBrains.ReSharper.Psi.Tree
1210
open JetBrains.DocumentManagers.Transactions.ProjectHostActions.Ordering
@@ -34,7 +32,7 @@ open JetBrains.ReSharper.Resources.Shell
3432
type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider) =
3533
inherit FSharpContextActionBase(dataProvider)
3634

37-
let mkSignatureFile (fsharpFile: IFSharpFile) : IFSharpFile =
35+
let mkSignatureFile (fsharpFile: IFSharpFile): IFSharpFile =
3836
let factory : IFSharpElementFactory = fsharpFile.CreateElementFactory(extension = FSharpSignatureProjectFileType.FsiExtension)
3937
let signatureFile : IFSharpFile = factory.CreateEmptyFile()
4038
let lineEnding = fsharpFile.GetLineEnding()
@@ -43,72 +41,62 @@ type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider)
4341
let rec createModuleMemberSig (indentation: int) (moduleDecl: IModuleLikeDeclaration) (moduleMember: IModuleMember) : IFSharpTreeNode =
4442
match moduleMember with
4543
| :? ITypeDeclarationGroup as typeGroup ->
46-
let sigTypeDeclGroups =
47-
// TODO: Update type into and keyword for second IFSharpTypeDeclaration in a group.
48-
44+
// Filter out the IFSharpTypeDeclaration where we support the TypeRepresentation for now.
45+
let supportedTypeDeclarations =
4946
typeGroup.TypeDeclarations
5047
|> Seq.choose (function
5148
| :? IFSharpTypeDeclaration as typeDecl ->
52-
// TODO: update and keyword
53-
(*
54-
ModificationUtil.ReplaceChild(
55-
sigTypeGroup.TypeDeclarations.[1].TypeKeyword,
56-
(FSharpTokenType.AND.CreateLeafElement()))
57-
*)
58-
59-
// Resharper implementation
60-
//typeDecl.MemberDeclarations
61-
62-
// Untyped tree like
63-
// typeDecl.TypeMembers
64-
let sigMembers =
65-
typeDecl.TypeMembers
66-
|> Seq.choose (createMemberDeclaration >> Option.ofObj)
67-
6849
match typeDecl.TypeRepresentation with
69-
// TODO: checkout delegates
70-
| :? ITypeAbbreviationRepresentation as abbr ->
71-
let sigTypeGroup = factory.CreateModuleMember($"type {getName typeDecl} = int")
72-
match sigTypeGroup with
73-
| :? ITypeDeclarationGroup as sigTypeGroup ->
74-
let sigDecl = sigTypeGroup.TypeDeclarations.[0] :?> IFSharpTypeDeclaration
75-
76-
77-
78-
ModificationUtil.DeleteChildRange(sigDecl.EqualsToken.NextSibling, sigDecl.LastChild)
79-
addNodesAfter sigDecl.EqualsToken [
80-
Whitespace()
81-
abbr.Copy()
82-
]
83-
|> ignore
84-
Some sigTypeGroup
85-
| _ -> None
86-
| :? ISimpleTypeRepresentation as repr ->
87-
let sigTypeGroup = factory.CreateModuleMember($"type {getName typeDecl} = int")
88-
match sigTypeGroup with
89-
| :? ITypeDeclarationGroup as sigTypeGroup ->
90-
let sigDecl = sigTypeGroup.TypeDeclarations.[0] :?> IFSharpTypeDeclaration
91-
ModificationUtil.DeleteChildRange(sigDecl.EqualsToken.NextSibling, sigDecl.LastChild)
92-
addNodesAfter sigDecl.EqualsToken [
93-
NewLine(lineEnding)
94-
Whitespace(indentation + moduleDecl.GetIndentSize())
95-
repr.Copy()
96-
for sigMember in sigMembers do
97-
NewLine(lineEnding)
98-
Whitespace(indentation + moduleDecl.GetIndentSize())
99-
sigMember
100-
]
101-
|> ignore
102-
Some sigTypeGroup
103-
| _ -> None
50+
| :? ITypeAbbreviationRepresentation
51+
| :? ISimpleTypeRepresentation -> Some typeDecl
10452
| _ -> None
105-
106-
107-
108-
| _ -> None) // TODO: address this
109-
110-
sigTypeDeclGroups.FirstOrDefault()
111-
// TODO : ITypeExtensionDeclaration
53+
| _ -> None)
54+
|> Seq.mapi (fun idx typeDecl ->
55+
let kw = if idx = 0 then "type" else "and"
56+
{| SignatureIdx = idx ; TypeDeclaration = typeDecl; SourceText = $"{kw} {getName typeDecl} = int" |})
57+
|> Seq.toArray
58+
59+
if Array.isEmpty supportedTypeDeclarations then null else
60+
61+
let sourceText = supportedTypeDeclarations |> Array.map (fun info -> info.SourceText) |> String.concat "\n"
62+
let sigTypeDeclarationGroup = factory.CreateModuleMember(sourceText) :?> ITypeDeclarationGroup
63+
64+
if isNull sigTypeDeclarationGroup then null else
65+
66+
for info in supportedTypeDeclarations do
67+
let typeDecl: IFSharpTypeDeclaration = info.TypeDeclaration
68+
let sigTypeDecl = sigTypeDeclarationGroup.TypeDeclarations.[info.SignatureIdx] :?> IFSharpTypeDeclaration
69+
if isNull sigTypeDecl then () else
70+
71+
let sigMembers =
72+
typeDecl.TypeMembers
73+
|> Seq.choose (createMemberDeclaration >> Option.ofObj)
74+
75+
match typeDecl.TypeRepresentation with
76+
| :? ITypeAbbreviationRepresentation as abbr ->
77+
ModificationUtil.DeleteChildRange(sigTypeDecl.EqualsToken.NextSibling, sigTypeDecl.LastChild)
78+
addNodesAfter sigTypeDecl.EqualsToken [
79+
Whitespace()
80+
abbr.Copy()
81+
// TODO: there technically could be members here.
82+
// Although I think this would need the `with` keyword.
83+
] |> ignore
84+
| :? ISimpleTypeRepresentation as repr ->
85+
ModificationUtil.DeleteChildRange(sigTypeDecl.EqualsToken.NextSibling, sigTypeDecl.LastChild)
86+
addNodesAfter sigTypeDecl.EqualsToken [
87+
NewLine(lineEnding)
88+
Whitespace(indentation + moduleDecl.GetIndentSize())
89+
repr.Copy()
90+
for sigMember in sigMembers do
91+
NewLine(lineEnding)
92+
Whitespace(indentation + moduleDecl.GetIndentSize())
93+
sigMember
94+
] |> ignore
95+
| repr ->
96+
// This pattern match should match the types we filtered out earlier for supportedTypeDeclarations
97+
failwith $"Unexpected representation {repr.GetType()}"
98+
99+
sigTypeDeclarationGroup
112100

113101
| :? INestedModuleDeclaration as nestedNestedModule ->
114102
let nestedSigModule = factory.CreateNestedModule(nestedNestedModule.NameIdentifier.Name)
@@ -127,7 +115,7 @@ type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider)
127115
and processModuleLikeDeclaration (indentation: int) (moduleDecl: IModuleLikeDeclaration) (moduleSig: IModuleLikeDeclaration) : IFSharpTreeNode =
128116
for moduleMember in moduleDecl.Members do
129117
let signatureMember = createModuleMemberSig indentation moduleDecl moduleMember
130-
118+
131119
if isNotNull signatureMember then
132120
// newline + indentation whitespace
133121
addNodesAfter moduleSig.LastChild [
@@ -155,19 +143,18 @@ type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider)
155143
sb.Append(memberDecl.AccessModifier.GetText()) |> ignore
156144

157145
sb.Append(getName memberDecl) |> ignore
158-
sb.Append(": ") |> ignore
159-
146+
sb.Append(": ") |> ignore
147+
160148
let symbolUse = memberDecl.GetFcsSymbolUse()
161149
if isNotNull symbolUse then
162150
let mfv = symbolUse.Symbol.As<FSharpMemberOrFunctionOrValue>()
163151
if isNotNull mfv then
164152
sb.Append(mfv.FullType.Format(symbolUse.DisplayContext)) |> ignore
165-
153+
166154
sb.ToString()
167155

168156
factory.CreateTypeMemberSignature(sourceString)
169157
| _ -> null
170-
171158

172159
for decl in fsharpFile.ModuleDeclarations do
173160
let signatureModule : IModuleLikeDeclaration =
@@ -182,13 +169,13 @@ type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider)
182169
| decl -> failwithf $"Unexpected declaration, got: %A{decl}"
183170

184171
ModificationUtil.AddChildAfter(signatureModule.LastChild, NewLine(lineEnding)) |> ignore
185-
let signatureModule = processModuleLikeDeclaration 0 decl signatureModule
172+
let signatureModule = processModuleLikeDeclaration 0 decl signatureModule
186173
ModificationUtil.AddChild(signatureFile, signatureModule) |> ignore
187174

188175
signatureFile
189176

190177
override this.Text = "Generate signature file for current file"
191-
178+
192179
override this.IsAvailable _ =
193180
let solution = dataProvider.Solution
194181
let isSettingEnabled = solution.IsFSharpExperimentalFeatureEnabled(ExperimentalFeature.GenerateSignatureFile)
@@ -198,7 +185,7 @@ type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider)
198185
// TODO: don't check has pair in unit test
199186
let hasSignature = fcsService.FcsProjectProvider.HasPairFile dataProvider.SourceFile
200187
not hasSignature
201-
188+
202189
override this.ExecutePsiTransaction(solution, _) =
203190
let projectFile = dataProvider.SourceFile.ToProjectFile()
204191
let fsharpFile = projectFile.GetPrimaryPsiFile().AsFSharpFile()
@@ -211,7 +198,7 @@ type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider)
211198
let virtualPath = FileSystemPath.TryParse(fsiFile).ToVirtualFileSystemPath()
212199
let relativeTo = RelativeTo(projectFile, RelativeToType.Before)
213200
let projectFile = transactionCookie.AddFile(projectFile.ParentFolder, virtualPath, context = OrderingContext(relativeTo))
214-
201+
215202
if (not Shell.Instance.IsTestShell) then
216203
let navigationOptions = NavigationOptions.FromWindowContext(Shell.Instance.GetComponent<IMainWindowPopupWindowContext>().Source, "")
217204
NavigationManager
@@ -224,7 +211,7 @@ type GenerateSignatureFileAction(dataProvider: FSharpContextActionDataProvider)
224211
)
225212

226213
null
227-
214+
228215
// First test name would be: ``ModuleStructure 01`` , ``NamespaceStructure 01``
229-
230-
// TODO: raise parser issue.
216+
217+
// TODO: raise parser issue.

0 commit comments

Comments
 (0)