void PrintTo(const TranslationUnit &translationUnit, ::std::ostream *os)
{
    *os << "TranslationUnit("
        << translationUnit.filePath().constData() << ", "
        << translationUnit.projectPartId().constData() << ", "
        << translationUnit.documentRevision() << ")";
}
Exemple #2
0
int test_main(int argc, char * argv[])
{
   try
   { 
      // setup log
      initializeStderrLog("coredev", ::core::system::kLogLevelWarning);

      // ignore sigpipe
      Error error = ::core::system::ignoreSignal(::core::system::SigPipe);
      if (error)
         LOG_ERROR(error);

      // write a C++ file
      std::string cpp =
        "#include <string>\n"
        "class X { public:\n"
        "   void test(int y, int x = 10);\n"
        "}\n"
        "void X::test(int y, int x) {}\n"
        "void foobar() {\n"
        "   X x;\n"
        "   x."
        "}";
      std::ofstream ostr("foo.cpp");
      ostr << cpp;
      ostr.close();

      // load libclang
      using namespace libclang;
      std::string diagnostics;
      clang().load(EmbeddedLibrary(), LibraryVersion(3,4,0), &diagnostics);
      if (!clang().isLoaded())
      {
         std::cerr << "Failed to load libclang: " << diagnostics << std::endl;
         return EXIT_FAILURE;
      }

      // create a source index and get a translation unit for it
      SourceIndex sourceIndex;
      TranslationUnit tu = sourceIndex.getTranslationUnit("foo.cpp");
      if (tu.empty())
      {
         std::cerr << "No translation unit foo.cpp" << std::endl;
         return EXIT_FAILURE;
      }

      // code complete
      CodeCompleteResults results = tu.codeCompleteAt("foo.cpp", 8, 6);
      for (unsigned i = 0; i<results.getNumResults(); i++) {
        std::cout << results.getResult(i).getTypedText() << std::endl;
        std::cout << "   " << results.getResult(i).getText() << std::endl;
      }

      return EXIT_SUCCESS;
   }
   CATCH_UNEXPECTED_EXCEPTION
   
   // if we got this far we had an unexpected exception
   return EXIT_FAILURE ;
}
IAsyncJob::AsyncPrepareResult UpdateAnnotationsJob::prepareAsyncRun()
{
    const JobRequest jobRequest = context().jobRequest;
    QTC_ASSERT(isExpectedJobRequestType(jobRequest), return AsyncPrepareResult());
    QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());

    const TranslationUnit translationUnit = *m_translationUnit;
    const TranslationUnitUpdateInput updateInput = createUpdateInput(m_pinnedDocument);
    setRunner([translationUnit, updateInput]() {
        TIME_SCOPE_DURATION("UpdateAnnotationsJobRunner");

        // Update
        UpdateAnnotationsJob::AsyncResult asyncResult;
        asyncResult.updateResult = translationUnit.update(updateInput);

        // Collect
        translationUnit.extractAnnotations(asyncResult.firstHeaderErrorDiagnostic,
                                           asyncResult.diagnostics,
                                           asyncResult.tokenInfos,
                                           asyncResult.skippedSourceRanges);
        asyncResult.unresolvedFilePaths.unite(
            unresolvedFilePaths({asyncResult.firstHeaderErrorDiagnostic}));
        asyncResult.unresolvedFilePaths.unite(unresolvedFilePaths(asyncResult.diagnostics));

        return asyncResult;
    });

    return AsyncPrepareResult{translationUnit.id()};
}
Exemple #4
0
bool JobQueue::isJobRequestOutDated(const JobRequest &jobRequest) const
{
    const JobRequest::Requirements requirements = jobRequest.requirements;
    const UnsavedFiles unsavedFiles = m_translationUnits.unsavedFiles();

    if (requirements.testFlag(JobRequest::CurrentUnsavedFiles)) {
        if (jobRequest.unsavedFilesChangeTimePoint != unsavedFiles.lastChangeTimePoint()) {
            qCDebug(jobsLog) << "Removing due to outdated unsaved files:" << jobRequest;
            return true;
        }
    }

    bool projectCheckedAndItExists = false;

    if (requirements.testFlag(JobRequest::DocumentValid)) {
        if (!m_translationUnits.hasTranslationUnit(jobRequest.filePath, jobRequest.projectPartId)) {
            qCDebug(jobsLog) << "Removing due to already closed document:" << jobRequest;
            return true;
        }

        if (!m_projectParts.hasProjectPart(jobRequest.projectPartId)) {
            qCDebug(jobsLog) << "Removing due to already closed project:" << jobRequest;
            return true;
        }
        projectCheckedAndItExists = true;

        const TranslationUnit translationUnit
                = m_translationUnits.translationUnit(jobRequest.filePath, jobRequest.projectPartId);
        if (!translationUnit.isIntact()) {
            qCDebug(jobsLog) << "Removing due to not intact translation unit:" << jobRequest;
            return true;
        }

        if (requirements.testFlag(JobRequest::CurrentDocumentRevision)) {
            if (translationUnit.documentRevision() != jobRequest.documentRevision) {
                qCDebug(jobsLog) << "Removing due to changed document revision:" << jobRequest;
                return true;
            }
        }
    }

    if (requirements.testFlag(JobRequest::CurrentProject)) {
        if (!projectCheckedAndItExists && !m_projectParts.hasProjectPart(jobRequest.projectPartId)) {
            qCDebug(jobsLog) << "Removing due to already closed project:" << jobRequest;
            return true;
        }

        const ProjectPart &project = m_projectParts.project(jobRequest.projectPartId);
        if (project.lastChangeTimePoint() != jobRequest.projectChangeTimePoint) {
            qCDebug(jobsLog) << "Removing due to outdated project:" << jobRequest;
            return true;
        }
    }

    return false;
}
Exemple #5
0
void TranslationUnits::sendDocumentAnnotations(const TranslationUnit &translationUnit)
{
    if (sendDocumentAnnotationsCallback) {
        DocumentAnnotationsChangedMessage message(translationUnit.fileContainer(),
                                                  translationUnit.mainFileDiagnostics(),
                                                  translationUnit.highlightingMarks().toHighlightingMarksContainers(),
                                                  translationUnit.skippedSourceRanges().toSourceRangeContainers());

        sendDocumentAnnotationsCallback(std::move(message));
    }
}
Exemple #6
0
 TranslationUnit *parse(const QByteArray &source,
                        TranslationUnit::ParseMode mode,
                        LanguageFeatures features)
 {
     const StringLiteral *fileId = control->stringLiteral("<stdin>");
     TranslationUnit *unit = new TranslationUnit(control.data(), fileId);
     unit->setSource(source.constData(), source.length());
     unit->setLanguageFeatures(features);
     unit->parse(mode);
     return unit;
 }
