Skip to content

Commit aaa7cfa

Browse files
authored
Merge pull request #10260 from bitjammer/upstream-migrator
Upstream lib/Migrator to Open Source
2 parents 16e36f0 + e577ebb commit aaa7cfa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+71025
-34
lines changed

include/swift/Basic/Diff.h

Lines changed: 2598 additions & 0 deletions
Large diffs are not rendered by default.

include/swift/IDE/DigesterEnums.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ DIFF_ITEM_KEY_KIND_INT(Index)
132132
SPECIAL_CASE_ID(NSOpenGLSetOption)
133133
SPECIAL_CASE_ID(NSOpenGLGetOption)
134134
SPECIAL_CASE_ID(StaticAbsToSwiftAbs)
135+
SPECIAL_CASE_ID(NSOpenGLGetVersion)
136+
SPECIAL_CASE_ID(ToIntMax)
137+
SPECIAL_CASE_ID(ToUIntMax)
135138

136139
#undef SPECIAL_CASE_ID
137140
#undef DIFF_ITEM_KEY_KIND_INT

include/swift/Migrator/EditorAdapter.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
#ifndef SWIFT_MIGRATOR_EDITORADAPTER_H
2121
#define SWIFT_MIGRATOR_EDITORADAPTER_H
2222

23+
#include "swift/Migrator/Replacement.h"
2324
#include "clang/Basic/LangOptions.h"
2425
#include "clang/Basic/SourceLocation.h"
2526
#include "clang/Edit/Commit.h"
2627
#include "llvm/ADT/DenseMap.h"
28+
#include "llvm/ADT/SmallSet.h"
2729

