Skip to content

Commit 6fcb830

Browse files
Kacper20Harlan
authored andcommitted
[IDE] Refactoring: conversion from “force try” to error handled version (swiftlang#12063)
* [IDE] Refactoring: conversion from “force try” do error handled version * Removed unnecessary empty line * Changed name of the refactor * Review fixes * Fixed recognizing try_! location by CursorResolver * Review fixes
1 parent 82d6780 commit 6fcb830

File tree

19 files changed

+211
-4
lines changed

19 files changed

+211
-4
lines changed

include/swift/IDE/RefactoringKinds.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ CURSOR_REFACTORING(SimplifyNumberLiteral, "Simplify Long Number Literal", simpli
4040

4141
CURSOR_REFACTORING(CollapseNestedIfExpr, "Collapse Nested If Expression", collapse.nested.if.expr)
4242

43+
CURSOR_REFACTORING(ConvertToDoCatch, "Convert To Do/Catch", convert.do.catch)
44+
4345
RANGE_REFACTORING(ExtractExpr, "Extract Expression", extract.expr)
4446

4547
RANGE_REFACTORING(ExtractFunction, "Extract Method", extract.function)

lib/IDE/Refactoring.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "swift/IDE/Refactoring.h"
1414
#include "swift/AST/ASTContext.h"
15+
#include "swift/AST/ASTPrinter.h"
1516
#include "swift/AST/Decl.h"
1617
#include "swift/AST/DiagnosticsRefactoring.h"
1718
#include "swift/AST/Expr.h"
@@ -1923,6 +1924,60 @@ bool RefactoringActionLocalizeString::performChange() {
19231924
return false;
19241925
}
19251926

1927+
static CharSourceRange
1928+
findSourceRangeToWrapInCatch(ResolvedCursorInfo CursorInfo,
1929+
SourceFile *TheFile,
1930+
SourceManager &SM) {
1931+
Expr *E = CursorInfo.TrailingExpr;
1932+
if (!E)
1933+
return CharSourceRange();
1934+
auto Node = ASTNode(E);
1935+
auto NodeChecker = [](ASTNode N) { return N.isStmt(StmtKind::Brace); };
1936+
ContextFinder Finder(*TheFile, Node, NodeChecker);
1937+
Finder.resolve();
1938+
auto Contexts = Finder.getContexts();
1939+
if (Contexts.size() == 0)
1940+
return CharSourceRange();
1941+
auto TargetNode = Contexts.back();
1942+
BraceStmt *BStmt = dyn_cast<BraceStmt>(TargetNode.dyn_cast<Stmt*>());
1943+
auto ConvertToCharRange = [&SM](SourceRange SR) {
1944+
return Lexer::getCharSourceRangeFromSourceRange(SM, SR);
1945+
};
1946+
assert(BStmt);
1947+
auto ExprRange = ConvertToCharRange(E->getSourceRange());
1948+
// Check elements of the deepest BraceStmt, pick one that covers expression.
1949+
for (auto Elem: BStmt->getElements()) {
1950+
auto ElemRange = ConvertToCharRange(Elem.getSourceRange());
1951+
if (ElemRange.contains(ExprRange))
1952+
TargetNode = Elem;
1953+
}
1954+
return ConvertToCharRange(TargetNode.getSourceRange());
1955+
}
1956+
1957+
bool RefactoringActionConvertToDoCatch::isApplicable(ResolvedCursorInfo Tok) {
1958+
if (!Tok.TrailingExpr)
1959+
return false;
1960+
return isa<ForceTryExpr>(Tok.TrailingExpr);
1961+
}
1962+
1963+
bool RefactoringActionConvertToDoCatch::performChange() {
1964+
auto *TryExpr = dyn_cast<ForceTryExpr>(CursorInfo.TrailingExpr);
1965+
if (!TryExpr)
1966+
return true;
1967+
auto Range = findSourceRangeToWrapInCatch(CursorInfo, TheFile, SM);
1968+
if (!Range.isValid())
1969+
return true;
1970+
// Wrap given range in do catch block.
1971+
EditConsumer.accept(SM, Range.getStart(), "do {\n");
1972+
EditorConsumerInsertStream OS(EditConsumer, SM, Range.getEnd());
1973+
OS << "\n} catch {\n" << getCodePlaceholder() << "\n}";
1974+
1975+
// Delete ! from try! expression
1976+
auto ExclaimRange = CharSourceRange(TryExpr->getExclaimLoc(), 1);
1977+
EditConsumer.accept(SM, ExclaimRange, "");
1978+
return false;
1979+
}
1980+
19261981
/// Given a cursor position, this function tries to collect a number literal
19271982
/// expression immediately following the cursor.
19281983
static NumberLiteralExpr *getTrailingNumberLiteral(ResolvedCursorInfo Tok) {

lib/IDE/SwiftSourceDocInfo.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,14 @@ bool CursorInfoResolver::walkToExprPre(Expr *E) {
188188
ContainerType = ME->getBase()->getType();
189189
}
190190
}
191-
191+
auto IsProperCursorLocation = E->getStartLoc() == LocToResolve;
192+
// Handle cursor placement between try and ! in ForceTryExpr.
193+
if (auto *FTE = dyn_cast<ForceTryExpr>(E)) {
194+
IsProperCursorLocation = LocToResolve == FTE->getExclaimLoc() ||
195+
IsProperCursorLocation;
196+
}
192197
// Keep track of trailing expressions.
193-
if (!E->isImplicit() && E->getStartLoc() == LocToResolve)
198+
if (!E->isImplicit() && IsProperCursorLocation)
194199
TrailingExprStack.push_back(E);
195200
}
196201
return true;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
func throwingFunc() throws {
2+
return
3+
}
4+
do {
5+
try throwingFunc()
6+
} catch {
7+
<#code#>
8+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
func throwingFunc() throws {
2+
return
3+
}
4+
func foo() {
5+
do {
6+
try throwingFunc()
7+
} catch {
8+
<#code#>
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
func throwingFunc() throws -> [Int] {
2+
return []
3+
}
4+
do {
5+
for num in try throwingFunc() {
6+
let _ = num
7+
}
8+
} catch {
9+
<#code#>
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
func throwingFunc() throws -> Bool {
2+
return true
3+
}
4+
do {
5+
if try throwingFunc() {
6+
let _ = 3
7+
}
8+
} catch {
9+
<#code#>
10+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
func throwingFunc() throws -> Bool {
2+
return true
3+
}
4+
if 4 > 3 {
5+
do {
6+
if try throwingFunc() {
7+
let _ = 3
8+
}
9+
} catch {
10+
<#code#>
11+
}
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
func throwingFunc() throws -> Int? {
2+
return nil
3+
}
4+
do {
5+
if let val = try throwingFunc() {
6+
let _ = val
7+
}
8+
} catch {
9+
<#code#>
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
func throwingFunc() throws -> [Int] {
2+
return []
3+
}
4+
struct X { let array: [Int] }
5+
do {
6+
let _ = X(array: try throwingFunc())
7+
} catch {
8+
<#code#>
9+
}

0 commit comments

Comments
 (0)