|
12 | 12 |
|
13 | 13 | #include "LocalRename.h" |
14 | 14 | #include "RefactoringActions.h" |
15 | | -#include "Renamer.h" |
16 | 15 | #include "swift/AST/DiagnosticsRefactoring.h" |
17 | 16 | #include "swift/AST/ParameterList.h" |
18 | 17 | #include "swift/AST/USRGeneration.h" |
|
22 | 21 | using namespace swift::refactoring; |
23 | 22 | using namespace swift::index; |
24 | 23 |
|
25 | | -class TextReplacementsRenamer : public Renamer { |
26 | | - llvm::StringSet<> &ReplaceTextContext; |
27 | | - SmallVector<Replacement> Replacements; |
28 | | - |
29 | | -public: |
30 | | - const DeclNameViewer New; |
31 | | - |
32 | | -private: |
33 | | - StringRef registerText(StringRef Text) { |
34 | | - if (Text.empty()) |
35 | | - return Text; |
36 | | - return ReplaceTextContext.insert(Text).first->getKey(); |
37 | | - } |
38 | | - |
39 | | - StringRef getCallArgLabelReplacement(StringRef OldLabelRange, |
40 | | - StringRef NewLabel) { |
41 | | - return NewLabel.empty() ? "" : NewLabel; |
42 | | - } |
43 | | - |
44 | | - StringRef getCallArgColonReplacement(StringRef OldLabelRange, |
45 | | - StringRef NewLabel) { |
46 | | - // Expected OldLabelRange: foo( []3, a[: ]2, b[ : ]3 ...) |
47 | | - // FIXME: Preserve comments: foo([a/*:*/ : /*:*/ ]2, ...) |
48 | | - if (NewLabel.empty()) |
49 | | - return ""; |
50 | | - if (OldLabelRange.empty()) |
51 | | - return ": "; |
52 | | - return registerText(OldLabelRange); |
53 | | - } |
54 | | - |
55 | | - StringRef getCallArgCombinedReplacement(StringRef OldArgLabel, |
56 | | - StringRef NewArgLabel) { |
57 | | - // This case only happens when going from foo([]1) to foo([a: ]1). |
58 | | - assert(OldArgLabel.empty()); |
59 | | - if (NewArgLabel.empty()) |
60 | | - return ""; |
61 | | - return registerText((Twine(NewArgLabel) + ": ").str()); |
62 | | - } |
63 | | - |
64 | | - StringRef getParamNameReplacement(StringRef OldParam, StringRef OldArgLabel, |
65 | | - StringRef NewArgLabel) { |
66 | | - // We don't want to get foo(a a: Int), so drop the parameter name if the |
67 | | - // argument label will match the original name. |
68 | | - // Note: the leading whitespace is part of the parameter range. |
69 | | - if (!NewArgLabel.empty() && OldParam.ltrim() == NewArgLabel) |
70 | | - return ""; |
71 | | - |
72 | | - // If we're renaming foo(x: Int) to foo(_:), then use the original argument |
73 | | - // label as the parameter name so as to not break references in the body. |
74 | | - if (NewArgLabel.empty() && !OldArgLabel.empty() && OldParam.empty()) |
75 | | - return registerText((Twine(" ") + OldArgLabel).str()); |
76 | | - |
77 | | - return registerText(OldParam); |
78 | | - } |
79 | | - |
80 | | - StringRef getDeclArgumentLabelReplacement(StringRef OldLabelRange, |
81 | | - StringRef NewArgLabel) { |
82 | | - // OldLabelRange is subscript([]a: Int), foo([a]: Int) or foo([a] b: Int) |
83 | | - if (NewArgLabel.empty()) |
84 | | - return OldLabelRange.empty() ? "" : "_"; |
85 | | - |
86 | | - if (OldLabelRange.empty()) |
87 | | - return registerText((Twine(NewArgLabel) + " ").str()); |
88 | | - return registerText(NewArgLabel); |
89 | | - } |
90 | | - |
91 | | - StringRef getReplacementText(StringRef LabelRange, |
92 | | - RefactoringRangeKind RangeKind, |
93 | | - StringRef OldLabel, StringRef NewLabel) { |
94 | | - switch (RangeKind) { |
95 | | - case RefactoringRangeKind::CallArgumentLabel: |
96 | | - return getCallArgLabelReplacement(LabelRange, NewLabel); |
97 | | - case RefactoringRangeKind::CallArgumentColon: |
98 | | - return getCallArgColonReplacement(LabelRange, NewLabel); |
99 | | - case RefactoringRangeKind::CallArgumentCombined: |
100 | | - return getCallArgCombinedReplacement(LabelRange, NewLabel); |
101 | | - case RefactoringRangeKind::ParameterName: |
102 | | - return getParamNameReplacement(LabelRange, OldLabel, NewLabel); |
103 | | - case RefactoringRangeKind::NoncollapsibleParameterName: |
104 | | - return LabelRange; |
105 | | - case RefactoringRangeKind::DeclArgumentLabel: |
106 | | - return getDeclArgumentLabelReplacement(LabelRange, NewLabel); |
107 | | - case RefactoringRangeKind::SelectorArgumentLabel: |
108 | | - return NewLabel.empty() ? "_" : registerText(NewLabel); |
109 | | - default: |
110 | | - llvm_unreachable("label range type is none but there are labels"); |
111 | | - } |
112 | | - } |
113 | | - |
114 | | - void addReplacement(CharSourceRange LabelRange, |
115 | | - RefactoringRangeKind RangeKind, StringRef OldLabel, |
116 | | - StringRef NewLabel) { |
117 | | - StringRef ExistingLabel = LabelRange.str(); |
118 | | - StringRef Text = |
119 | | - getReplacementText(ExistingLabel, RangeKind, OldLabel, NewLabel); |
120 | | - if (Text != ExistingLabel) |
121 | | - Replacements.push_back({/*Path=*/{}, LabelRange, /*BufferName=*/{}, Text, |
122 | | - /*RegionsWorthNote=*/{}}); |
123 | | - } |
124 | | - |
125 | | - void doRenameLabel(CharSourceRange Label, RefactoringRangeKind RangeKind, |
126 | | - unsigned NameIndex) override { |
127 | | - addReplacement(Label, RangeKind, Old.args()[NameIndex], |
128 | | - New.args()[NameIndex]); |
129 | | - } |
130 | | - |
131 | | - void doRenameBase(CharSourceRange Range, RefactoringRangeKind) override { |
132 | | - if (Old.base() != New.base()) |
133 | | - Replacements.push_back({/*Path=*/{}, Range, /*BufferName=*/{}, |
134 | | - registerText(New.base()), |
135 | | - /*RegionsWorthNote=*/{}}); |
136 | | - } |
137 | | - |
138 | | -public: |
139 | | - TextReplacementsRenamer(const SourceManager &SM, StringRef OldName, |
140 | | - StringRef NewName, |
141 | | - llvm::StringSet<> &ReplaceTextContext) |
142 | | - : Renamer(SM, OldName), ReplaceTextContext(ReplaceTextContext), |
143 | | - New(NewName) { |
144 | | - assert(Old.isValid() && New.isValid()); |
145 | | - assert(Old.partsCount() == New.partsCount()); |
146 | | - } |
147 | | - |
148 | | - ArrayRef<Replacement> getReplacements() const { return Replacements; } |
149 | | -}; |
150 | | - |
151 | 24 | static const ValueDecl *getRelatedSystemDecl(const ValueDecl *VD) { |
152 | 25 | if (VD->getModuleContext()->isNonUserModule()) |
153 | 26 | return VD; |
@@ -498,127 +371,6 @@ bool RefactoringActionLocalRename::performChange() { |
498 | 371 | *consumers[0]); |
499 | 372 | } |
500 | 373 |
|
501 | | -static std::vector<ResolvedLoc> |
502 | | -resolveRenameLocations(ArrayRef<RenameLoc> RenameLocs, SourceFile &SF, |
503 | | - DiagnosticEngine &Diags) { |
504 | | - SourceManager &SM = SF.getASTContext().SourceMgr; |
505 | | - unsigned BufferID = SF.getBufferID().value(); |
506 | | - |
507 | | - std::vector<UnresolvedLoc> UnresolvedLocs; |
508 | | - for (const RenameLoc &RenameLoc : RenameLocs) { |
509 | | - DeclNameViewer OldName(RenameLoc.OldName); |
510 | | - SourceLoc Location = |
511 | | - SM.getLocForLineCol(BufferID, RenameLoc.Line, RenameLoc.Column); |
512 | | - |
513 | | - if (!OldName.isValid()) { |
514 | | - Diags.diagnose(Location, diag::invalid_name, RenameLoc.OldName); |
515 | | - return {}; |
516 | | - } |
517 | | - |
518 | | - if (!RenameLoc.NewName.empty()) { |
519 | | - DeclNameViewer NewName(RenameLoc.NewName); |
520 | | - ArrayRef<StringRef> ParamNames = NewName.args(); |
521 | | - bool newOperator = Lexer::isOperator(NewName.base()); |
522 | | - bool NewNameIsValid = |
523 | | - NewName.isValid() && |
524 | | - (Lexer::isIdentifier(NewName.base()) || newOperator) && |
525 | | - std::all_of(ParamNames.begin(), ParamNames.end(), |
526 | | - [](StringRef Label) { |
527 | | - return Label.empty() || Lexer::isIdentifier(Label); |
528 | | - }); |
529 | | - |
530 | | - if (!NewNameIsValid) { |
531 | | - Diags.diagnose(Location, diag::invalid_name, RenameLoc.NewName); |
532 | | - return {}; |
533 | | - } |
534 | | - |
535 | | - if (NewName.partsCount() != OldName.partsCount()) { |
536 | | - Diags.diagnose(Location, diag::arity_mismatch, RenameLoc.NewName, |
537 | | - RenameLoc.OldName); |
538 | | - return {}; |
539 | | - } |
540 | | - |
541 | | - if (RenameLoc.Usage == NameUsage::Call && !RenameLoc.IsFunctionLike) { |
542 | | - Diags.diagnose(Location, diag::name_not_functionlike, |
543 | | - RenameLoc.NewName); |
544 | | - return {}; |
545 | | - } |
546 | | - } |
547 | | - |
548 | | - bool isOperator = Lexer::isOperator(OldName.base()); |
549 | | - UnresolvedLocs.push_back( |
550 | | - {Location, (RenameLoc.Usage == NameUsage::Unknown || |
551 | | - (RenameLoc.Usage == NameUsage::Call && !isOperator))}); |
552 | | - } |
553 | | - |
554 | | - NameMatcher Resolver(SF); |
555 | | - return Resolver.resolve(UnresolvedLocs, SF.getAllTokens()); |
556 | | -} |
557 | | - |
558 | | -int swift::ide::syntacticRename(SourceFile *SF, ArrayRef<RenameLoc> RenameLocs, |
559 | | - SourceEditConsumer &EditConsumer, |
560 | | - DiagnosticConsumer &DiagConsumer) { |
561 | | - |
562 | | - assert(SF && "null source file"); |
563 | | - |
564 | | - SourceManager &SM = SF->getASTContext().SourceMgr; |
565 | | - DiagnosticEngine DiagEngine(SM); |
566 | | - DiagEngine.addConsumer(DiagConsumer); |
567 | | - |
568 | | - auto ResolvedLocs = resolveRenameLocations(RenameLocs, *SF, DiagEngine); |
569 | | - if (ResolvedLocs.size() != RenameLocs.size()) |
570 | | - return true; // Already diagnosed. |
571 | | - |
572 | | - size_t index = 0; |
573 | | - llvm::StringSet<> ReplaceTextContext; |
574 | | - for (const RenameLoc &Rename : RenameLocs) { |
575 | | - ResolvedLoc &Resolved = ResolvedLocs[index++]; |
576 | | - TextReplacementsRenamer Renamer(SM, Rename.OldName, Rename.NewName, |
577 | | - ReplaceTextContext); |
578 | | - RegionType Type = Renamer.addSyntacticRenameRanges(Resolved, Rename); |
579 | | - if (Type == RegionType::Mismatch) { |
580 | | - DiagEngine.diagnose(Resolved.Range.getStart(), diag::mismatched_rename, |
581 | | - Rename.NewName); |
582 | | - EditConsumer.accept(SM, Type, llvm::None); |
583 | | - } else { |
584 | | - EditConsumer.accept(SM, Type, Renamer.getReplacements()); |
585 | | - } |
586 | | - } |
587 | | - |
588 | | - return false; |
589 | | -} |
590 | | - |
591 | | -int swift::ide::findSyntacticRenameRanges( |
592 | | - SourceFile *SF, ArrayRef<RenameLoc> RenameLocs, |
593 | | - FindRenameRangesConsumer &RenameConsumer, |
594 | | - DiagnosticConsumer &DiagConsumer) { |
595 | | - assert(SF && "null source file"); |
596 | | - |
597 | | - SourceManager &SM = SF->getASTContext().SourceMgr; |
598 | | - DiagnosticEngine DiagEngine(SM); |
599 | | - DiagEngine.addConsumer(DiagConsumer); |
600 | | - |
601 | | - auto ResolvedLocs = resolveRenameLocations(RenameLocs, *SF, DiagEngine); |
602 | | - if (ResolvedLocs.size() != RenameLocs.size()) |
603 | | - return true; // Already diagnosed. |
604 | | - |
605 | | - size_t index = 0; |
606 | | - for (const RenameLoc &Rename : RenameLocs) { |
607 | | - ResolvedLoc &Resolved = ResolvedLocs[index++]; |
608 | | - RenameRangeDetailCollector Renamer(SM, Rename.OldName); |
609 | | - RegionType Type = Renamer.addSyntacticRenameRanges(Resolved, Rename); |
610 | | - if (Type == RegionType::Mismatch) { |
611 | | - DiagEngine.diagnose(Resolved.Range.getStart(), diag::mismatched_rename, |
612 | | - Rename.NewName); |
613 | | - RenameConsumer.accept(SM, Type, llvm::None); |
614 | | - } else { |
615 | | - RenameConsumer.accept(SM, Type, Renamer.Ranges); |
616 | | - } |
617 | | - } |
618 | | - |
619 | | - return false; |
620 | | -} |
621 | | - |
622 | 374 | int swift::ide::findLocalRenameRanges(SourceFile *SF, RangeConfig Range, |
623 | 375 | FindRenameRangesConsumer &RenameConsumer, |
624 | 376 | DiagnosticConsumer &DiagConsumer) { |
|
0 commit comments