2830
namespace swift {
2931

@@ -45,6 +47,10 @@ class EditorAdapter {
4547
/// in the `getClangFileIDForSwiftBufferID` method below.
4648
mutable llvm::SmallDenseMap<unsigned, clang::FileID> SwiftToClangBufferMap;
4749

50+
/// Tracks a history of edits outside of the clang::edit::Commit collector
51+
/// below. That doesn't handle duplicate or redundant changes.
52+
mutable llvm::SmallSet<Replacement, 32> Replacements;
53+
4854
/// A running transactional collection of basic edit operations.
4955
/// Clang uses this transaction concept to cancel a batch of edits due to
5056
/// incompatibilities, such as those due to macro expansions, but we don't
@@ -66,6 +72,13 @@ class EditorAdapter {
6672
clang::CharSourceRange
6773
translateCharSourceRange(CharSourceRange SwiftSourceSourceRange) const;
6874

75+
/// Returns the buffer ID and absolute offset for a Swift SourceLoc.
76+
std::pair<unsigned, unsigned> getLocInfo(swift::SourceLoc Loc) const;
77+
78+
/// Returns true if the replacement has already been booked. Otherwise,
79+
/// returns false and adds it to the replacement set.
80+
bool cacheReplacement(CharSourceRange Range, StringRef Text) const;
81+
6982
public:
7083
EditorAdapter(swift::SourceManager &SwiftSrcMgr,
7184
clang::SourceManager &ClangSrcMgr)

include/swift/Migrator/FixitApplyDiagnosticConsumer.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include "swift/AST/DiagnosticConsumer.h"
2121
#include "swift/Migrator/FixitFilter.h"
22+
#include "swift/Migrator/Migrator.h"
23+
#include "swift/Migrator/Replacement.h"
2224
#include "clang/Rewrite/Core/RewriteBuffer.h"
2325
#include "llvm/ADT/DenseSet.h"
2426

@@ -31,6 +33,8 @@ class SourceManager;
3133

3234
namespace migrator {
3335

36+
struct Replacement;
37+
3438
class FixitApplyDiagnosticConsumer final
3539
: public DiagnosticConsumer, public FixitFilter {
3640
clang::RewriteBuffer RewriteBuf;
@@ -46,8 +50,9 @@ class FixitApplyDiagnosticConsumer final
4650
/// determine whether to call `printResult`.
4751
unsigned NumFixitsApplied;
4852

49-
/// Tracks whether a SourceLoc already got an `@objc` insertion.
50-
llvm::SmallPtrSet<const void *, 32> AddedObjC;
53+
/// Tracks previous replacements so we don't pump the rewrite buffer with
54+
/// multiple equivalent replacements, which can result in weird behavior.
55+
llvm::SmallSet<Replacement, 32> Replacements;
5156

5257
public:
5358
FixitApplyDiagnosticConsumer(const StringRef Text,

include/swift/Migrator/Replacement.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===--- Replacement.h - Migrator Replacements ------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_MIGRATOR_REPLACEMENT_H
14+
#define SWIFT_MIGRATOR_REPLACEMENT_H
15+
namespace swift {
16+
namespace migrator {
17+
18+
struct Replacement {
19+
size_t Offset;
20+
size_t Remove;
21+
std::string Text;
22+
23+
bool isRemove() const {
24+
return Remove > 0;
25+
}
26+
27+
bool isInsert() const {
28+
return Remove == 0 && Text.size() > 0;
29+
}
30+
31+
bool isReplace() const {
32+
return Remove > 0 && Text.size() > 0;
33+
}
34+
35+
size_t endOffset() const {
36+
if (isInsert()) {
37+
return Offset + Text.size();
38+
} else {
39+
return Offset + Remove;
40+
}
41+
}
42+
43+
bool operator<(const Replacement &Other) const {
44+
return Offset < Other.Offset;
45+
}
46+
47+
bool operator==(const Replacement &Other) const {
48+
return Offset == Other.Offset && Remove == Other.Remove &&
49+
Text == Other.Text;
50+
}
51+
};
52+
53+
} // end namespace migrator
54+
} // end namespace swift
55+
56+
#endif // SWIFT_MIGRATOR_REPLACEMENT_H

lib/IDE/Utils.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,15 @@ static const char *skipParenExpression(const char *p, const char *End) {
4545
case ')':
4646
done = --ParenCount == 0;
4747
break;
48-
48+
4949
case '(':
5050
++ParenCount;
5151
break;
52-
52+
5353
case '"':
5454
e = skipStringInCode (e, End);
5555
break;
56-
56+
5757
default:
5858
break;
5959
}
@@ -76,15 +76,15 @@ static const char *skipStringInCode(const char *p, const char *End) {
7676
case '"':
7777
done = true;
7878
break;
79-
79+
8080
case '\\':
8181
++e;
8282
if (e >= End)
8383
done = true;
8484
else if (*e == '(')
8585
e = skipParenExpression (e, End);
8686
break;
87-
87+
8888
default:
8989
break;
9090
}
@@ -113,8 +113,8 @@ ide::isSourceInputComplete(std::unique_ptr<llvm::MemoryBuffer> MemBuf) {
113113

114114
SourceCompleteResult SCR;
115115
SCR.IsComplete = !P.isInputIncomplete();
116-
117-
// Use the same code that was in the REPL code to track the indent level
116+
117+
// Use the same code that was in the REPL code to track the indent level
118118
// for now. In the future we should get this from the Parser if possible.
119119

120120
CharSourceRange entireRange = SM.getRangeForBuffer(BufferID);
@@ -167,7 +167,7 @@ ide::isSourceInputComplete(std::unique_ptr<llvm::MemoryBuffer> MemBuf) {
167167
if (!IndentInfos.empty())
168168
IndentInfos.pop_back();
169169
break;
170-
170+
171171
default:
172172
if (LineSourceStart == nullptr && !isspace(*p))
173173
LineSourceStart = p;

lib/Migrator/APIDiffMigratorPass.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,59 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
446446
// Swift.abs(1.0)
447447
Editor.replace(Call->getFn()->getSourceRange(), "Swift.abs");
448448
return true;
449+
case SpecialCaseId::ToUIntMax:
450+
if (const auto *DotCall = dyn_cast<DotSyntaxCallExpr>(Call->getFn())) {
451+
Editor.insert(DotCall->getStartLoc(), "UInt64(");
452+
Editor.replace({ DotCall->getDotLoc(), Call->getEndLoc() }, ")");
453+
return true;
454+
}
455+
return false;
456+
case SpecialCaseId::ToIntMax:
457+
if (const auto *DotCall = dyn_cast<DotSyntaxCallExpr>(Call->getFn())) {
458+
Editor.insert(DotCall->getStartLoc(), "Int64(");
459+
Editor.replace({ DotCall->getDotLoc(), Call->getEndLoc() }, ")");
460+
return true;
461+
}
462+
return false;
463+
case SpecialCaseId::NSOpenGLGetVersion: {
464+
if (const auto *Tuple = dyn_cast<TupleExpr>(Arg)) {
465+
if (Tuple->getNumElements() != 2) {
466+
return false;
467+
}
468+
469+
auto extractArg = [](const Expr *Arg) -> const DeclRefExpr * {
470+
while (const auto *ICE = dyn_cast<ImplicitConversionExpr>(Arg)) {
471+
Arg = ICE->getSubExpr();
472+
}
473+
if (const auto *IOE = dyn_cast<InOutExpr>(Arg)) {
474+
return dyn_cast<DeclRefExpr>(IOE->getSubExpr());
475+
}
476+
return nullptr;
477+
};
478+
479+
const auto *Arg0 = extractArg(Tuple->getElement(0));
480+
const auto *Arg1 = extractArg(Tuple->getElement(1));
481+
482+
if (!(Arg0 && Arg1)) {
483+
return false;
484+
}
485+
SmallString<256> Scratch;
486+
llvm::raw_svector_ostream OS(Scratch);
487+
auto StartLoc = Call->getStartLoc();
488+
Editor.insert(StartLoc, "(");
489+
Editor.insert(StartLoc,
490+
SM.extractText(Lexer::getCharSourceRangeFromSourceRange(SM,
491+
Arg0->getSourceRange())));
492+
Editor.insert(StartLoc, ", ");
493+
Editor.insert(StartLoc,
494+
SM.extractText(Lexer::getCharSourceRangeFromSourceRange(SM,
495+
Arg1->getSourceRange())));
496+
Editor.insert(StartLoc, ") = ");
497+
Editor.replace(Call->getSourceRange(), "NSOpenGLContext.openGLVersion");
498+
return true;
499+
}
500+
return false;
501+
}
449502
}
450503
}
451504

lib/Migrator/EditorAdapter.cpp

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,33 @@
1313
#include "swift/Basic/SourceLoc.h"
1414
#include "swift/Basic/SourceManager.h"
1515
#include "swift/Migrator/EditorAdapter.h"
16+
#include "swift/Migrator/Replacement.h"
1617
#include "swift/Parse/Lexer.h"
1718
#include "clang/Basic/SourceManager.h"
1819

1920
using namespace swift;
2021
using namespace swift::migrator;
2122

23+
std::pair<unsigned, unsigned>
24+
EditorAdapter::getLocInfo(swift::SourceLoc Loc) const {
25+
auto SwiftBufferID = SwiftSrcMgr.findBufferContainingLoc(Loc);
26+
auto Offset = SwiftSrcMgr.getLocOffsetInBuffer(Loc, SwiftBufferID);
27+
return { SwiftBufferID, Offset };
28+
}
29+
30+
bool
31+
EditorAdapter::cacheReplacement(CharSourceRange Range, StringRef Text) const {
32+
unsigned SwiftBufferID, Offset;
33+
std::tie(SwiftBufferID, Offset) = getLocInfo(Range.getStart());
34+
Replacement R { Offset, Range.getByteLength(), Text };
35+
if (Replacements.count(R)) {
36+
return true;
37+
} else {
38+
Replacements.insert(R);
39+
}
40+
return false;
41+
}
42+
2243
clang::FileID
2344
EditorAdapter::getClangFileIDForSwiftBufferID(unsigned BufferID) const {
2445
/// Check if we already have a mapping for this BufferID.
@@ -40,8 +61,8 @@ EditorAdapter::getClangFileIDForSwiftBufferID(unsigned BufferID) const {
4061

4162
clang::SourceLocation
4263
EditorAdapter::translateSourceLoc(SourceLoc SwiftLoc) const {
43-
auto SwiftBufferID = SwiftSrcMgr.findBufferContainingLoc(SwiftLoc);
44-
auto Offset = SwiftSrcMgr.getLocOffsetInBuffer(SwiftLoc, SwiftBufferID);
64+
unsigned SwiftBufferID, Offset;
65+
std::tie(SwiftBufferID, Offset) = getLocInfo(SwiftLoc);
4566

4667
auto ClangFileID = getClangFileIDForSwiftBufferID(SwiftBufferID);
4768
return ClangSrcMgr.getLocForStartOfFile(ClangFileID).getLocWithOffset(Offset);
@@ -67,6 +88,10 @@ bool EditorAdapter::insert(SourceLoc Loc, StringRef Text, bool AfterToken,
6788
if (AfterToken)
6889
Loc = Lexer::getLocForEndOfToken(SwiftSrcMgr, Loc);
6990

91+
if (cacheReplacement(CharSourceRange { Loc, 0 }, Text)) {
92+
return true;
93+
}
94+
7095
auto ClangLoc = translateSourceLoc(Loc);
7196
return Edits.insert(ClangLoc, Text, /*AfterToken=*/false, BeforePreviousInsertions);
7297
}
@@ -78,6 +103,11 @@ bool EditorAdapter::insertFromRange(SourceLoc Loc, CharSourceRange Range,
78103
if (AfterToken)
79104
Loc = Lexer::getLocForEndOfToken(SwiftSrcMgr, Loc);
80105

106+
if (cacheReplacement(CharSourceRange { Loc, 0 },
107+
SwiftSrcMgr.extractText(Range))) {
108+
return true;
109+
}
110+
81111
auto ClangLoc = translateSourceLoc(Loc);
82112
auto ClangCharRange = translateCharSourceRange(Range);
83113

@@ -92,23 +122,41 @@ bool EditorAdapter::insertWrap(StringRef Before, CharSourceRange Range,
92122
}
93123

94124
bool EditorAdapter::remove(CharSourceRange Range) {
125+
if (cacheReplacement(Range, "")) {
126+
return true;
127+
}
95128
auto ClangRange = translateCharSourceRange(Range);
96129
return Edits.remove(ClangRange);
97130
}
98131

99132
bool EditorAdapter::replace(CharSourceRange Range, StringRef Text) {
133+
if (cacheReplacement(Range, Text)) {
134+
return true;
135+
}
136+
100137
auto ClangRange = translateCharSourceRange(Range);
101138
return Edits.replace(ClangRange, Text);
102139
}
103140

104141
bool EditorAdapter::replaceWithInner(CharSourceRange Range,
105142
CharSourceRange InnerRange) {
143+
144+
if (cacheReplacement(Range, SwiftSrcMgr.extractText(InnerRange))) {
145+
return true;
146+
}
106147
auto ClangRange = translateCharSourceRange(Range);
107148
auto ClangInnerRange = translateCharSourceRange(InnerRange);
108149
return Edits.replaceWithInner(ClangRange, ClangInnerRange);
109150
}
151+
110152
bool EditorAdapter::replaceText(SourceLoc Loc, StringRef Text,
111-
StringRef ReplacementText) {
153+
StringRef ReplacementText) {
154+
auto Range = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr,
155+
{ Loc, Loc.getAdvancedLoc(Text.size())});
156+
if (cacheReplacement(Range, Text)) {
157+
return true;
158+
}
159+
112160
auto ClangLoc = translateSourceLoc(Loc);
113161
return Edits.replaceText(ClangLoc, Text, ReplacementText);
114162
}

lib/Migrator/FixitApplyDiagnosticConsumer.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,11 @@ handleDiagnostic(SourceManager &SM, SourceLoc Loc,
5656
ThisBufferID);
5757
auto Length = Fixit.getRange().getByteLength();
5858

59-
if (Fixit.getText().ltrim().rtrim() == "@objc") {
60-
if (AddedObjC.count(Loc.getOpaquePointerValue())) {
61-
return;
62-
} else {
63-
AddedObjC.insert(Loc.getOpaquePointerValue());
64-
}
59+
Replacement R { Offset, Length, Fixit.getText() };
60+
if (Replacements.count(R)) {
61+
return;
62+
} else {
63+
Replacements.insert(R);
6564
}
6665

6766
RewriteBuf.ReplaceText(Offset, Length, Fixit.getText());

0 commit comments

Comments
 (0)