Add a callback for recovering using a typo correction.

Also keep track of the stack of Exprs visited during the tree transform
so the callback can be passed the parent of the TypoExpr.

llvm-svn: 220697
This commit is contained in:
Kaelyn Takata 2014-10-27 18:07:42 +00:00
parent 9ab7fb6b73
commit 8363f04ee6
4 changed files with 27 additions and 14 deletions

View File

@ -2592,6 +2592,8 @@ public:
bool VolatileThis);
typedef std::function<void(const TypoCorrection &)> TypoDiagnosticGenerator;
typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)>
TypoRecoveryCallback;
private:
bool CppLookupName(LookupResult &R, Scope *S);
@ -2599,6 +2601,7 @@ private:
struct TypoExprState {
std::unique_ptr<TypoCorrectionConsumer> Consumer;
TypoDiagnosticGenerator DiagHandler;
TypoRecoveryCallback RecoveryHandler;
};
/// \brief The set of unhandled TypoExprs and their associated state.
@ -2606,7 +2609,8 @@ private:
/// \brief Creates a new TypoExpr AST node.
TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
TypoDiagnosticGenerator TDG);
TypoDiagnosticGenerator TDG,
TypoRecoveryCallback TRC);
// \brief The set of known/encountered (unique, canonicalized) NamespaceDecls.
//
@ -2718,7 +2722,7 @@ public:
CXXScopeSpec *SS,
std::unique_ptr<CorrectionCandidateCallback> CCC,
TypoDiagnosticGenerator TDG,
CorrectTypoKind Mode,
TypoRecoveryCallback TRC, CorrectTypoKind Mode,
DeclContext *MemberContext = nullptr,
bool EnteringContext = false,
const ObjCObjectPointerType *OPT = nullptr);

View File

@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Ownership.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {

View File

@ -5996,13 +5996,17 @@ public:
// For the first TypoExpr and an uncached TypoExpr, find the next likely
// typo correction and return it.
while (TypoCorrection TC = State.Consumer->getNextCorrection()) {
LookupResult R(SemaRef,
State.Consumer->getLookupResult().getLookupNameInfo(),
State.Consumer->getLookupResult().getLookupKind());
if (!TC.isKeyword())
R.addDecl(TC.getCorrectionDecl());
ExprResult NE =
SemaRef.BuildDeclarationNameExpr(CXXScopeSpec(), R, false);
ExprResult NE;
if (State.RecoveryHandler) {
NE = State.RecoveryHandler(SemaRef, E, TC);
} else {
LookupResult R(SemaRef,
State.Consumer->getLookupResult().getLookupNameInfo(),
State.Consumer->getLookupResult().getLookupKind());
if (!TC.isKeyword())
R.addDecl(TC.getCorrectionDecl());
NE = SemaRef.BuildDeclarationNameExpr(CXXScopeSpec(), R, false);
}
assert(!NE.isUnset() &&
"Typo was transformed into a valid-but-null ExprResult");
if (!NE.isInvalid())

View File

@ -4332,6 +4332,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
/// \param TDG A TypoDiagnosticGenerator functor that will be used to print
/// diagnostics when the actual typo correction is attempted.
///
/// \param TRC A TypoRecoveryCallback functor that will be used to build an
/// Expr from a typo correction candidate.
///
/// \param MemberContext if non-NULL, the context in which to look for
/// a member access expression.
///
@ -4350,7 +4353,7 @@ TypoExpr *Sema::CorrectTypoDelayed(
const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS,
std::unique_ptr<CorrectionCandidateCallback> CCC,
TypoDiagnosticGenerator TDG, CorrectTypoKind Mode,
TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode,
DeclContext *MemberContext, bool EnteringContext,
const ObjCObjectPointerType *OPT) {
assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback");
@ -4375,7 +4378,7 @@ TypoExpr *Sema::CorrectTypoDelayed(
return nullptr;
ExprEvalContexts.back().NumTypos++;
return createDelayedTypo(std::move(Consumer), std::move(TDG));
return createDelayedTypo(std::move(Consumer), std::move(TDG), std::move(TRC));
}
void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
@ -4575,14 +4578,15 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
<< CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
}
TypoExpr *
Sema::createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
TypoDiagnosticGenerator TDG) {
TypoExpr *Sema::createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
TypoDiagnosticGenerator TDG,
TypoRecoveryCallback TRC) {
assert(TCC && "createDelayedTypo requires a valid TypoCorrectionConsumer");
auto TE = new (Context) TypoExpr(Context.DependentTy);
auto &State = DelayedTypos[TE];
State.Consumer = std::move(TCC);
State.DiagHandler = std::move(TDG);
State.RecoveryHandler = std::move(TRC);
return TE;
}