Exemple #7
0
TranslationUnitUpdater Document::createUpdater() const
{
    TranslationUnit unit = translationUnit();

    const TranslationUnitUpdateInput updateInput = createUpdateInput();
    TranslationUnitUpdater updater(unit.id(),
                                   unit.cxIndex(),
                                   unit.cxTranslationUnit(),
                                   updateInput);

    return updater;
}
Exemple #8
0
static int priority(const TranslationUnit &translationUnit)
{
    int thePriority = 0;

    if (translationUnit.isUsedByCurrentEditor())
        thePriority += 1000;

    if (translationUnit.isVisibleInEditor())
        thePriority += 100;

    return thePriority;
}
Exemple #9
0
 TranslationUnit *parse(const QByteArray &source,
                        TranslationUnit::ParseMode mode,
                        bool blockErrors = false)
 {
     StringLiteral *fileId = control.findOrInsertStringLiteral("<stdin>");
     TranslationUnit *unit = new TranslationUnit(&control, fileId);
     unit->setObjCEnabled(true);
     unit->setSource(source.constData(), source.length());
     unit->blockErrors(blockErrors);
     unit->parse(mode);
     return unit;
 }
Exemple #10
0
void tst_Lookup::base_class_defined_1()
{
    Overview overview;

    const QByteArray source = "\n"
        "class base {};\n"
        "class derived: public base {};\n";

    Document::Ptr doc = Document::create("base_class_defined_1");
    doc->setSource(source);
    doc->parse();
    doc->check();

    QVERIFY(doc->diagnosticMessages().isEmpty());
    QCOMPARE(doc->globalSymbolCount(), 2U);

    Snapshot snapshot;
    snapshot.insert(doc->fileName(), doc);

    Document::Ptr emptyDoc = Document::create("<empty>");

    Class *baseClass = doc->globalSymbolAt(0)->asClass();
    QVERIFY(baseClass);

    Class *derivedClass = doc->globalSymbolAt(1)->asClass();
    QVERIFY(derivedClass);

    LookupContext ctx(derivedClass, emptyDoc, doc, snapshot);

    const QList<Symbol *> candidates =
        ctx.resolveClass(derivedClass->baseClassAt(0)->name());

    QCOMPARE(candidates.size(), 1);
    QCOMPARE(candidates.at(0), baseClass);

    TranslationUnit *unit = doc->translationUnit();
    QVERIFY(unit != 0);

    TranslationUnitAST *ast = unit->ast()->asTranslationUnit();
    QVERIFY(ast != 0);

    ClassSymbols classSymbols(doc->control());
    classSymbols(ast);

    QCOMPARE(classSymbols.size(), 2);

    const QMap<Class *, ClassSpecifierAST *> classToAST =
            invert(classSymbols.asMap());

    QVERIFY(classToAST.value(baseClass) != 0);
    QVERIFY(classToAST.value(derivedClass) != 0);
}
IAsyncJob::AsyncPrepareResult UpdateExtraDocumentAnnotationsJob::prepareAsyncRun()
{
    const JobRequest jobRequest = context().jobRequest;
    QTC_ASSERT(acquireDocument(), return AsyncPrepareResult());

    const TranslationUnit translationUnit = *m_translationUnit;
    setRunner([translationUnit]() {
        TIME_SCOPE_DURATION("UpdateExtraDocumentAnnotationsJobRunner");
        return translationUnit.fullTokenInfos().toTokenInfoContainers();
    });

    return AsyncPrepareResult{translationUnit.id()};
}
Exemple #12
0
 TranslationUnit *parse(const QByteArray &source,
                        TranslationUnit::ParseMode mode,
                        bool enableObjc,
                        bool qtMocRun)
 {
     const StringLiteral *fileId = control->stringLiteral("<stdin>");
     TranslationUnit *unit = new TranslationUnit(control.data(), fileId);
     unit->setSource(source.constData(), source.length());
     unit->setObjCEnabled(enableObjc);
     unit->setQtMocRunEnabled(qtMocRun);
     unit->parse(mode);
     return unit;
 }
