[IDE] Use Identifier for printing member name in generateMemberwiseInit

Avoid relying on the source text and print the identifier, escaping
if needed.
This commit is contained in:
Hamish Knight
2025-11-13 11:54:26 +00:00
parent 442a11bb0d
commit 01b965fe3c
5 changed files with 28 additions and 15 deletions

View File

@@ -16,15 +16,23 @@ using namespace swift::refactoring;
namespace { namespace {
struct MemberwiseParameter { struct MemberwiseParameter {
CharSourceRange NameRange; Identifier Name;
Type MemberType; Type MemberType;
Expr *DefaultExpr; Expr *DefaultExpr;
MemberwiseParameter(CharSourceRange nameRange, Type type, Expr *initialExpr) MemberwiseParameter(Identifier name, Type type, Expr *initialExpr)
: NameRange(nameRange), MemberType(type), DefaultExpr(initialExpr) {} : Name(name), MemberType(type), DefaultExpr(initialExpr) {}
}; };
} // namespace } // namespace
static void printMemberName(Identifier name, llvm::raw_ostream &OS) {
if (escapeIdentifierInContext(name, PrintNameContext::TypeMember)) {
OS << '`' << name << '`';
} else {
OS << name;
}
}
static void generateMemberwiseInit(SourceEditConsumer &EditConsumer, static void generateMemberwiseInit(SourceEditConsumer &EditConsumer,
SourceManager &SM, SourceManager &SM,
ArrayRef<MemberwiseParameter> memberVector, ArrayRef<MemberwiseParameter> memberVector,
@@ -34,7 +42,8 @@ static void generateMemberwiseInit(SourceEditConsumer &EditConsumer,
auto insertMember = [&SM](const MemberwiseParameter &memberData, auto insertMember = [&SM](const MemberwiseParameter &memberData,
raw_ostream &OS, bool wantsSeparator) { raw_ostream &OS, bool wantsSeparator) {
{ {
OS << SM.extractText(memberData.NameRange) << ": "; printMemberName(memberData.Name, OS);
OS << ": ";
// Unconditionally print '@escaping' if we print out a function type - // Unconditionally print '@escaping' if we print out a function type -
// the assignments we generate below will escape this parameter. // the assignments we generate below will escape this parameter.
if (isa<AnyFunctionType>(memberData.MemberType->getCanonicalType())) { if (isa<AnyFunctionType>(memberData.MemberType->getCanonicalType())) {
@@ -73,8 +82,11 @@ static void generateMemberwiseInit(SourceEditConsumer &EditConsumer,
OS << ") {\n"; OS << ") {\n";
for (auto &member : memberVector) { for (auto &member : memberVector) {
// self.<property> = <property> // self.<property> = <property>
auto name = SM.extractText(member.NameRange); OS << "self.";
OS << "self." << name << " = " << name << "\n"; printMemberName(member.Name, OS);
OS << " = ";
printMemberName(member.Name, OS);
OS << "\n";
} }
OS << "}\n"; OS << "}\n";
@@ -104,8 +116,6 @@ collectMembersForInit(ResolvedCursorInfoPtr CursorInfo,
if (!targetLocation.isValid()) if (!targetLocation.isValid())
return SourceLoc(); return SourceLoc();
SourceManager &SM = nominalDecl->getASTContext().SourceMgr;
for (auto member : nominalDecl->getMemberwiseInitProperties()) { for (auto member : nominalDecl->getMemberwiseInitProperties()) {
auto varDecl = dyn_cast<VarDecl>(member); auto varDecl = dyn_cast<VarDecl>(member);
if (!varDecl) { if (!varDecl) {
@@ -130,9 +140,7 @@ collectMembersForInit(ResolvedCursorInfoPtr CursorInfo,
defaultInit = patternBinding->getOriginalInit(i); defaultInit = patternBinding->getOriginalInit(i);
} }
auto NameRange = memberVector.emplace_back(varDecl->getName(), varDecl->getTypeInContext(),
Lexer::getCharSourceRangeFromSourceRange(SM, varDecl->getNameLoc());
memberVector.emplace_back(NameRange, varDecl->getTypeInContext(),
defaultInit); defaultInit);
} }

View File

@@ -44,6 +44,7 @@ struct Place {
let callback: Callback let callback: Callback
@MyWrapper var wrapped: String @MyWrapper var wrapped: String
var `protocol`: String var `protocol`: String
var `some raw identifier`: Int
} }
protocol Thing { protocol Thing {

View File

@@ -31,6 +31,7 @@ struct Place {
let callback: Callback let callback: Callback
@MyWrapper var wrapped: String @MyWrapper var wrapped: String
var `protocol`: String var `protocol`: String
var `some raw identifier`: Int
} }
protocol Thing { protocol Thing {

View File

@@ -20,7 +20,7 @@ class Person {
} }
struct Place { struct Place {
internal init(person: Person, street: String, apartment: Optional<String> = nil, city: String, state: String, postalCode: Int, plusFour: Int? = nil, callback: @escaping Place.Callback, wrapped: String, `protocol`: String) { internal init(person: Person, street: String, apartment: Optional<String> = nil, city: String, state: String, postalCode: Int, plusFour: Int? = nil, callback: @escaping Place.Callback, wrapped: String, `protocol`: String, `some raw identifier`: Int) {
self.person = person self.person = person
self.street = street self.street = street
self.apartment = apartment self.apartment = apartment
@@ -31,6 +31,7 @@ self.plusFour = plusFour
self.callback = callback self.callback = callback
self.wrapped = wrapped self.wrapped = wrapped
self.`protocol` = `protocol` self.`protocol` = `protocol`
self.`some raw identifier` = `some raw identifier`
} }
typealias Callback = () -> () typealias Callback = () -> ()
@@ -44,6 +45,7 @@ self.`protocol` = `protocol`
let callback: Callback let callback: Callback
@MyWrapper var wrapped: String @MyWrapper var wrapped: String
var `protocol`: String var `protocol`: String
var `some raw identifier`: Int
} }
protocol Thing { protocol Thing {

View File

@@ -31,6 +31,7 @@ struct Place {
let callback: Callback let callback: Callback
@MyWrapper var wrapped: String @MyWrapper var wrapped: String
var `protocol`: String var `protocol`: String
var `some raw identifier`: Int
} }
protocol Thing { protocol Thing {
@@ -58,9 +59,9 @@ struct MyWrapper {
// RUN: %refactor -memberwise-init -source-filename %s -pos=22:8 > %t.result/struct_members.swift // RUN: %refactor -memberwise-init -source-filename %s -pos=22:8 > %t.result/struct_members.swift
// RUN: diff -u %S/Outputs/generate_memberwise/struct_members.swift.expected %t.result/struct_members.swift // RUN: diff -u %S/Outputs/generate_memberwise/struct_members.swift.expected %t.result/struct_members.swift
// RUN: %refactor -memberwise-init -source-filename %s -pos=44:8 > %t.result/only_computed_members.swift // RUN: %refactor -memberwise-init -source-filename %s -pos=45:8 > %t.result/only_computed_members.swift
// RUN: diff -u %S/Outputs/generate_memberwise/only_computed_members.swift.expected %t.result/only_computed_members.swift // RUN: diff -u %S/Outputs/generate_memberwise/only_computed_members.swift.expected %t.result/only_computed_members.swift
// RUN: not %refactor -memberwise-init -source-filename %s -pos=36:10 > %t.result/protocol_members.swift // RUN: not %refactor -memberwise-init -source-filename %s -pos=37:10 > %t.result/protocol_members.swift
// RUN: not %refactor -memberwise-init -source-filename %s -pos=40:6 > %t.result/enum_members.swift // RUN: not %refactor -memberwise-init -source-filename %s -pos=41:6 > %t.result/enum_members.swift