Skip to content

Commit bff3f8a

Browse files
authored
Merge pull request #16983 from mohitathwani/SR-7292
[WIP] Generating member wise initializer with local refactoring
2 parents b83da60 + ce11229 commit bff3f8a

File tree

6 files changed

+146
-1
lines changed

6 files changed

+146
-1
lines changed

include/swift/IDE/RefactoringKinds.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ CURSOR_REFACTORING(ConvertToDoCatch, "Convert To Do/Catch", convert.do.catch)
5050

5151
CURSOR_REFACTORING(TrailingClosure, "Convert To Trailing Closure", trailingclosure)
5252

53+
CURSOR_REFACTORING(MemberwiseInitLocalRefactoring, "Generate Memberwise Initializer", memberwise.init.local.refactoring)
54+
5355
RANGE_REFACTORING(ExtractExpr, "Extract Expression", extract.expr)
5456

5557
RANGE_REFACTORING(ExtractFunction, "Extract Method", extract.function)

lib/IDE/Refactoring.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,6 +2571,110 @@ bool RefactoringActionLocalizeString::performChange() {
25712571
return false;
25722572
}
25732573

2574+
static void generateMemberwiseInit(SourceEditConsumer &EditConsumer,
2575+
SourceManager &SM,
2576+
SmallVectorImpl<std::string>& memberNameVector,
2577+
SmallVectorImpl<std::string>& memberTypeVector,
2578+
SourceLoc targetLocation) {
2579+
2580+
assert(!memberTypeVector.empty());
2581+
assert(memberTypeVector.size() == memberNameVector.size());
2582+
2583+
EditConsumer.accept(SM, targetLocation, "\ninternal init(");
2584+
2585+
for (size_t i = 0, n = memberTypeVector.size(); i < n ; i++) {
2586+
EditConsumer.accept(SM, targetLocation, memberNameVector[i] + ": " +
2587+
memberTypeVector[i]);
2588+
2589+
if (i != memberTypeVector.size() - 1) {
2590+
EditConsumer.accept(SM, targetLocation, ", ");
2591+
}
2592+
}
2593+
2594+
EditConsumer.accept(SM, targetLocation, ") {\n");
2595+
2596+
for (auto varName: memberNameVector) {
2597+
EditConsumer.accept(SM, targetLocation,
2598+
"self." + varName + " = " + varName + "\n");
2599+
}
2600+
2601+
EditConsumer.accept(SM, targetLocation, "}\n");
2602+
}
2603+
2604+
static SourceLoc collectMembersForInit(ResolvedCursorInfo CursorInfo,
2605+
SmallVectorImpl<std::string>& memberNameVector,
2606+
SmallVectorImpl<std::string>& memberTypeVector) {
2607+
2608+
if (!CursorInfo.ValueD)
2609+
return SourceLoc();
2610+
2611+
ClassDecl *classDecl = dyn_cast<ClassDecl>(CursorInfo.ValueD);
2612+
if (!classDecl || classDecl->getStoredProperties().empty() ||
2613+
CursorInfo.IsRef) {
2614+
return SourceLoc();
2615+
}
2616+
2617+
SourceLoc bracesStart = classDecl->getBraces().Start;
2618+
if (!bracesStart.isValid())
2619+
return SourceLoc();
2620+
2621+
SourceLoc targetLocation = bracesStart.getAdvancedLoc(1);
2622+
if (!targetLocation.isValid())
2623+
return SourceLoc();
2624+
2625+
for (auto varDecl : classDecl->getStoredProperties()) {
2626+
auto parentPatternBinding = varDecl->getParentPatternBinding();
2627+
if (!parentPatternBinding)
2628+
continue;
2629+
2630+
auto varDeclIndex =
2631+
parentPatternBinding->getPatternEntryIndexForVarDecl(varDecl);
2632+
2633+
if (auto init = varDecl->getParentPatternBinding()->getInit(varDeclIndex)) {
2634+
if (init->getStartLoc().isValid())
2635+
continue;
2636+
}
2637+
2638+
StringRef memberName = varDecl->getName().str();
2639+
memberNameVector.push_back(memberName.str());
2640+
2641+
std::string memberType = varDecl->getType().getString();
2642+
memberTypeVector.push_back(memberType);
2643+
}
2644+
2645+
if (memberNameVector.empty() || memberTypeVector.empty()) {
2646+
return SourceLoc();
2647+
}
2648+
2649+
return targetLocation;
2650+
}
2651+
2652+
bool RefactoringActionMemberwiseInitLocalRefactoring::
2653+
isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
2654+
2655+
SmallVector<std::string, 8> memberNameVector;
2656+
SmallVector<std::string, 8> memberTypeVector;
2657+
2658+
return collectMembersForInit(Tok, memberNameVector,
2659+
memberTypeVector).isValid();
2660+
}
2661+
2662+
bool RefactoringActionMemberwiseInitLocalRefactoring::performChange() {
2663+
2664+
SmallVector<std::string, 8> memberNameVector;
2665+
SmallVector<std::string, 8> memberTypeVector;
2666+
2667+
SourceLoc targetLocation = collectMembersForInit(CursorInfo, memberNameVector,
2668+
memberTypeVector);
2669+
if (targetLocation.isInvalid())
2670+
return true;
2671+
2672+
generateMemberwiseInit(EditConsumer, SM, memberNameVector,
2673+
memberTypeVector, targetLocation);
2674+
2675+
return false;
2676+
}
2677+
25742678
static CharSourceRange
25752679
findSourceRangeToWrapInCatch(ResolvedCursorInfo CursorInfo,
25762680
SourceFile *TheFile,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class Person {
2+
internal init(firstName: String?, lastName: String?, age: Int?) {
3+
self.firstName = firstName
4+
self.lastName = lastName
5+
self.age = age
6+
}
7+
8+
var firstName: String!
9+
var lastName: String!
10+
var age: Int!
11+
var planet = "Earth", solarSystem = "Milky Way"
12+
var avgHeight = 175
13+
}
14+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Person {
2+
var firstName: String!
3+
var lastName: String!
4+
var age: Int!
5+
var planet = "Earth", solarSystem = "Milky Way"
6+
var avgHeight = 175
7+
}
8+
9+
// RUN: %empty-directory(%t.result)
10+
// RUN: %refactor -memberwise-init -source-filename %s -pos=1:8 > %t.result/class_members.swift
11+
// RUN: diff -u %S/Outputs/class_members/class_members.swift.expected %t.result/class_members.swift
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class Person {
2+
var firstName: String!
3+
var lastName: String!
4+
var age: Int!
5+
var planet = "Earth", solarSystem = "Milky Way"
6+
var avgHeight = 175
7+
}
8+
9+
let _ = Person()
10+
11+
// RUN: %refactor -source-filename %s -pos=9:10 | %FileCheck %s -check-prefix=CHECK-NONE
12+
// CHECK-NONE: Action begins
13+
// CHECK-NONE-NEXT: Action ends

tools/swift-refactor/swift-refactor.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ Action(llvm::cl::desc("kind:"), llvm::cl::init(RefactoringKind::None),
6666
clEnumValN(RefactoringKind::TrailingClosure,
6767
"trailingclosure", "Perform trailing closure refactoring"),
6868
clEnumValN(RefactoringKind::ReplaceBodiesWithFatalError,
69-
"replace-bodies-with-fatalError", "Perform trailing closure refactoring")));
69+
"replace-bodies-with-fatalError", "Perform trailing closure refactoring"),
70+
clEnumValN(RefactoringKind::MemberwiseInitLocalRefactoring, "memberwise-init", "Generate member wise initializer")));
7071

7172

7273
static llvm::cl::opt<std::string>

0 commit comments

Comments
 (0)