Repository navigation
Add Convert closure to function code action #2519
Description
Activity
I'm not sure we often see this pattern
let closure = { ... } use(closure)
But obviously we often see
use { ... }
which can be rewritten
func operation(...) { ... } use(operation) // where 'operation' is a parameter name in `use(_:)`
The implementation should check the exact type of the closure and the desired function name (variable name or parameter name).
Hello, I’d love to take a crack at this as my first contribution to sourcekit-lsp. I have gone through the rust-analyser, and also the swift example, I got the idea here.
Would it be alright if I start working on this ?
@ahoppen Can you please let me know where should I start looking into for reference, or anything of sorts that can guide me ?Great to hear that you’re interested, @BoseSj.
The most similar code action is
ConvertComputedPropertyToStored, which you could use as reference: Both need to infer the type of a variable (or parameters in the case of this refactoring) using cursor info. You should be able to follow that as a blueprint.Reacted by SJ BasakHello, its been some time. Among other stuffs, I have dived into swift-syntax apis and existing similar refactoring actions for reference.
As of now, my flow in following:- Detecting Functionc all expressions
- Detecting trailing Closure expression
- Get parameter names and types for ClosureParameterList, eg. ... (num: Int, decinum: Float) in ...
- Get parameter names and types for ClosureShorthandParameterList, eg. ... num, decinum in ...
As I have been experimenting before actually implementing the action. I have not been able to get the type for
ClosureShorthandParameterListSyntax, any idea on that ? @ahoppenSo as of now I have been able to do the following kind of transformation
For
ClosureParameterClauseSyntaxOriginal
dosome { (num: Int, decinum: Float) -> Void in return "Hello: \(num)" }Generated
func <#name#>(num: Int, decinum: Float) -> Void { return "Hello: \(num)" }For
ClosureShorthandParameterListSyntaxOriginal
dosome { num, decinum in let val = "Hello: \(num)" return val }Generated
func <#name#>(num: <#Type#>, decinum : <#Type#>) -> <#returnType#> { let val = "Hello: \(num)" return val }@Tabonx are these looking closer to expectation ?
@ahoppen a little help there for the
ClosureShorthandParameterListSyntaxcase,, I am a little stuck there.@BoseSj thanks for tackling this and sorry for the delayed reply. In case the closure’s parameter list doesn’t specify any types, you should be able to run a cursor info request to retrieve it. For example, look at how we resole the type of a variable here:
sourcekit-lsp/Sources/SwiftSyntaxCodeActions/ConvertStoredPropertyToComputed.swift
Line 75 in 46d33b1
guard let symbolInfo = try await symbolInfo(data.position).only, let typeName = symbolInfo.typeName, typeName != "_" Reacted by SJ Basak
Description
Convert a closure to a named nested function, turning captures into parameters.
Before:
After:
See also: rust-analyzer
convert_closure_to_fn