summaryrefslogtreecommitdiffstats
path: root/unittests/Sema
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2016-05-19 10:46:10 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2016-05-19 10:46:10 +0000
commit38d99f6be1ba2f56c118c3ed970018a386de5add (patch)
tree7938af38d89eca0a1c5c17689e5a56fe51b5ef36 /unittests/Sema
parent6a15942a75b0e1cf99f738ebc2d7394626881f34 (diff)
[Sema] Allow an external sema source to handle delayed typo corrections.
This probably isn't perfectly perfect but allows correcting function calls again. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@270039 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/Sema')
-rw-r--r--unittests/Sema/ExternalSemaSourceTest.cpp101
1 files changed, 80 insertions, 21 deletions
diff --git a/unittests/Sema/ExternalSemaSourceTest.cpp b/unittests/Sema/ExternalSemaSourceTest.cpp
index 703e97b4ac..d2cdd633fa 100644
--- a/unittests/Sema/ExternalSemaSourceTest.cpp
+++ b/unittests/Sema/ExternalSemaSourceTest.cpp
@@ -39,19 +39,18 @@ public:
bool Result;
};
-// \brief Counts the number of err_using_directive_member_suggest diagnostics
-// correcting from one namespace to another while still passing all diagnostics
-// along a chain of consumers.
-class NamespaceDiagnosticWatcher : public clang::DiagnosticConsumer {
+/// Counts the number of typo-correcting diagnostics correcting from one name to
+/// another while still passing all diagnostics along a chain of consumers.
+class DiagnosticWatcher : public clang::DiagnosticConsumer {
DiagnosticConsumer *Chained;
- std::string FromNS;
- std::string ToNS;
+ std::string FromName;
+ std::string ToName;
public:
- NamespaceDiagnosticWatcher(StringRef From, StringRef To)
- : Chained(nullptr), FromNS(From), ToNS("'"), SeenCount(0) {
- ToNS.append(To);
- ToNS.append("'");
+ DiagnosticWatcher(StringRef From, StringRef To)
+ : Chained(nullptr), FromName(From), ToName("'"), SeenCount(0) {
+ ToName.append(To);
+ ToName.append("'");
}
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
@@ -61,7 +60,12 @@ public:
if (Info.getID() - 1 == diag::err_using_directive_member_suggest) {
const IdentifierInfo *Ident = Info.getArgIdentifier(0);
const std::string &CorrectedQuotedStr = Info.getArgStdStr(1);
- if (Ident->getName() == FromNS && CorrectedQuotedStr == ToNS)
+ if (Ident->getName() == FromName && CorrectedQuotedStr == ToName)
+ ++SeenCount;
+ } else if (Info.getID() == diag::err_no_member_suggest) {
+ auto Ident = DeclarationName::getFromOpaqueInteger(Info.getRawArg(0));
+ const std::string &CorrectedQuotedStr = Info.getArgStdStr(3);
+ if (Ident.getAsString() == FromName && CorrectedQuotedStr == ToName)
++SeenCount;
}
}
@@ -78,7 +82,7 @@ public:
return false;
}
- NamespaceDiagnosticWatcher *Chain(DiagnosticConsumer *ToChain) {
+ DiagnosticWatcher *Chain(DiagnosticConsumer *ToChain) {
Chained = ToChain;
return this;
}
@@ -130,11 +134,53 @@ public:
int CallCount;
};
-// \brief Chains together a vector of NamespaceDiagnosticWatchers and
+class FunctionTypoProvider : public clang::ExternalSemaSource {
+ std::string CorrectFrom;
+ std::string CorrectTo;
+ Sema *CurrentSema;
+
+public:
+ FunctionTypoProvider(StringRef From, StringRef To)
+ : CorrectFrom(From), CorrectTo(To), CurrentSema(nullptr), CallCount(0) {}
+
+ void InitializeSema(Sema &S) override { CurrentSema = &S; }
+
+ void ForgetSema() override { CurrentSema = nullptr; }
+
+ TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, int LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext, bool EnteringContext,
+ const ObjCObjectPointerType *OPT) override {
+ ++CallCount;
+ if (CurrentSema && Typo.getName().getAsString() == CorrectFrom) {
+ DeclContext *DestContext = nullptr;
+ ASTContext &Context = CurrentSema->getASTContext();
+ if (SS)
+ DestContext = CurrentSema->computeDeclContext(*SS, EnteringContext);
+ if (!DestContext)
+ DestContext = Context.getTranslationUnitDecl();
+ IdentifierInfo *ToIdent =
+ CurrentSema->getPreprocessor().getIdentifierInfo(CorrectTo);
+ auto *NewFunction = FunctionDecl::Create(
+ Context, DestContext, SourceLocation(), SourceLocation(), ToIdent,
+ Context.getFunctionType(Context.VoidTy, {}, {}), nullptr, SC_Static);
+ DestContext->addDecl(NewFunction);
+ TypoCorrection Correction(ToIdent);
+ Correction.addCorrectionDecl(NewFunction);
+ return Correction;
+ }
+ return TypoCorrection();
+ }
+
+ int CallCount;
+};
+
+// \brief Chains together a vector of DiagnosticWatchers and
// adds a vector of ExternalSemaSources to the CompilerInstance before
// performing semantic analysis.
class ExternalSemaSourceInstaller : public clang::ASTFrontendAction {
- std::vector<NamespaceDiagnosticWatcher *> Watchers;
+ std::vector<DiagnosticWatcher *> Watchers;
std::vector<clang::ExternalSemaSource *> Sources;
std::unique_ptr<DiagnosticConsumer> OwnedClient;
@@ -170,16 +216,14 @@ public:
Sources.push_back(Source);
}
- void PushWatcher(NamespaceDiagnosticWatcher *Watcher) {
- Watchers.push_back(Watcher);
- }
+ void PushWatcher(DiagnosticWatcher *Watcher) { Watchers.push_back(Watcher); }
};
-// Make sure that the NamespaceDiagnosticWatcher is not miscounting.
+// Make sure that the DiagnosticWatcher is not miscounting.
TEST(ExternalSemaSource, SanityCheck) {
std::unique_ptr<ExternalSemaSourceInstaller> Installer(
new ExternalSemaSourceInstaller);
- NamespaceDiagnosticWatcher Watcher("AAB", "BBB");
+ DiagnosticWatcher Watcher("AAB", "BBB");
Installer->PushWatcher(&Watcher);
std::vector<std::string> Args(1, "-std=c++11");
ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs(
@@ -193,7 +237,7 @@ TEST(ExternalSemaSource, ExternalTypoCorrectionPrioritized) {
std::unique_ptr<ExternalSemaSourceInstaller> Installer(
new ExternalSemaSourceInstaller);
NamespaceTypoProvider Provider("AAB", "BBB");
- NamespaceDiagnosticWatcher Watcher("AAB", "BBB");
+ DiagnosticWatcher Watcher("AAB", "BBB");
Installer->PushSource(&Provider);
Installer->PushWatcher(&Watcher);
std::vector<std::string> Args(1, "-std=c++11");
@@ -211,7 +255,7 @@ TEST(ExternalSemaSource, ExternalTypoCorrectionOrdering) {
NamespaceTypoProvider First("XXX", "BBB");
NamespaceTypoProvider Second("AAB", "CCC");
NamespaceTypoProvider Third("AAB", "DDD");
- NamespaceDiagnosticWatcher Watcher("AAB", "CCC");
+ DiagnosticWatcher Watcher("AAB", "CCC");
Installer->PushSource(&First);
Installer->PushSource(&Second);
Installer->PushSource(&Third);
@@ -225,6 +269,21 @@ TEST(ExternalSemaSource, ExternalTypoCorrectionOrdering) {
ASSERT_EQ(1, Watcher.SeenCount);
}
+TEST(ExternalSemaSource, ExternalDelayedTypoCorrection) {
+ std::unique_ptr<ExternalSemaSourceInstaller> Installer(
+ new ExternalSemaSourceInstaller);
+ FunctionTypoProvider Provider("aaa", "bbb");
+ DiagnosticWatcher Watcher("aaa", "bbb");
+ Installer->PushSource(&Provider);
+ Installer->PushWatcher(&Watcher);
+ std::vector<std::string> Args(1, "-std=c++11");
+ ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs(
+ Installer.release(), "namespace AAA { } void foo() { AAA::aaa(); }",
+ Args));
+ ASSERT_LE(0, Provider.CallCount);
+ ASSERT_EQ(1, Watcher.SeenCount);
+}
+
// We should only try MaybeDiagnoseMissingCompleteType if we can't otherwise
// solve the problem.
TEST(ExternalSemaSource, TryOtherTacticsBeforeDiagnosing) {