Skip to content

Commit 6b2e54d

Browse files
committed
Extract RefactoringActionConvertStringsConcatenationToInterpolation to its own file
1 parent d5b29f2 commit 6b2e54d

File tree

3 files changed

+144
-122
lines changed

3 files changed

+144
-122
lines changed

lib/Refactoring/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
add_swift_host_library(swiftRefactoring STATIC
2-
Refactoring.cpp)
2+
ConvertStringConcatenationToInterpolation.cpp
3+
Refactoring.cpp
4+
)
35

46
target_link_libraries(swiftRefactoring PRIVATE
57
swiftAST
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
//===----------------------------------------------------------------------===//
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+
#include "RefactoringActions.h"
14+
15+
using namespace swift::refactoring;
16+
17+
static std::unique_ptr<llvm::SetVector<Expr *>>
18+
findConcatenatedExpressions(const ResolvedRangeInfo &Info, ASTContext &Ctx) {
19+
Expr *E = nullptr;
20+
21+
switch (Info.Kind) {
22+
case RangeKind::SingleExpression:
23+
E = Info.ContainedNodes[0].get<Expr *>();
24+
break;
25+
case RangeKind::PartOfExpression:
26+
E = Info.CommonExprParent;
27+
break;
28+
default:
29+
return nullptr;
30+
}
31+
32+
assert(E);
33+
34+
struct StringInterpolationExprFinder : public SourceEntityWalker {
35+
std::unique_ptr<llvm::SetVector<Expr *>> Bucket =
36+
std::make_unique<llvm::SetVector<Expr *>>();
37+
ASTContext &Ctx;
38+
39+
bool IsValidInterpolation = true;
40+
StringInterpolationExprFinder(ASTContext &Ctx) : Ctx(Ctx) {}
41+
42+
bool isConcatenationExpr(DeclRefExpr *Expr) {
43+
if (!Expr)
44+
return false;
45+
auto *FD = dyn_cast<FuncDecl>(Expr->getDecl());
46+
if (FD == nullptr ||
47+
(FD != Ctx.getPlusFunctionOnString() &&
48+
FD != Ctx.getPlusFunctionOnRangeReplaceableCollection())) {
49+
return false;
50+
}
51+
return true;
52+
}
53+
54+
bool walkToExprPre(Expr *E) override {
55+
if (E->isImplicit())
56+
return true;
57+
// FIXME: we should have ErrorType instead of null.
58+
if (E->getType().isNull())
59+
return true;
60+
61+
// Only binary concatenation operators should exist in expression
62+
if (E->getKind() == ExprKind::Binary) {
63+
auto *BE = dyn_cast<BinaryExpr>(E);
64+
auto *OperatorDeclRef = BE->getSemanticFn()->getMemberOperatorRef();
65+
if (!(isConcatenationExpr(OperatorDeclRef) &&
66+
E->getType()->isString())) {
67+
IsValidInterpolation = false;
68+
return false;
69+
}
70+
return true;
71+
}
72+
// Everything that evaluates to string should be gathered.
73+
if (E->getType()->isString()) {
74+
Bucket->insert(E);
75+
return false;
76+
}
77+
if (auto *DR = dyn_cast<DeclRefExpr>(E)) {
78+
// Checks whether all function references in expression are
79+
// concatenations.
80+
auto *FD = dyn_cast<FuncDecl>(DR->getDecl());
81+
auto IsConcatenation = isConcatenationExpr(DR);
82+
if (FD && IsConcatenation) {
83+
return false;
84+
}
85+
}
86+
// There was non-expected expression, it's not valid interpolation then.
87+
IsValidInterpolation = false;
88+
return false;
89+
}
90+
} Walker(Ctx);
91+
Walker.walk(E);
92+
93+
// There should be two or more expressions to convert.
94+
if (!Walker.IsValidInterpolation || Walker.Bucket->size() < 2)
95+
return nullptr;
96+
97+
return std::move(Walker.Bucket);
98+
}
99+
100+
static void interpolatedExpressionForm(Expr *E, SourceManager &SM,
101+
llvm::raw_ostream &OS) {
102+
if (auto *Literal = dyn_cast<StringLiteralExpr>(E)) {
103+
OS << Literal->getValue();
104+
return;
105+
}
106+
auto ExpStr =
107+
Lexer::getCharSourceRangeFromSourceRange(SM, E->getSourceRange())
108+
.str()
109+
.str();
110+
if (isa<InterpolatedStringLiteralExpr>(E)) {
111+
ExpStr.erase(0, 1);
112+
ExpStr.pop_back();
113+
OS << ExpStr;
114+
return;
115+
}
116+
OS << "\\(" << ExpStr << ")";
117+
}
118+
119+
bool RefactoringActionConvertStringsConcatenationToInterpolation::isApplicable(
120+
const ResolvedRangeInfo &Info, DiagnosticEngine &Diag) {
121+
auto RangeContext = Info.RangeContext;
122+
if (RangeContext) {
123+
auto &Ctx = Info.RangeContext->getASTContext();
124+
return findConcatenatedExpressions(Info, Ctx) != nullptr;
125+
}
126+
return false;
127+
}
128+
129+
bool RefactoringActionConvertStringsConcatenationToInterpolation::
130+
performChange() {
131+
auto Expressions = findConcatenatedExpressions(RangeInfo, Ctx);
132+
if (!Expressions)
133+
return true;
134+
EditorConsumerInsertStream OS(EditConsumer, SM, RangeInfo.ContentRange);
135+
OS << "\"";
136+
for (auto It = Expressions->begin(); It != Expressions->end(); ++It) {
137+
interpolatedExpressionForm(*It, SM, OS);
138+
}
139+
OS << "\"";
140+
return false;
141+
}

lib/Refactoring/Refactoring.cpp

Lines changed: 0 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1914,127 +1914,6 @@ bool RefactoringActionCollapseNestedIfStmt::performChange() {
19141914
return false;
19151915
}
19161916

1917-
static std::unique_ptr<llvm::SetVector<Expr*>>
1918-
findConcatenatedExpressions(const ResolvedRangeInfo &Info, ASTContext &Ctx) {
1919-
Expr *E = nullptr;
1920-
1921-
switch (Info.Kind) {
1922-
case RangeKind::SingleExpression:
1923-
E = Info.ContainedNodes[0].get<Expr*>();
1924-
break;
1925-
case RangeKind::PartOfExpression:
1926-
E = Info.CommonExprParent;
1927-
break;
1928-
default:
1929-
return nullptr;
1930-
}
1931-
1932-
assert(E);
1933-
1934-
struct StringInterpolationExprFinder: public SourceEntityWalker {
1935-
std::unique_ptr<llvm::SetVector<Expr *>> Bucket =
1936-
std::make_unique<llvm::SetVector<Expr *>>();
1937-
ASTContext &Ctx;
1938-
1939-
bool IsValidInterpolation = true;
1940-
StringInterpolationExprFinder(ASTContext &Ctx): Ctx(Ctx) {}
1941-
1942-
bool isConcatenationExpr(DeclRefExpr* Expr) {
1943-
if (!Expr)
1944-
return false;
1945-
auto *FD = dyn_cast<FuncDecl>(Expr->getDecl());
1946-
if (FD == nullptr || (FD != Ctx.getPlusFunctionOnString() &&
1947-
FD != Ctx.getPlusFunctionOnRangeReplaceableCollection())) {
1948-
return false;
1949-
}
1950-
return true;
1951-
}
1952-
1953-
bool walkToExprPre(Expr *E) override {
1954-
if (E->isImplicit())
1955-
return true;
1956-
// FIXME: we should have ErrorType instead of null.
1957-
if (E->getType().isNull())
1958-
return true;
1959-
1960-
//Only binary concatenation operators should exist in expression
1961-
if (E->getKind() == ExprKind::Binary) {
1962-
auto *BE = dyn_cast<BinaryExpr>(E);
1963-
auto *OperatorDeclRef = BE->getSemanticFn()->getMemberOperatorRef();
1964-
if (!(isConcatenationExpr(OperatorDeclRef) &&
1965-
E->getType()->isString())) {
1966-
IsValidInterpolation = false;
1967-
return false;
1968-
}
1969-
return true;
1970-
}
1971-
// Everything that evaluates to string should be gathered.
1972-
if (E->getType()->isString()) {
1973-
Bucket->insert(E);
1974-
return false;
1975-
}
1976-
if (auto *DR = dyn_cast<DeclRefExpr>(E)) {
1977-
// Checks whether all function references in expression are concatenations.
1978-
auto *FD = dyn_cast<FuncDecl>(DR->getDecl());
1979-
auto IsConcatenation = isConcatenationExpr(DR);
1980-
if (FD && IsConcatenation) {
1981-
return false;
1982-
}
1983-
}
1984-
// There was non-expected expression, it's not valid interpolation then.
1985-
IsValidInterpolation = false;
1986-
return false;
1987-
}
1988-
} Walker(Ctx);
1989-
Walker.walk(E);
1990-
1991-
// There should be two or more expressions to convert.
1992-
if (!Walker.IsValidInterpolation || Walker.Bucket->size() < 2)
1993-
return nullptr;
1994-
1995-
return std::move(Walker.Bucket);
1996-
}
1997-
1998-
static void interpolatedExpressionForm(Expr *E, SourceManager &SM,
1999-
llvm::raw_ostream &OS) {
2000-
if (auto *Literal = dyn_cast<StringLiteralExpr>(E)) {
2001-
OS << Literal->getValue();
2002-
return;
2003-
}
2004-
auto ExpStr = Lexer::getCharSourceRangeFromSourceRange(SM,
2005-
E->getSourceRange()).str().str();
2006-
if (isa<InterpolatedStringLiteralExpr>(E)) {
2007-
ExpStr.erase(0, 1);
2008-
ExpStr.pop_back();
2009-
OS << ExpStr;
2010-
return;
2011-
}
2012-
OS << "\\(" << ExpStr << ")";
2013-
}
2014-
2015-
bool RefactoringActionConvertStringsConcatenationToInterpolation::
2016-
isApplicable(const ResolvedRangeInfo &Info, DiagnosticEngine &Diag) {
2017-
auto RangeContext = Info.RangeContext;
2018-
if (RangeContext) {
2019-
auto &Ctx = Info.RangeContext->getASTContext();
2020-
return findConcatenatedExpressions(Info, Ctx) != nullptr;
2021-
}
2022-
return false;
2023-
}
2024-
2025-
bool RefactoringActionConvertStringsConcatenationToInterpolation::performChange() {
2026-
auto Expressions = findConcatenatedExpressions(RangeInfo, Ctx);
2027-
if (!Expressions)
2028-
return true;
2029-
EditorConsumerInsertStream OS(EditConsumer, SM, RangeInfo.ContentRange);
2030-
OS << "\"";
2031-
for (auto It = Expressions->begin(); It != Expressions->end(); ++It) {
2032-
interpolatedExpressionForm(*It, SM, OS);
2033-
}
2034-
OS << "\"";
2035-
return false;
2036-
}
2037-
20381917
/// Abstract helper class containing info about a TernaryExpr
20391918
/// that can be expanded into an IfStmt.
20401919
class ExpandableTernaryExprInfo {

0 commit comments

Comments
 (0)