@@ -2752,78 +2752,107 @@ bool RefactoringActionLocalizeString::performChange() {
2752
2752
return false ;
2753
2753
}
2754
2754
2755
+ struct MemberwiseParameter {
2756
+ Identifier Name;
2757
+ Type MemberType;
2758
+ Expr *DefaultExpr;
2759
+
2760
+ MemberwiseParameter (Identifier name, Type type, Expr *initialExpr)
2761
+ : Name(name), MemberType(type), DefaultExpr(initialExpr) {}
2762
+ };
2763
+
2755
2764
static void generateMemberwiseInit (SourceEditConsumer &EditConsumer,
2756
- SourceManager &SM,
2757
- SmallVectorImpl<std::string>& memberNameVector,
2758
- SmallVectorImpl<std::string>& memberTypeVector,
2759
- SourceLoc targetLocation) {
2760
-
2761
- assert (!memberTypeVector.empty ());
2762
- assert (memberTypeVector.size () == memberNameVector.size ());
2765
+ SourceManager &SM,
2766
+ ArrayRef<MemberwiseParameter> memberVector,
2767
+ SourceLoc targetLocation) {
2763
2768
2769
+ assert (!memberVector.empty ());
2770
+
2764
2771
EditConsumer.accept (SM, targetLocation, " \n internal init(" );
2765
-
2766
- for (size_t i = 0 , n = memberTypeVector.size (); i < n ; i++) {
2767
- EditConsumer.accept (SM, targetLocation, memberNameVector[i] + " : " +
2768
- memberTypeVector[i]);
2769
-
2770
- if (i != memberTypeVector.size () - 1 ) {
2771
- EditConsumer.accept (SM, targetLocation, " , " );
2772
+ auto insertMember = [&SM](const MemberwiseParameter &memberData,
2773
+ llvm::raw_ostream &OS, bool wantsSeparator) {
2774
+ OS << memberData.Name << " : " << memberData.MemberType .getString ();
2775
+ if (auto *expr = memberData.DefaultExpr ) {
2776
+ if (isa<NilLiteralExpr>(expr)) {
2777
+ OS << " = nil" ;
2778
+ } else if (expr->getSourceRange ().isValid ()) {
2779
+ auto range =
2780
+ Lexer::getCharSourceRangeFromSourceRange (
2781
+ SM, expr->getSourceRange ());
2782
+ OS << " = " << SM.extractText (range);
2783
+ }
2784
+ }
2785
+
2786
+ if (wantsSeparator) {
2787
+ OS << " , " ;
2772
2788
}
2789
+ };
2790
+
2791
+ // Process the initial list of members, inserting commas as appropriate.
2792
+ std::string Buffer;
2793
+ llvm::raw_string_ostream OS (Buffer);
2794
+ for (const auto &memberData : memberVector.drop_back ()) {
2795
+ insertMember (memberData, OS, /* wantsSeparator*/ true );
2773
2796
}
2774
-
2775
- EditConsumer.accept (SM, targetLocation, " ) {\n " );
2776
-
2777
- for (auto varName: memberNameVector) {
2778
- EditConsumer.accept (SM, targetLocation,
2779
- " self." + varName + " = " + varName + " \n " );
2797
+
2798
+ // Process the last (or perhaps, only) member.
2799
+ insertMember (memberVector.back (), OS, /* wantsSeparator*/ false );
2800
+
2801
+ // Synthesize the body.
2802
+ OS << " ) {\n " ;
2803
+ for (auto &member : memberVector) {
2804
+ // self.<property> = <property>
2805
+ OS << " self." << member.Name << " = " << member.Name << " \n " ;
2780
2806
}
2781
-
2782
- EditConsumer.accept (SM, targetLocation, " }\n " );
2807
+ OS << " }\n " ;
2808
+
2809
+ // Accept the entire edit.
2810
+ EditConsumer.accept (SM, targetLocation, OS.str ());
2783
2811
}
2784
-
2785
- static SourceLoc collectMembersForInit (ResolvedCursorInfo CursorInfo,
2786
- SmallVectorImpl<std::string>& memberNameVector ,
2787
- SmallVectorImpl<std::string>& memberTypeVector ) {
2788
-
2812
+
2813
+ static SourceLoc
2814
+ collectMembersForInit (ResolvedCursorInfo CursorInfo ,
2815
+ SmallVectorImpl<MemberwiseParameter> &memberVector ) {
2816
+
2789
2817
if (!CursorInfo.ValueD )
2790
2818
return SourceLoc ();
2791
2819
2792
- ClassDecl *classDecl = dyn_cast<ClassDecl >(CursorInfo.ValueD );
2793
- if (!classDecl || classDecl ->getStoredProperties ().empty () ||
2820
+ NominalTypeDecl *nominalDecl = dyn_cast<NominalTypeDecl >(CursorInfo.ValueD );
2821
+ if (!nominalDecl || nominalDecl ->getStoredProperties ().empty () ||
2794
2822
CursorInfo.IsRef ) {
2795
2823
return SourceLoc ();
2796
2824
}
2797
-
2798
- SourceLoc bracesStart = classDecl ->getBraces ().Start ;
2825
+
2826
+ SourceLoc bracesStart = nominalDecl ->getBraces ().Start ;
2799
2827
if (!bracesStart.isValid ())
2800
2828
return SourceLoc ();
2801
2829
2802
2830
SourceLoc targetLocation = bracesStart.getAdvancedLoc (1 );
2803
2831
if (!targetLocation.isValid ())
2804
2832
return SourceLoc ();
2805
-
2806
- for (auto varDecl : classDecl->getStoredProperties ()) {
2807
- auto parentPatternBinding = varDecl->getParentPatternBinding ();
2808
- if (!parentPatternBinding)
2833
+
2834
+ for (auto varDecl : nominalDecl->getStoredProperties ()) {
2835
+ auto patternBinding = varDecl->getParentPatternBinding ();
2836
+ if (!patternBinding)
2837
+ continue ;
2838
+
2839
+ if (!varDecl->isMemberwiseInitialized (/* preferDeclaredProperties=*/ true )) {
2809
2840
continue ;
2810
-
2811
- auto varDeclIndex =
2812
- parentPatternBinding->getPatternEntryIndexForVarDecl (varDecl);
2813
-
2814
- if (auto init = varDecl->getParentPatternBinding ()->getInit (varDeclIndex)) {
2815
- if (init->getStartLoc ().isValid ())
2816
- continue ;
2817
2841
}
2818
-
2819
- StringRef memberName = varDecl->getName ().str ();
2820
- memberNameVector.push_back (memberName.str ());
2821
-
2822
- std::string memberType = varDecl->getType ().getString ();
2823
- memberTypeVector.push_back (memberType);
2842
+
2843
+ auto &entry = patternBinding->getPatternEntryForVarDecl (varDecl);
2844
+ bool isExplicitlyInitialized =
2845
+ entry.isInitialized () && entry.getEqualLoc ().isValid ();
2846
+ Expr *defaultInit = nullptr ;
2847
+ if (isExplicitlyInitialized || patternBinding->isDefaultInitializable ()) {
2848
+ defaultInit = varDecl->getParentInitializer ();
2849
+ }
2850
+
2851
+ memberVector.emplace_back (varDecl->getName (),
2852
+ varDecl->getType (), defaultInit);
2824
2853
}
2825
2854
2826
- if (memberNameVector. empty () || memberTypeVector .empty ()) {
2855
+ if (memberVector .empty ()) {
2827
2856
return SourceLoc ();
2828
2857
}
2829
2858
@@ -2833,25 +2862,18 @@ static SourceLoc collectMembersForInit(ResolvedCursorInfo CursorInfo,
2833
2862
bool RefactoringActionMemberwiseInitLocalRefactoring::
2834
2863
isApplicable (ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
2835
2864
2836
- SmallVector<std::string, 8 > memberNameVector;
2837
- SmallVector<std::string, 8 > memberTypeVector;
2838
-
2839
- return collectMembersForInit (Tok, memberNameVector,
2840
- memberTypeVector).isValid ();
2865
+ SmallVector<MemberwiseParameter, 8 > memberVector;
2866
+ return collectMembersForInit (Tok, memberVector).isValid ();
2841
2867
}
2842
2868
2843
2869
bool RefactoringActionMemberwiseInitLocalRefactoring::performChange () {
2844
2870
2845
- SmallVector<std::string, 8 > memberNameVector;
2846
- SmallVector<std::string, 8 > memberTypeVector;
2847
-
2848
- SourceLoc targetLocation = collectMembersForInit (CursorInfo, memberNameVector,
2849
- memberTypeVector);
2871
+ SmallVector<MemberwiseParameter, 8 > memberVector;
2872
+ SourceLoc targetLocation = collectMembersForInit (CursorInfo, memberVector);
2850
2873
if (targetLocation.isInvalid ())
2851
2874
return true ;
2852
2875
2853
- generateMemberwiseInit (EditConsumer, SM, memberNameVector,
2854
- memberTypeVector, targetLocation);
2876
+ generateMemberwiseInit (EditConsumer, SM, memberVector, targetLocation);
2855
2877
2856
2878
return false ;
2857
2879
}
0 commit comments