Exemple #13
0
TEST(visit, declTest)
{
    const char* path = "loadsrcs/decl.c";
    CyFlowVisitor* visitor = new CyFlowVisitor();

    EXPECT_EQ( 0 ,cflowSrcParse(path));

    TranslationUnit* unit = TranslationUnit::getInstance();
    unit->accept(visitor);
    visitor->save("dots/decl");
    unit->deleteInstance();
    delete visitor;
}
void tst_Lookup::base_class_defined_1()
{
    Overview overview;

    const QByteArray source = "\n"
        "class base {};\n"
        "class derived: public base {};\n";

    Document::Ptr doc = Document::create("base_class_defined_1");
    doc->setUtf8Source(source);
    doc->parse();
    doc->check();

    QVERIFY(doc->diagnosticMessages().isEmpty());
    QCOMPARE(doc->globalSymbolCount(), 2U);

    Snapshot snapshot;
    snapshot.insert(doc);

    Class *baseClass = doc->globalSymbolAt(0)->asClass();
    QVERIFY(baseClass);

    Class *derivedClass = doc->globalSymbolAt(1)->asClass();
    QVERIFY(derivedClass);

    const LookupContext ctx(doc, snapshot);

    LookupScope *klass = ctx.lookupType(derivedClass->baseClassAt(0)->name(), derivedClass->enclosingScope());
    QVERIFY(klass != 0);

    QCOMPARE(klass->symbols().size(), 1);
    QCOMPARE(klass->symbols().first(), baseClass);

    TranslationUnit *unit = doc->translationUnit();
    QVERIFY(unit != 0);

    TranslationUnitAST *ast = unit->ast()->asTranslationUnit();
    QVERIFY(ast != 0);

    ClassSymbols classSymbols(unit);
    classSymbols(ast);

    QCOMPARE(classSymbols.size(), 2);

    const QMap<Class *, ClassSpecifierAST *> classToAST =
            invert(classSymbols.asMap());

    QVERIFY(classToAST.value(baseClass) != 0);
    QVERIFY(classToAST.value(derivedClass) != 0);
}
TEST_F( TranslationUnitTest, InvalidTranslationUnit ) {

  TranslationUnit unit;

  EXPECT_TRUE( unit.IsCurrentlyUpdating() );

  EXPECT_EQ( std::vector< CompletionData >(),
             unit.CandidatesForLocation( 1, 1, std::vector< UnsavedFile >() ) );

  EXPECT_EQ( Location(),
             unit.GetDeclarationLocation( 1,
                                          1,
                                          std::vector< UnsavedFile >() ) );

  EXPECT_EQ( Location(),
             unit.GetDefinitionLocation( 1,
                                         1,
                                         std::vector< UnsavedFile >() ) );

  EXPECT_EQ( std::string( "Internal error: no translation unit" ),
             unit.GetTypeAtLocation( 1, 1, std::vector< UnsavedFile >() ) );

  EXPECT_EQ( std::string( "Internal error: no translation unit" ),
             unit.GetEnclosingFunctionAtLocation( 1,
                                                  1,
                                                  std::vector< UnsavedFile >()
                                                ) );

  EXPECT_EQ( DocumentationData(),
             unit.GetDocsForLocationInFile( 1,
                                            1,
                                            std::vector< UnsavedFile >(), false
                                          ) );
}
Exemple #16
0
void Symbol::setSourceLocation(unsigned sourceLocation)
{
    _sourceLocation = sourceLocation;

    if (! _sourceLocation) {
        _isGenerated = false;
        _sourceOffset = 0;
    } else {
        TranslationUnit *unit = translationUnit();

        const Token &tk = unit->tokenAt(sourceLocation);

        _isGenerated = tk.f.generated;
        _sourceOffset = tk.offset;
    }
}
/// Currently, we return the end of fileName.cpp
/// \todo take the definitions of the surrounding declarations into account
QList<InsertionLocation> InsertionPointLocator::methodDefinition(
    Declaration *declaration) const
{
    QList<InsertionLocation> result;
    if (!declaration)
        return result;

    const QString declFileName = QString::fromUtf8(declaration->fileName(),
                                                   declaration->fileNameLength());
    QString target = declFileName;
    if (!isSourceFile(declFileName)) {
        Internal::CppToolsPlugin *cpptools = Internal::CppToolsPlugin::instance();
        QString candidate = cpptools->correspondingHeaderOrSource(declFileName);
        if (!candidate.isEmpty())
            target = candidate;
    }

    Document::Ptr doc = m_refactoringChanges->file(target).cppDocument();
    if (doc.isNull())
        return result;

    Snapshot simplified = m_refactoringChanges->snapshot().simplified(doc);
    if (Symbol *s = simplified.findMatchingDefinition(declaration)) {
        if (Function *f = s->asFunction()) {
            if (f->isConst() == declaration->type().isConst()
                    && f->isVolatile() == declaration->type().isVolatile())
                return result;
        }
    }

    TranslationUnit *xUnit = doc->translationUnit();
    unsigned tokenCount = xUnit->tokenCount();
    if (tokenCount < 2) // no tokens available
        return result;

    unsigned line = 0, column = 0;
    xUnit->getTokenEndPosition(xUnit->tokenCount() - 2, &line, &column);

    const QLatin1String prefix("\n\n");
    result.append(InsertionLocation(target, prefix, QString(), line, column));

    return result;
}
IAsyncJob::AsyncPrepareResult UpdateDocumentAnnotationsJob::prepareAsyncRun()
{
    const JobRequest jobRequest = context().jobRequest;
    QTC_ASSERT(jobRequest.type == JobRequest::Type::UpdateDocumentAnnotations,
               return AsyncPrepareResult());

    try {
        m_pinnedDocument = context().documentForJobRequest();
        m_pinnedFileContainer = m_pinnedDocument.fileContainer();

        const TranslationUnit translationUnit
                = m_pinnedDocument.translationUnit(jobRequest.preferredTranslationUnit);
        const TranslationUnitUpdateInput updateInput = m_pinnedDocument.createUpdateInput();
        setRunner([translationUnit, updateInput]() {
            return runAsyncHelper(translationUnit, updateInput);
        });
        return AsyncPrepareResult{translationUnit.id()};

    } catch (const std::exception &exception) {
        qWarning() << "Error in UpdateDocumentAnnotationsJob::prepareAsyncRun:" << exception.what();
        return AsyncPrepareResult();
    }
}
bool operator==(const TranslationUnit &first, const TranslationUnit &second)
{
    return first.filePath() == second.filePath() && first.projectPartId() == second.projectPartId();
}
Exemple #20
0
/*
     Walk the codemodel.
*/
void CodeModelAttributes::createAttributes(TranslationUnit translationUnit)
{
    m_translationUnit = translationUnit;
    parseScope(const_cast<CodeModel::NamespaceScope *>(translationUnit.codeModel()));
}
Exemple #21
0
Error getCppCompletions(const core::json::JsonRpcRequest& request,
                        core::json::JsonRpcResponse* pResponse)
{
   // get params
   std::string docPath, userText;
   int line, column;
   Error error = json::readParams(request.params,
                                  &docPath,
                                  &line,
                                  &column,
                                  &userText);
   if (error)
      return error;

   // resolve the docPath if it's aliased
   FilePath filePath = module_context::resolveAliasedPath(docPath);

   // get the translation unit and do the code completion
   std::string filename = filePath.absolutePath();
   TranslationUnit tu = rSourceIndex().getTranslationUnit(filename);

   if (!tu.empty())
   {
      std::string lastTypedText;
      json::Array completionsJson;
      boost::shared_ptr<CodeCompleteResults> pResults =
                              tu.codeCompleteAt(filename, line, column);
      if (!pResults->empty())
      {
         // get results
         for (unsigned i = 0; i<pResults->getNumResults(); i++)
         {
            CodeCompleteResult result = pResults->getResult(i);

            // filter on user text if we have it
            if (!userText.empty() &&
                !boost::algorithm::starts_with(result.getTypedText(), userText))
            {
               continue;
            }

            // check whether this completion is valid and bail if not
            if (result.getAvailability() != CXAvailability_Available)
            {
               continue;
            }

            std::string typedText = result.getTypedText();

            // if we have the same typed text then just ammend previous result
            if ((typedText == lastTypedText) && !completionsJson.empty())
            {
               json::Object& res = completionsJson.back().get_obj();
               json::Array& text = res["text"].get_array();
               text.push_back(friendlyCompletionText(result));
            }
            else
            {
               completionsJson.push_back(toJson(result));
            }

            lastTypedText = typedText;
         }
      }

      json::Object resultJson;
      resultJson["completions"] = completionsJson;
      pResponse->setResult(resultJson);
   }
   else
   {
      // set null result indicating this file doesn't support completions
      pResponse->setResult(json::Value());
   }

   return Success();
}
Exemple #22
0
        Nameables
        resolve (TranslationUnit& tu,
                 ScopedName const& from,
                 Name const& name)
        {

          if (trace) cerr << "resolve: starting resolution process for \'"
                          << name << "\' from \'" << from << "\'" << endl;

          Nameables r;

          // Check if name is already scoped.
          //
          if (name.scoped ())
          {
            r  = tu.lookup (ScopedName (name));
          }
          else
          {
            // Obtain all nodes corresponding to this scope name.
            //

            for (ScopedName next (from);;)
            {
              Nameables scopes (tu.lookup (next));

              // Lookup the name in each scope.
              //
              for (Nameables::const_iterator
                     i (scopes.begin ()), end (scopes.end ());
                   i != end; ++i)
              {
                if (Scope* s = dynamic_cast<Scope*> (*i))
                {
                  s->lookup (name, r);
                }
              }

              if (r.begin () != r.end () || next.simple ())
              {
                // Found something -or- at the root scope.
                //
                break;
              }

              next = ScopedName (next.begin (), next.end () - 1);
            }
          }

          if (r.begin () == r.end ())
          {
            if (trace) cerr << "resolve: resolution process for \'"
                            << name << "\' from \'" << from << "\' failed."
                            << endl;

            throw NotFound ();
          }
          else
          {
            if (trace) cerr << "resolve: resolution process for \'"
                            << name << "\' from \'" << from << "\' succeeded:"
                            << endl;

            for (Nameables::const_iterator i (r.begin ()), end (r.end ());
                 i != end; ++i)
            {
              if (trace) cerr << "\t\'" << (**i).scoped_name () << "\'"
                              << endl;
            }
          }

          return r;
        }
