14432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain//=== unittests/Sema/ExternalSemaSourceTest.cpp - ExternalSemaSource tests ===//
24432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain//
34432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain//                     The LLVM Compiler Infrastructure
44432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain//
54432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// This file is distributed under the University of Illinois Open Source
64432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// License. See LICENSE.TXT for details.
74432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain//
84432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain//===----------------------------------------------------------------------===//
94432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
104432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "clang/AST/ASTConsumer.h"
114432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "clang/AST/ASTContext.h"
124432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "clang/Frontend/CompilerInstance.h"
134432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "clang/Lex/Preprocessor.h"
144432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "clang/Parse/ParseAST.h"
154432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "clang/Sema/ExternalSemaSource.h"
164432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "clang/Sema/Sema.h"
174432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "clang/Sema/SemaDiagnostic.h"
184432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "clang/Sema/TypoCorrection.h"
194432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "clang/Tooling/Tooling.h"
204432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain#include "gtest/gtest.h"
214432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
224432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrainusing namespace clang;
234432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrainusing namespace clang::tooling;
244432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
254432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrainnamespace {
264432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
275d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain// \brief Counts the number of times MaybeDiagnoseMissingCompleteType
285d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain// is called. Returns the result it was provided on creation.
295d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrainclass CompleteTypeDiagnoser : public clang::ExternalSemaSource {
305d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrainpublic:
315d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  CompleteTypeDiagnoser(bool MockResult) : CallCount(0), Result(MockResult) {}
325d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain
335d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation L, QualType T) {
345d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain    ++CallCount;
355d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain    return Result;
365d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  }
375d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain
385d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  int CallCount;
395d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  bool Result;
405d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain};
415d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain
424432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// \brief Counts the number of err_using_directive_member_suggest diagnostics
434432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// correcting from one namespace to another while still passing all diagnostics
444432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// along a chain of consumers.
454432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrainclass NamespaceDiagnosticWatcher : public clang::DiagnosticConsumer {
464432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  DiagnosticConsumer *Chained;
474432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  std::string FromNS;
484432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  std::string ToNS;
494432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
504432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrainpublic:
514432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  NamespaceDiagnosticWatcher(StringRef From, StringRef To)
52ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      : Chained(nullptr), FromNS(From), ToNS("'"), SeenCount(0) {
534432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    ToNS.append(To);
544432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    ToNS.append("'");
554432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  }
564432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
574432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
584432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain                                const Diagnostic &Info) {
594432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    if (Chained)
604432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      Chained->HandleDiagnostic(DiagLevel, Info);
614432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    if (Info.getID() - 1 == diag::err_using_directive_member_suggest) {
624432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      const IdentifierInfo *Ident = Info.getArgIdentifier(0);
634432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      const std::string &CorrectedQuotedStr = Info.getArgStdStr(1);
644432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      if (Ident->getName() == FromNS && CorrectedQuotedStr == ToNS)
654432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain        ++SeenCount;
664432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    }
674432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  }
684432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
694432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  virtual void clear() {
704432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    DiagnosticConsumer::clear();
714432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    if (Chained)
724432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      Chained->clear();
734432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  }
744432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
754432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  virtual bool IncludeInDiagnosticCounts() const {
764432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    if (Chained)
774432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      return Chained->IncludeInDiagnosticCounts();
784432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    return false;
794432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  }
804432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
814432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  NamespaceDiagnosticWatcher *Chain(DiagnosticConsumer *ToChain) {
824432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    Chained = ToChain;
834432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    return this;
844432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  }
854432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
864432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  int SeenCount;
874432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain};
884432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
894432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// \brief Always corrects a typo matching CorrectFrom with a new namespace
904432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// with the name CorrectTo.
914432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrainclass NamespaceTypoProvider : public clang::ExternalSemaSource {
924432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  std::string CorrectFrom;
934432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  std::string CorrectTo;
944432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  Sema *CurrentSema;
954432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
964432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrainpublic:
974432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  NamespaceTypoProvider(StringRef From, StringRef To)
98ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      : CorrectFrom(From), CorrectTo(To), CurrentSema(nullptr), CallCount(0) {}
994432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
1004432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  virtual void InitializeSema(Sema &S) { CurrentSema = &S; }
1014432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
102ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  virtual void ForgetSema() { CurrentSema = nullptr; }
1034432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
1044432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  virtual TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
1054432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain                                     int LookupKind, Scope *S, CXXScopeSpec *SS,
1064432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain                                     CorrectionCandidateCallback &CCC,
1074432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain                                     DeclContext *MemberContext,
1084432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain                                     bool EnteringContext,
1094432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain                                     const ObjCObjectPointerType *OPT) {
1104432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    ++CallCount;
1114432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    if (CurrentSema && Typo.getName().getAsString() == CorrectFrom) {
112ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      DeclContext *DestContext = nullptr;
1134432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      ASTContext &Context = CurrentSema->getASTContext();
114ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      if (SS)
1154432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain        DestContext = CurrentSema->computeDeclContext(*SS, EnteringContext);
116ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      if (!DestContext)
1174432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain        DestContext = Context.getTranslationUnitDecl();
1184432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      IdentifierInfo *ToIdent =
1194432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain          CurrentSema->getPreprocessor().getIdentifierInfo(CorrectTo);
1204432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      NamespaceDecl *NewNamespace =
1214432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain          NamespaceDecl::Create(Context, DestContext, false, Typo.getBeginLoc(),
122ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                Typo.getLoc(), ToIdent, nullptr);
1234432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      DestContext->addDecl(NewNamespace);
1244432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      TypoCorrection Correction(ToIdent);
1254432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      Correction.addCorrectionDecl(NewNamespace);
1264432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      return Correction;
1274432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    }
1284432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    return TypoCorrection();
1294432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  }
1304432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
1314432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  int CallCount;
1324432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain};
1334432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
1344432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// \brief Chains together a vector of NamespaceDiagnosticWatchers and
1354432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// adds a vector of ExternalSemaSources to the CompilerInstance before
1364432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// performing semantic analysis.
1374432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrainclass ExternalSemaSourceInstaller : public clang::ASTFrontendAction {
1384432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  std::vector<NamespaceDiagnosticWatcher *> Watchers;
1394432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  std::vector<clang::ExternalSemaSource *> Sources;
140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<DiagnosticConsumer> OwnedClient;
1414432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
1424432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrainprotected:
1434432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  virtual clang::ASTConsumer *
1444432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  CreateASTConsumer(clang::CompilerInstance &Compiler,
1454432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain                    llvm::StringRef /* dummy */) {
1464432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    return new clang::ASTConsumer();
1474432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  }
1484432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
1494432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  virtual void ExecuteAction() {
1504432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    CompilerInstance &CI = getCompilerInstance();
1514432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    ASSERT_FALSE(CI.hasSema());
152ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    CI.createSema(getTranslationUnitKind(), nullptr);
1534432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    ASSERT_TRUE(CI.hasDiagnostics());
1544432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    DiagnosticsEngine &Diagnostics = CI.getDiagnostics();
1554432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    DiagnosticConsumer *Client = Diagnostics.getClient();
1564432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    if (Diagnostics.ownsClient())
1574432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      OwnedClient.reset(Diagnostics.takeClient());
1584432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    for (size_t I = 0, E = Watchers.size(); I < E; ++I)
1594432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      Client = Watchers[I]->Chain(Client);
1604432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    Diagnostics.setClient(Client, false);
1614432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    for (size_t I = 0, E = Sources.size(); I < E; ++I) {
1624432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      Sources[I]->InitializeSema(CI.getSema());
1634432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      CI.getSema().addExternalSource(Sources[I]);
1644432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    }
1654432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats,
1664432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain             CI.getFrontendOpts().SkipFunctionBodies);
1674432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  }
1684432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
1694432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrainpublic:
1704432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  void PushSource(clang::ExternalSemaSource *Source) {
1714432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    Sources.push_back(Source);
1724432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  }
1734432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
1744432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  void PushWatcher(NamespaceDiagnosticWatcher *Watcher) {
1754432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain    Watchers.push_back(Watcher);
1764432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  }
1774432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain};
1784432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
1794432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// Make sure that the NamespaceDiagnosticWatcher is not miscounting.
1804432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn UhrainTEST(ExternalSemaSource, SanityCheck) {
181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<ExternalSemaSourceInstaller> Installer(
1824432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      new ExternalSemaSourceInstaller);
1834432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  NamespaceDiagnosticWatcher Watcher("AAB", "BBB");
1844432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  Installer->PushWatcher(&Watcher);
1854432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  std::vector<std::string> Args(1, "-std=c++11");
1864432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs(
187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Installer.release(), "namespace AAA { } using namespace AAB;", Args));
1884432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  ASSERT_EQ(0, Watcher.SeenCount);
1894432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain}
1904432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
1914432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// Check that when we add a NamespaceTypeProvider, we use that suggestion
1924432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// instead of the usual suggestion we would use above.
1934432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn UhrainTEST(ExternalSemaSource, ExternalTypoCorrectionPrioritized) {
194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<ExternalSemaSourceInstaller> Installer(
1954432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      new ExternalSemaSourceInstaller);
1964432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  NamespaceTypoProvider Provider("AAB", "BBB");
1974432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  NamespaceDiagnosticWatcher Watcher("AAB", "BBB");
1984432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  Installer->PushSource(&Provider);
1994432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  Installer->PushWatcher(&Watcher);
2004432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  std::vector<std::string> Args(1, "-std=c++11");
2014432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs(
202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Installer.release(), "namespace AAA { } using namespace AAB;", Args));
2034432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  ASSERT_LE(0, Provider.CallCount);
2044432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  ASSERT_EQ(1, Watcher.SeenCount);
2054432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain}
2064432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
2074432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// Check that we use the first successful TypoCorrection returned from an
2084432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain// ExternalSemaSource.
2094432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn UhrainTEST(ExternalSemaSource, ExternalTypoCorrectionOrdering) {
210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<ExternalSemaSourceInstaller> Installer(
2114432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain      new ExternalSemaSourceInstaller);
2124432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  NamespaceTypoProvider First("XXX", "BBB");
2134432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  NamespaceTypoProvider Second("AAB", "CCC");
2144432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  NamespaceTypoProvider Third("AAB", "DDD");
2154432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  NamespaceDiagnosticWatcher Watcher("AAB", "CCC");
2164432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  Installer->PushSource(&First);
2174432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  Installer->PushSource(&Second);
2184432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  Installer->PushSource(&Third);
2194432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  Installer->PushWatcher(&Watcher);
2204432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  std::vector<std::string> Args(1, "-std=c++11");
2214432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs(
222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Installer.release(), "namespace AAA { } using namespace AAB;", Args));
2234432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  ASSERT_LE(1, First.CallCount);
2244432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  ASSERT_LE(1, Second.CallCount);
2254432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  ASSERT_EQ(0, Third.CallCount);
2264432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain  ASSERT_EQ(1, Watcher.SeenCount);
2274432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain}
2284432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain
2295d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain// We should only try MaybeDiagnoseMissingCompleteType if we can't otherwise
2305d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain// solve the problem.
2315d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn UhrainTEST(ExternalSemaSource, TryOtherTacticsBeforeDiagnosing) {
232651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<ExternalSemaSourceInstaller> Installer(
2335d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain      new ExternalSemaSourceInstaller);
2345d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  CompleteTypeDiagnoser Diagnoser(false);
2355d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  Installer->PushSource(&Diagnoser);
2365d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  std::vector<std::string> Args(1, "-std=c++11");
2375d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  // This code hits the class template specialization/class member of a class
2385d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  // template specialization checks in Sema::RequireCompleteTypeImpl.
2395d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs(
240651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Installer.release(),
2415d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain      "template <typename T> struct S { class C { }; }; S<char>::C SCInst;",
2425d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain      Args));
2435d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  ASSERT_EQ(0, Diagnoser.CallCount);
2445d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain}
2455d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain
2465d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain// The first ExternalSemaSource where MaybeDiagnoseMissingCompleteType returns
2475d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain// true should be the last one called.
2485d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn UhrainTEST(ExternalSemaSource, FirstDiagnoserTaken) {
249651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<ExternalSemaSourceInstaller> Installer(
2505d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain      new ExternalSemaSourceInstaller);
2515d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  CompleteTypeDiagnoser First(false);
2525d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  CompleteTypeDiagnoser Second(true);
2535d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  CompleteTypeDiagnoser Third(true);
2545d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  Installer->PushSource(&First);
2555d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  Installer->PushSource(&Second);
2565d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  Installer->PushSource(&Third);
2575d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  std::vector<std::string> Args(1, "-std=c++11");
2585d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  ASSERT_FALSE(clang::tooling::runToolOnCodeWithArgs(
259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Installer.release(), "class Incomplete; Incomplete IncompleteInstance;",
2605d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain      Args));
2615d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  ASSERT_EQ(1, First.CallCount);
2625d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  ASSERT_EQ(1, Second.CallCount);
2635d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain  ASSERT_EQ(0, Third.CallCount);
2645d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain}
2655d937b3fe7832f8ffa0a258d1b037c64708e97c1Kaelyn Uhrain
2664432bf007abb40cdbe2679dd94ec5b11c5795355Kaelyn Uhrain} // anonymous namespace
267