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