mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Refactoring] Move ConvertToDoCatch to its own file
This commit is contained in:
@@ -5,6 +5,7 @@ add_swift_host_library(swiftRefactoring STATIC
|
|||||||
ConvertStringConcatenationToInterpolation.cpp
|
ConvertStringConcatenationToInterpolation.cpp
|
||||||
ConvertGuardExprToIfLetExpr.cpp
|
ConvertGuardExprToIfLetExpr.cpp
|
||||||
ConvertIfLetExprToGuardExpr.cpp
|
ConvertIfLetExprToGuardExpr.cpp
|
||||||
|
ConvertToDoCatch.cpp
|
||||||
ConvertToSwitchStmt.cpp
|
ConvertToSwitchStmt.cpp
|
||||||
ConvertToTernaryExpr.cpp
|
ConvertToTernaryExpr.cpp
|
||||||
ExpandSwitchCases.cpp
|
ExpandSwitchCases.cpp
|
||||||
|
|||||||
73
lib/Refactoring/ConvertToDoCatch.cpp
Normal file
73
lib/Refactoring/ConvertToDoCatch.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See https://swift.org/LICENSE.txt for license information
|
||||||
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "ContextFinder.h"
|
||||||
|
#include "RefactoringActions.h"
|
||||||
|
#include "swift/AST/Stmt.h"
|
||||||
|
|
||||||
|
using namespace swift::refactoring;
|
||||||
|
|
||||||
|
static CharSourceRange
|
||||||
|
findSourceRangeToWrapInCatch(const ResolvedExprStartCursorInfo &CursorInfo,
|
||||||
|
SourceFile *TheFile, SourceManager &SM) {
|
||||||
|
Expr *E = CursorInfo.getTrailingExpr();
|
||||||
|
if (!E)
|
||||||
|
return CharSourceRange();
|
||||||
|
auto Node = ASTNode(E);
|
||||||
|
auto NodeChecker = [](ASTNode N) { return N.isStmt(StmtKind::Brace); };
|
||||||
|
ContextFinder Finder(*TheFile, Node, NodeChecker);
|
||||||
|
Finder.resolve();
|
||||||
|
auto Contexts = Finder.getContexts();
|
||||||
|
if (Contexts.empty())
|
||||||
|
return CharSourceRange();
|
||||||
|
auto TargetNode = Contexts.back();
|
||||||
|
BraceStmt *BStmt = dyn_cast<BraceStmt>(TargetNode.dyn_cast<Stmt *>());
|
||||||
|
auto ConvertToCharRange = [&SM](SourceRange SR) {
|
||||||
|
return Lexer::getCharSourceRangeFromSourceRange(SM, SR);
|
||||||
|
};
|
||||||
|
assert(BStmt);
|
||||||
|
auto ExprRange = ConvertToCharRange(E->getSourceRange());
|
||||||
|
// Check elements of the deepest BraceStmt, pick one that covers expression.
|
||||||
|
for (auto Elem : BStmt->getElements()) {
|
||||||
|
auto ElemRange = ConvertToCharRange(Elem.getSourceRange());
|
||||||
|
if (ElemRange.contains(ExprRange))
|
||||||
|
TargetNode = Elem;
|
||||||
|
}
|
||||||
|
return ConvertToCharRange(TargetNode.getSourceRange());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RefactoringActionConvertToDoCatch::isApplicable(ResolvedCursorInfoPtr Tok,
|
||||||
|
DiagnosticEngine &Diag) {
|
||||||
|
auto ExprStartInfo = dyn_cast<ResolvedExprStartCursorInfo>(Tok);
|
||||||
|
if (!ExprStartInfo || !ExprStartInfo->getTrailingExpr())
|
||||||
|
return false;
|
||||||
|
return isa<ForceTryExpr>(ExprStartInfo->getTrailingExpr());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RefactoringActionConvertToDoCatch::performChange() {
|
||||||
|
auto ExprStartInfo = cast<ResolvedExprStartCursorInfo>(CursorInfo);
|
||||||
|
auto *TryExpr = dyn_cast<ForceTryExpr>(ExprStartInfo->getTrailingExpr());
|
||||||
|
assert(TryExpr);
|
||||||
|
auto Range = findSourceRangeToWrapInCatch(*ExprStartInfo, TheFile, SM);
|
||||||
|
if (!Range.isValid())
|
||||||
|
return true;
|
||||||
|
// Wrap given range in do catch block.
|
||||||
|
EditConsumer.accept(SM, Range.getStart(), "do {\n");
|
||||||
|
EditorConsumerInsertStream OS(EditConsumer, SM, Range.getEnd());
|
||||||
|
OS << "\n} catch {\n" << getCodePlaceholder() << "\n}";
|
||||||
|
|
||||||
|
// Delete ! from try! expression
|
||||||
|
auto ExclaimLen = getKeywordLen(tok::exclaim_postfix);
|
||||||
|
auto ExclaimRange = CharSourceRange(TryExpr->getExclaimLoc(), ExclaimLen);
|
||||||
|
EditConsumer.remove(SM, ExclaimRange);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -566,62 +566,6 @@ collectRefactoringsAtCursor(SourceFile *SF, unsigned Line, unsigned Column,
|
|||||||
return collectRefactorings(Tok, /*ExcludeRename=*/false);
|
return collectRefactorings(Tok, /*ExcludeRename=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CharSourceRange
|
|
||||||
findSourceRangeToWrapInCatch(const ResolvedExprStartCursorInfo &CursorInfo,
|
|
||||||
SourceFile *TheFile, SourceManager &SM) {
|
|
||||||
Expr *E = CursorInfo.getTrailingExpr();
|
|
||||||
if (!E)
|
|
||||||
return CharSourceRange();
|
|
||||||
auto Node = ASTNode(E);
|
|
||||||
auto NodeChecker = [](ASTNode N) { return N.isStmt(StmtKind::Brace); };
|
|
||||||
ContextFinder Finder(*TheFile, Node, NodeChecker);
|
|
||||||
Finder.resolve();
|
|
||||||
auto Contexts = Finder.getContexts();
|
|
||||||
if (Contexts.empty())
|
|
||||||
return CharSourceRange();
|
|
||||||
auto TargetNode = Contexts.back();
|
|
||||||
BraceStmt *BStmt = dyn_cast<BraceStmt>(TargetNode.dyn_cast<Stmt*>());
|
|
||||||
auto ConvertToCharRange = [&SM](SourceRange SR) {
|
|
||||||
return Lexer::getCharSourceRangeFromSourceRange(SM, SR);
|
|
||||||
};
|
|
||||||
assert(BStmt);
|
|
||||||
auto ExprRange = ConvertToCharRange(E->getSourceRange());
|
|
||||||
// Check elements of the deepest BraceStmt, pick one that covers expression.
|
|
||||||
for (auto Elem: BStmt->getElements()) {
|
|
||||||
auto ElemRange = ConvertToCharRange(Elem.getSourceRange());
|
|
||||||
if (ElemRange.contains(ExprRange))
|
|
||||||
TargetNode = Elem;
|
|
||||||
}
|
|
||||||
return ConvertToCharRange(TargetNode.getSourceRange());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RefactoringActionConvertToDoCatch::isApplicable(ResolvedCursorInfoPtr Tok,
|
|
||||||
DiagnosticEngine &Diag) {
|
|
||||||
auto ExprStartInfo = dyn_cast<ResolvedExprStartCursorInfo>(Tok);
|
|
||||||
if (!ExprStartInfo || !ExprStartInfo->getTrailingExpr())
|
|
||||||
return false;
|
|
||||||
return isa<ForceTryExpr>(ExprStartInfo->getTrailingExpr());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RefactoringActionConvertToDoCatch::performChange() {
|
|
||||||
auto ExprStartInfo = cast<ResolvedExprStartCursorInfo>(CursorInfo);
|
|
||||||
auto *TryExpr = dyn_cast<ForceTryExpr>(ExprStartInfo->getTrailingExpr());
|
|
||||||
assert(TryExpr);
|
|
||||||
auto Range = findSourceRangeToWrapInCatch(*ExprStartInfo, TheFile, SM);
|
|
||||||
if (!Range.isValid())
|
|
||||||
return true;
|
|
||||||
// Wrap given range in do catch block.
|
|
||||||
EditConsumer.accept(SM, Range.getStart(), "do {\n");
|
|
||||||
EditorConsumerInsertStream OS(EditConsumer, SM, Range.getEnd());
|
|
||||||
OS << "\n} catch {\n" << getCodePlaceholder() << "\n}";
|
|
||||||
|
|
||||||
// Delete ! from try! expression
|
|
||||||
auto ExclaimLen = getKeywordLen(tok::exclaim_postfix);
|
|
||||||
auto ExclaimRange = CharSourceRange(TryExpr->getExclaimLoc(), ExclaimLen);
|
|
||||||
EditConsumer.remove(SM, ExclaimRange);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a cursor position, this function tries to collect a number literal
|
/// Given a cursor position, this function tries to collect a number literal
|
||||||
/// expression immediately following the cursor.
|
/// expression immediately following the cursor.
|
||||||
static NumberLiteralExpr *getTrailingNumberLiteral(ResolvedCursorInfoPtr Tok) {
|
static NumberLiteralExpr *getTrailingNumberLiteral(ResolvedCursorInfoPtr Tok) {
|
||||||
|
|||||||
Reference in New Issue
Block a user