Add 'Extract tuple into struct' code action#2719
Open
krishnapermi wants to merge 2 commits into
Open
Conversation
This source file implements a syntactic code action that extracts a named tuple type into a named struct in Swift. It includes methods to find the tuple type, determine the insertion point for the new struct, and derive a suitable struct name based on the context.
krishnapermi
requested review from
ahoppen,
hamishknight and
rintaro
as code owners
July 14, 2026 07:04
ahoppen
reviewed
Jul 16, 2026
ahoppen
left a comment
Member
There was a problem hiding this comment.
Some initial comments. Could you also add test cases for this?
| /// return ("Alice", 30, "alice@example.com") | ||
| /// } | ||
| /// ``` | ||
| struct ExtractTupleIntoStruct: SyntaxCodeActionProvider { |
Member
There was a problem hiding this comment.
Could you implement this in terms of SyntaxRefactoringCodeActionProvider?
|
|
||
| let structName = deriveStructName(for: tupleType) | ||
|
|
||
| // Match the indentation style of the surrounding source. |
Member
There was a problem hiding this comment.
I don’t think this comment provides significant value as it just describes what the code below already clearly states. Please remove such comments.
| // trailing blank line and indentation to restore spacing before the | ||
| // original declaration. | ||
| let insertPos = enclosingDecl.positionAfterSkippingLeadingTrivia | ||
| let structText = "struct \(structName) {\n\(fields)\n\(baseIndent)}\n\n\(baseIndent)" |
Member
There was a problem hiding this comment.
This would read nicer as a multi-line string literal
| /// immediately before it, either at the top level of a function body or as a | ||
| /// nested member of a type. | ||
| private func findEnclosingInsertionPoint(of node: Syntax) -> DeclSyntax? { | ||
| var current: Syntax? = node |
Member
There was a problem hiding this comment.
Can’t you use findParentOfSelf here instead of walking the tree manually?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the "Extract tuple into struct" code action requested in #2511.
When the cursor is on a named tuple type — one where every element has a label — a new code action appears in the lightbulb menu. It generates a
structwith matching stored properties immediately before the enclosing declaration and replaces the tuple type annotation with the new struct name.Before:
After:
The struct name is inferred from context:
<FunctionName>Result(e.g.getUser→GetUserResult)Indentation is matched to the surrounding source using
BasicFormat.inferIndentation.Scope: This is the syntactic-only step discussed in #2511 — only the local type annotation is rewritten. Renaming call sites that construct or destructure the tuple is left to a follow-up rename refactoring (the pattern @ahoppen described as an acceptable first step).
What doesn't trigger it: unlabelled tuples, single-element tuples, and tuples with
_wildcard labels, since none of those produce clean property names.Resolves #2511.