Exemple #23
0
int main(int argc, char **argv) {
  llvm::cl::ParseCommandLineOptions(argc, argv, "clang-wpa");
  std::vector<ASTUnit*> ASTUnits;

  Program Prog;
  Indexer Idxer(Prog);

  if (InputFilenames.empty())
    return 0;

  DiagnosticOptions DiagOpts;
  llvm::IntrusiveRefCntPtr<Diagnostic> Diags
    = CompilerInstance::createDiagnostics(DiagOpts, argc, argv);
  for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
    const std::string &InFile = InputFilenames[i];
    llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromASTFile(InFile, Diags));
    if (!AST)
      return 1;

    ASTUnits.push_back(AST.take());
  }

  if (ViewCallGraph) {
    llvm::OwningPtr<CallGraph> CG;
    CG.reset(new CallGraph(Prog));

    for (unsigned i = 0, e = ASTUnits.size(); i != e; ++i)
      CG->addTU(ASTUnits[i]->getASTContext());

    CG->ViewCallGraph();
    return 0;
  }

  if (AnalyzeFunction.empty())
    return 0;

  // Feed all ASTUnits to the Indexer.
  for (unsigned i = 0, e = ASTUnits.size(); i != e; ++i) {
    ASTUnitTU *TU = new ASTUnitTU(ASTUnits[i]);
    Idxer.IndexAST(TU);
  }

  Entity Ent = Entity::get(AnalyzeFunction, Prog);
  FunctionDecl *FD;
  TranslationUnit *TU;
  llvm::tie(FD, TU) = Idxer.getDefinitionFor(Ent);

  if (!FD)
    return 0;

  // Create an analysis engine.
  Preprocessor &PP = TU->getPreprocessor();

  // Hard code options for now.
  AnalysisManager AMgr(TU->getASTContext(), PP.getDiagnostics(),
                       PP.getLangOptions(), /* PathDiagnostic */ 0,
                       CreateRegionStoreManager,
                       CreateRangeConstraintManager, &Idxer,
                       /* MaxNodes */ 300000, /* MaxLoop */ 3,
                       /* VisualizeEG */ false, /* VisualizeEGUbi */ false,
                       /* PurgeDead */ true, /* EagerlyAssume */ false,
                       /* TrimGraph */ false, /* InlineCall */ true, 
                       /* UseUnoptimizedCFG */ false);

  GRTransferFuncs* TF = MakeCFRefCountTF(AMgr.getASTContext(), /*GC*/false,
                                         AMgr.getLangOptions());
  GRExprEngine Eng(AMgr, TF);

  Eng.ExecuteWorkList(AMgr.getStackFrame(FD, TU), AMgr.getMaxNodes());
  
  return 0;
}
Exemple #24
0
bool operator==(const FileContainer &fileContainer, const TranslationUnit &translationUnit)
{
    return fileContainer.filePath() == translationUnit.filePath() && fileContainer.projectPartId() == translationUnit.projectPartId();
}
Exemple #25
0
core::Error findReferences(const core::libclang::FileLocation& location,
                           std::string* pSpelling,
                           std::vector<core::libclang::FileRange>* pRefs)
{
   Cursor cursor = rSourceIndex().referencedCursorForFileLocation(location);
   if (!cursor.isValid() || !cursor.isDeclaration())
      return Success();

   // get it's USR (bail if it doesn't have one)
   std::string USR = cursor.getUSR();
   if (USR.empty())
      return Success();

   // determine what translation units to look in -- if this is a package
   // then we look throughout all the source code in the package.
   if (rCompilationDatabase().hasTranslationUnit(
                                         location.filePath.absolutePath()))
   {
      // get all translation units to search
      std::vector<std::string> files = rCompilationDatabase()
                                                .translationUnits();

      // get translation units we've already indexed
      std::map<std::string,TranslationUnit> indexedUnits =
                           rSourceIndex().getIndexedTranslationUnits();

      for (const std::string& filename : files)
      {
         // first look in already indexed translation units
         // (this will pickup unsaved files)
         std::map<std::string,TranslationUnit>::iterator it =
                                                   indexedUnits.find(filename);
         if (it != indexedUnits.end())
         {
            findReferences(USR,
                           it->second.getCXTranslationUnit(),
                           pSpelling,
                           pRefs);
         }
         else
         {
            // get the compilation arguments for this file and use them to
            // create a temporary translation unit to search
            std::vector<std::string> compileArgs =
               rCompilationDatabase().compileArgsForTranslationUnit(filename,
                                                                    true);

            if (compileArgs.empty())
               continue;

            // create temporary index
            CXIndex index = libclang::clang().createIndex(
                              1 /* Exclude PCH */,
                              (rSourceIndex().verbose() > 0) ? 1 : 0);

            // get args in form clang expects
            core::system::ProcessArgs argsArray(compileArgs);

            // parse the translation unit
            CXTranslationUnit tu = libclang::clang().parseTranslationUnit(
                                  index,
                                  filename.c_str(),
                                  argsArray.args(),
                                  gsl::narrow_cast<int>(argsArray.argCount()),
                                  nullptr, 0, // no unsaved files
                                  CXTranslationUnit_None |
                                  CXTranslationUnit_Incomplete);

            // find references
            findReferences(USR, tu, pSpelling, pRefs);

            // dispose translation unit and index
            libclang::clang().disposeTranslationUnit(tu);
            libclang::clang().disposeIndex(index);
         }
      }
   }
   // not a package, just search locally
   else
   {
      TranslationUnit tu = rSourceIndex().getTranslationUnit(
                                             location.filePath.absolutePath(),
                                             true);
      if (!tu.empty())
         findReferences(USR, tu.getCXTranslationUnit(), pSpelling, pRefs);
   }

   return Success();

}