示例#1
0
    std::string tokenize_as_vimson(char const* const* args, size_t const argc)
    {
        CXIndex index = clang_createIndex(/*excludeDeclsFromPCH*/ 1, /*displayDiagnostics*/0);

        translation_unit = clang_parseTranslationUnit(index, file_name.c_str(), args, argc, NULL, 0, CXTranslationUnit_Incomplete);
        if (translation_unit == NULL) {
            clang_disposeIndex(index);
            return "{}";
        }
        auto file_range = get_range_whole_file();
        if (clang_Range_isNull(file_range)) {
            clang_disposeTranslationUnit(translation_unit);
            clang_disposeIndex(index);
            return "{}";
        }

        CXToken *tokens_;
        unsigned int num_tokens;
        clang_tokenize(translation_unit, file_range, &tokens_, &num_tokens);
        std::vector<CXToken> tokens(tokens_, tokens_ + num_tokens);

        auto result = make_vimson_from_tokens(tokens);

        clang_disposeTokens(translation_unit, tokens_, num_tokens);
        clang_disposeTranslationUnit(translation_unit);
        clang_disposeIndex(index);

        return result;
    }
void ClangParser::finish()
{
   if (p->tu) {

      delete[] p->cursors;
      clang_disposeTokens(p->tu, p->tokens, p->numTokens);
      clang_disposeTranslationUnit(p->tu);
      clang_disposeIndex(p->index);

      p->fileMapping.clear();
      p->tokens    = 0;
      p->numTokens = 0;
      p->cursors   = 0;
   }

   for (uint i = 0; i < p->numFiles; i++) {
      free((void *)p->ufs[i].Filename);
   }

   delete[] p->ufs;
   delete[] p->sources;

   p->ufs       = 0;
   p->sources   = 0;
   p->numFiles  = 0;
   p->tu        = 0;
}
示例#3
0
 void TearDown() override {
   clang_disposeTranslationUnit(ClangTU);
   clang_disposeIndex(Index);
   for (const std::string &Path : Files)
     llvm::sys::fs::remove(Path);
   llvm::sys::fs::remove(TestDir);
 }
示例#4
0
文件: server.c 项目: gordio/ccode
void server_main()
{
	struct sigaction sa;
	int sock;

	sock_path = get_socket_path();
	sock = create_server_socket(sock_path);
	if (sock == -1) {
		fprintf(stderr, "Error! Failed to create a server socket: %s\n",
			sock_path->data);
		exit(1);
	}

	sa.sa_handler = handle_sigint;
	sa.sa_flags = 0;
	sigaction(SIGINT, &sa, 0);

	clang_index = clang_createIndex(0, 0);
	server_loop(sock);
	if (clang_tu)
		clang_disposeTranslationUnit(clang_tu);
	clang_disposeIndex(clang_index);

	close(sock);
	unlink(sock_path->data);
	str_free(sock_path);
}
示例#5
0
void DumpThread::run()
{
    const auto key = mConnection->disconnected().connect([this](const std::shared_ptr<Connection> &) { abort(); });

    CXIndex index = clang_createIndex(0, 0);
    CXTranslationUnit translationUnit = 0;
    String clangLine;
    RTags::parseTranslationUnit(mSource.sourceFile(), mSource.toCommandLine(Source::Default), translationUnit,
                                index, 0, 0, CXTranslationUnit_DetailedPreprocessingRecord, &clangLine);
    if (!(mQueryFlags & QueryMessage::DumpCheckIncludes))
        writeToConnetion(String::format<128>("Indexed: %s => %s", clangLine.constData(), translationUnit ? "success" : "failure"));
    if (translationUnit) {
        clang_visitChildren(clang_getTranslationUnitCursor(translationUnit), DumpThread::visitor, this);
        clang_disposeTranslationUnit(translationUnit);
    }

    clang_disposeIndex(index);
    mConnection->disconnected().disconnect(key);
    std::weak_ptr<Connection> conn = mConnection;
    if (mQueryFlags & QueryMessage::DumpCheckIncludes) {
        checkIncludes();
    }
    EventLoop::mainEventLoop()->callLater([conn]() {
            if (auto c = conn.lock())
                c->finish();
        });
}
示例#6
0
int main(int argc, char *argv[]) 
{
  CXIndex Index = clang_createIndex(0, 0);
  
  CXTranslationUnit TU;
  
  TU = clang_parseTranslationUnit(Index, 0, 
                                  (const char**)argv, argc, 
                                  0, 0, CXTranslationUnit_None);
  
        
  CXCodeCompleteResults *results = clang_codeCompleteAt(TU, argv[1], 20, 7, NULL, 0, clang_defaultCodeCompleteOptions());
      
     
  unsigned i;
  for(i =0; i<results->NumResults; i++)
    {
      printf("%s",results->Results[i].CompletionString);
    }
   
    
  //            clang_disposeString(String);
  
  clang_disposeCodeCompleteResults(results);
  clang_disposeTranslationUnit(TU);
  clang_disposeIndex(Index);
 
  return 0;
}
示例#7
0
void ClangParser::finish()
{
  static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING);
  if (!clangAssistedParsing) return;
  if (p->tu)
  {
    //printf("ClangParser::finish()\n");
    delete[] p->cursors;
    clang_disposeTokens(p->tu,p->tokens,p->numTokens);
    clang_disposeTranslationUnit(p->tu);
    clang_disposeIndex(p->index);
    p->fileMapping.clear();
    p->tokens    = 0;
    p->numTokens = 0;
    p->cursors   = 0;
  }
  for (uint i=0;i<p->numFiles;i++)
  {
    free((void *)p->ufs[i].Filename);
  }
  delete[] p->ufs;
  delete[] p->sources;
  p->ufs       = 0;
  p->sources   = 0;
  p->numFiles  = 0;
  p->tu        = 0;
}
/**
 * Параметр CXTranslationUnit_SkipFunctionBodies позволяет ускорить разбор
 * за счёт игнорирования парсером тел функций
 * Внутри функций обычно нет глобальных переменных
 */
void fileAction(const std::string &path)
{
    CXTranslationUnit unit = clang_parseTranslationUnit(
                g_index,
                path.c_str(),
                nullptr, /* argv */
                0, /* argc */
                nullptr, /* unsaved files */
                0, /* num unsaved files */
                CXTranslationUnit_SkipFunctionBodies
                | CXTranslationUnit_DetailedPreprocessingRecord
                );

    if (unit == nullptr)
    {
        std::cout << "Cannot parse: " << path << std::endl;
        return;
    }

    // Получаем курсор для всей единицы трансляции
    CXCursor cursorTU = clang_getTranslationUnitCursor(unit);
    clang_visitChildren(cursorTU, globalsFinder, NULL);

    clang_disposeTranslationUnit(unit);
}
void TranslationUnit::removeTranslationUnitIfProjectPartWasChanged() const
{
    if (projectPartIsOutdated()) {
        clang_disposeTranslationUnit(d->translationUnit);
        d->translationUnit = nullptr;
    }
}
/* Update command line arguments passing to clang translation unit. Format
   of the coming CMDLINEARGS message is as follows:
   
       num_args: [#n_args#]
       arg1 arg2 ... (there should be n_args items here)
*/
void completion_doCmdlineArgs(completion_Session *session, FILE *fp)
{
    int i_arg = 0;
    char arg[LINE_MAX];

    /* destroy command line args, and we will rebuild it later */
    completion_freeCmdlineArgs(session);

    /* get number of arguments */
    fscanf(fp, "num_args:%d", &(session->num_args)); __skip_the_rest(fp);
    session->cmdline_args = (char**)calloc(sizeof(char*), session->num_args);

    /* rebuild command line arguments vector according to the message */
    for ( ; i_arg < session->num_args; i_arg++)
    {
        /* fetch an argument from message */
        fscanf(fp, "%s", arg);

        /* and add it to cmdline_args */
        session->cmdline_args[i_arg] = (char*)calloc(sizeof(char), strlen(arg) + 1);
        strcpy(session->cmdline_args[i_arg], arg);
    }

    /* we have to rebuild our translation units to make these cmdline args changes 
       take place */
    clang_disposeTranslationUnit(session->cx_tu);
    completion_parseTranslationUnit(session);
    completion_reparseTranslationUnit(session);  /* dump PCH for acceleration */
}
void TranslationUnitUpdater::removeTranslationUnitIfProjectPartWasChanged()
{
    if (m_in.parseNeeded) {
        clang_disposeTranslationUnit(m_cxTranslationUnit);
        m_cxTranslationUnit = nullptr;
    }
}
ReflectionParser::~ReflectionParser(void)
{
    if (m_translationUnit)
        clang_disposeTranslationUnit( m_translationUnit );

    if (m_index)
        clang_disposeIndex( m_index );
}
示例#13
0
void TranslationUnit::Destroy() {
  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( clang_translation_unit_ ) {
    clang_disposeTranslationUnit( clang_translation_unit_ );
    clang_translation_unit_ = nullptr;
  }
}
示例#14
0
void reparseTranslationUnit(CXTranslationUnit &unit, CXUnsavedFile *unsaved, int unsavedCount)
{
    assert(unit);
    if (clang_reparseTranslationUnit(unit, 0, unsaved, clang_defaultReparseOptions(unit)) != 0) {
        clang_disposeTranslationUnit(unit);
        unit = 0;
    }
}
示例#15
0
Tokenizer::~Tokenizer()
    {
    CLangAutoLock lock(mCLangLock, __LINE__, this);
    if(mTransUnit)
        {
        clang_disposeTranslationUnit(mTransUnit);
        clang_disposeIndex(mContextIndex);
        }
    }
示例#16
0
ClangIndexer::~ClangIndexer()
{
    if (mLogFile)
        fclose(mLogFile);
    if (mClangUnit)
        clang_disposeTranslationUnit(mClangUnit);
    if (mIndex)
        clang_disposeIndex(mIndex);
}
示例#17
0
void translation_unit::reparse()
{
    int err = clang_reparseTranslationUnit(tu, 0, 0, clang_defaultReparseOptions(tu));
    if(err)
    {
        clang_disposeTranslationUnit(tu);
        tu = nullptr;
        throw error("unable to reparse tu");
    }
}
CXTranslationUnit ClangWorkerThread::DoCreateTU(CXIndex index, ClangThreadRequest* task, bool reparse)
{
    wxFileName fn(task->GetFileName());
    DoSetStatusMsg(wxString::Format(wxT("clang: parsing file %s..."), fn.GetFullName().c_str()));

    FileExtManager::FileType type = FileExtManager::GetType(task->GetFileName());
    int argc(0);
    char** argv = MakeCommandLine(task, argc, type);

    for(int i = 0; i < argc; i++) {
        CL_DEBUG(wxT("Command Line Argument: %s"), wxString(argv[i], wxConvUTF8).c_str());
    }

    std::string c_filename = task->GetFileName().mb_str(wxConvUTF8).data();
    CL_DEBUG(wxT("Calling clang_parseTranslationUnit..."));

    // First time, need to create it
    unsigned flags;
    if(reparse) {
        flags = CXTranslationUnit_CacheCompletionResults | CXTranslationUnit_PrecompiledPreamble |
                CXTranslationUnit_Incomplete | CXTranslationUnit_DetailedPreprocessingRecord |
                CXTranslationUnit_CXXChainedPCH;
    } else {
        flags = CXTranslationUnit_Incomplete | 
#if HAS_LIBCLANG_BRIEFCOMMENTS
		CXTranslationUnit_SkipFunctionBodies |
#endif
                CXTranslationUnit_DetailedPreprocessingRecord;
    }

    CXTranslationUnit TU = clang_parseTranslationUnit(index, c_filename.c_str(), argv, argc, NULL, 0, flags);

    CL_DEBUG(wxT("Calling clang_parseTranslationUnit... done"));
    ClangUtils::FreeArgv(argv, argc);
    DoSetStatusMsg(wxString::Format(wxT("clang: parsing file %s...done"), fn.GetFullName().c_str()));
    if(TU && reparse) {
        CL_DEBUG(wxT("Calling clang_reparseTranslationUnit..."));
        if(clang_reparseTranslationUnit(TU, 0, NULL, clang_defaultReparseOptions(TU)) == 0) {
            CL_DEBUG(wxT("Calling clang_reparseTranslationUnit... done"));
            return TU;

        } else {
            CL_DEBUG(wxT("An error occured during reparsing of the TU for file %s. TU: %p"),
                     task->GetFileName().c_str(),
                     (void*)TU);

            // The only thing that left to be done here, is to dispose the TU
            clang_disposeTranslationUnit(TU);
            PostEvent(wxEVT_CLANG_TU_CREATE_ERROR, task->GetFileName());
            return NULL;
        }
    }
    return TU;
}
示例#19
0
int main(int argc, char * argv[])
{
  CXIndex index = clang_createIndex(0, 0);
  CXTranslationUnit txUnit = clang_parseTranslationUnit(index, 0, (const char * const *) argv, argc, 0, 0, CXTranslationUnit_None);

  CXCursor cur = clang_getTranslationUnitCursor(txUnit);
  clang_visitChildren(cur, visitor, NULL);

  clang_disposeTranslationUnit(txUnit);
  clang_disposeIndex(index);
  return 0;
}
示例#20
0
int main(int argc, const char* const argv[]){
  if (argc < 2) {
    printf("Usage: %s header.h\n", argv[0]);
    printf("Standard clang arguments (-I, -D, etc.) may be used\n");
    exit(1);
  }
  unsigned i;

  char filename[] = "ffigen.tmp.XXXXXX";
  int fd = mkstemp(filename);
  FILE* file = fdopen(fd, "w");
  fprintf(file, "#define _SIZE_T\n");
  fprintf(file, "#define _PTRDIFF_T\n");
  fprintf(file, "typedef __SIZE_TYPE__ size_t;\n");
  fprintf(file, "typedef __PTRDIFF_TYPE__ ptrdiff_t;\n");
  fprintf(file, "#include <%s>\n", argv[1]);
  fclose(file);

  int clang_argc = argc + 1;
  const char** clang_argv = malloc(sizeof(char*) * clang_argc);
  clang_argv[0] = "-x";
  clang_argv[1] = "c";
  clang_argv[2] = filename;
  for (i=3; i < clang_argc; i++) {
    clang_argv[i] = argv[i-1];
  }

  CXIndex Index = clang_createIndex(0, 0);
  TU = clang_parseTranslationUnit(Index, 0, clang_argv, clang_argc,
                                  0, 0, CXTranslationUnit_DetailedPreprocessingRecord);
  json_t* json = json_object();
  clang_visitChildren(clang_getTranslationUnitCursor(TU), visit_program, (CXClientData)json);


  json_dumpf(json, stdout, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
  printf("\n");
  json_decref(json);


  for (i=0; i<clang_getNumDiagnostics(TU); i++) {
    putstring(clang_formatDiagnostic(clang_getDiagnostic(TU, i), clang_defaultDiagnosticDisplayOptions()));
  }


  clang_disposeTranslationUnit(TU);
  clang_disposeIndex(Index);
  free(clang_argv);
  unlink(filename);

  return 0;
}
示例#21
0
void TestCases::ClangTest() {
#ifdef ENABLE_CLANG_COMPLETION
  std::cout << "checking to see if libclang/libclang.dll works" << std::endl;

  int argc = 1;
  char* argv[] = {"--version"};

  CXIndex index = clang_createIndex(0, 0);
  CXTranslationUnit tu = clang_parseTranslationUnit(index, 0, argv, argc, 0, 0,
                                                    CXTranslationUnit_None);
  clang_disposeTranslationUnit(tu);
  clang_disposeIndex(index);
#endif
}
/* When emacs buffer is killed, a SHUTDOWN message is sent automatically by a hook 
   function to inform the completion server (this program) to terminate. */
void completion_doShutdown(completion_Session *session, FILE *fp)
{
    (void) fp;    /* this parameter is unused, the server will shutdown
                   * directly without sending any messages to its client */

    /* free clang parser infrastructures */
    clang_disposeTranslationUnit(session->cx_tu);
    clang_disposeIndex(session->cx_index);

    /* free session properties */
    completion_freeCmdlineArgs(session);
    free(session->src_buffer);

    exit(0);   /* terminate completion process */
}
示例#23
0
void DumpThread::run()
{
    CXIndex index = clang_createIndex(0, 0);
    CXTranslationUnit translationUnit = 0;
    String clangLine;
    RTags::parseTranslationUnit(mSource.sourceFile(), mSource.toCommandLine(Source::Default), translationUnit,
                                index, 0, 0, CXTranslationUnit_DetailedPreprocessingRecord, &clangLine);
    writeToConnetion(String::format<128>("Indexed: %s => %s", clangLine.constData(), translationUnit ? "success" : "failure"));
    if (translationUnit) {
        clang_visitChildren(clang_getTranslationUnitCursor(translationUnit), DumpThread::visitor, this);
        clang_disposeTranslationUnit(translationUnit);
    }

    clang_disposeIndex(index);
    EventLoop::mainEventLoop()->callLaterMove(std::bind((bool(Connection::*)(Message&&))&Connection::send, mConnection, std::placeholders::_1),
                                              FinishMessage());
}
示例#24
0
int main(int argc, char* argv[])
{

	CXString version = clang_getClangVersion();
	printf("%s\n", clang_getCString(version));
	clang_disposeString(version);

	CXIndex index = clang_createIndex(1, 1);
	CXTranslationUnit tu = clang_createTranslationUnit(index, argv[1]);
	if (tu) {
		clang_visitChildren(clang_getTranslationUnitCursor(tu), visitor, argv[2]);
		clang_disposeTranslationUnit(tu);
	}

	clang_disposeIndex(index);

	return 0;

}
示例#25
0
void Tokenizer::parse(OovStringRef fileName, OovStringRef buffer, size_t bufLen,
        char const * const clang_args[], size_t num_clang_args)
    {
    CLangAutoLock lock(mCLangLock, __LINE__, this);
    try
        {
        if(!mSourceFile)
            {
            // The clang_defaultCodeCompleteOptions() options are not for the parse
            // function, they are for the clang_codeCompleteAt func.
            unsigned options = clang_defaultEditingTranslationUnitOptions();
            // This is required to allow go to definition to work with #include.
            options |= CXTranslationUnit_DetailedPreprocessingRecord;

            mSourceFilename = fileName;
            mContextIndex = clang_createIndex(1, 1);
            mTransUnit = clang_parseTranslationUnit(mContextIndex, fileName,
                clang_args, static_cast<int>(num_clang_args), 0, 0, options);
            }
        else
            {
            static CXUnsavedFile file;
            file.Filename = mSourceFilename.c_str();
            file.Contents = buffer;
            file.Length = bufLen;

            unsigned options = clang_defaultReparseOptions(mTransUnit);
            int stat = clang_reparseTranslationUnit(mTransUnit, 1, &file, options);
            if(stat != 0)
                {
                clang_disposeTranslationUnit(mTransUnit);
                mTransUnit = nullptr;
                }
            }
        mSourceFile = clang_getFile(mTransUnit, fileName);
        }
    catch(...)
        {
        DUMP_PARSE_INT("Tokenizer::parse - CRASHED", 0);
        }
    }
示例#26
0
static int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
                             const char *filter, const char *prefix,
                             CXCursorVisitor Visitor,
                             PostVisitTU PV) {

  if (prefix)
    FileCheckPrefix = prefix;

  if (Visitor) {
    enum CXCursorKind K = CXCursor_NotImplemented;
    enum CXCursorKind *ck = &K;
    VisitorData Data;

    /* Perform some simple filtering. */
    if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL;
    else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0;
    else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
    else if (!strcmp(filter, "interface")) K = CXCursor_ObjCInterfaceDecl;
    else if (!strcmp(filter, "protocol")) K = CXCursor_ObjCProtocolDecl;
    else if (!strcmp(filter, "function")) K = CXCursor_FunctionDecl;
    else if (!strcmp(filter, "typedef")) K = CXCursor_TypedefDecl;
    else if (!strcmp(filter, "scan-function")) Visitor = FunctionScanVisitor;
    else {
      fprintf(stderr, "Unknown filter for -test-load-tu: %s\n", filter);
      return 1;
    }

    Data.TU = TU;
    Data.Filter = ck;
    clang_visitChildren(clang_getTranslationUnitCursor(TU), Visitor, &Data);
  }

  if (PV)
    PV(TU);

  PrintDiagnostics(TU);
  clang_disposeTranslationUnit(TU);
  return 0;
}
示例#27
0
translation_unit& index::parse_translation_unit(const std::vector<std::string>& args, const std::vector<unsaved_file>& unsaved)
{
    auto argv = convert_args(args);
    auto unsaved_files = convert_unsaved_files(unsaved);
    unsigned options = CXTranslationUnit_DetailedPreprocessingRecord | 
                        CXTranslationUnit_CacheCompletionResults;
    
    auto tu = clang_parseTranslationUnit(idx, nullptr, argv.data(), argv.size(), unsaved_files.data(), unsaved_files.size(), options);
    if(!tu)
        throw error("unable to parse tu");

    // Have to reparse to cache completion results.
    int err = clang_reparseTranslationUnit(tu, unsaved_files.size(), unsaved_files.data(), clang_defaultReparseOptions(tu));
    if(err)
    {
        clang_disposeTranslationUnit(tu);
        throw error("unable to reparse tu");
    }
    
    tus.emplace_back(tu);
    return tus.back();
}
示例#28
0
int main(int argc, char **argv)
{
    if (argc < 2)
        return 1;
    CXIndex index = clang_createIndex(1, 1);
    const char * const *args = 0;
    if (argc > 2)
        args = (const char *const *)&argv[2];

    CXTranslationUnit unit = clang_parseTranslationUnit(index, argv[1], args, argc - 2,
                                                        0, 0, clang_defaultEditingTranslationUnitOptions());
    if (unit) {
        int indent = 0;
        clang_visitChildren(clang_getTranslationUnitCursor(unit), visit, &indent);

        const unsigned int diagnosticCount = clang_getNumDiagnostics(unit);
        unsigned int i;
        for (i=0; i<diagnosticCount; ++i) {
            CXDiagnostic diagnostic = clang_getDiagnostic(unit, i);
            const unsigned int diagnosticOptions = (CXDiagnostic_DisplaySourceLocation|
                                                CXDiagnostic_DisplayColumn|
                                                CXDiagnostic_DisplaySourceRanges|
                                                CXDiagnostic_DisplayOption|
                                                CXDiagnostic_DisplayCategoryId|
                                                CXDiagnostic_DisplayCategoryName);
            CXString diagnosticText = clang_formatDiagnostic(diagnostic, diagnosticOptions);
            const char *cstr = clang_getCString(diagnosticText);
            if (cstr)
                printf("%s\n", cstr);
            clang_disposeString(diagnosticText);
        }
        clang_disposeTranslationUnit(unit);
    }
    clang_disposeIndex(index);
    return 0;
}
示例#29
0
void CompletionThread::process(Request *request)
{
    // if (!request->unsaved.isEmpty()) {
    //     int line = request->location.line();
    //     int pos = 0;
    //     while (line > 1) {
    //         int p = request->unsaved.indexOf('\n', pos);
    //         if (p == -1) {
    //             pos = -1;
    //             break;
    //         }
    //         pos = p + 1;
    //         --line;
    //     }
    //     if (pos != -1) {
    //         int end = request->unsaved.indexOf('\n', pos);
    //         if (end == -1)
    //             end = request->unsaved.size();
    //         error("Completing at %s:%d:%d line: [%s]\n",
    //               request->location.path().constData(),
    //               request->location.line(),
    //               request->location.column(),
    //               request->unsaved.mid(pos, end - pos).constData());
    //     }
    // }

    StopWatch sw;
    int parseTime = 0;
    int reparseTime = 0;
    int completeTime = 0;
    int processTime = 0;
    SourceFile *&cache = mCacheMap[request->source.fileId];
    if (cache && cache->source != request->source) {
        delete cache;
        cache = 0;
    }
    if (!cache) {
        cache = new SourceFile;
        mCacheList.append(cache);
        while (mCacheMap.size() > mCacheSize) {
            SourceFile *c = mCacheList.removeFirst();
            mCacheMap.remove(c->source.fileId);
            delete c;
        }
    } else {
        mCacheList.moveToEnd(cache);
    }
    const bool sendDebug = testLog(LogLevel::Debug);

    if (cache->translationUnit && cache->source != request->source) {
        clang_disposeTranslationUnit(cache->translationUnit);
        cache->translationUnit = 0;
        cache->source = request->source;
    } else if (!cache->translationUnit) {
        cache->source = request->source;
    }

    const Path sourceFile = request->source.sourceFile();
    CXUnsavedFile unsaved = {
        sourceFile.constData(),
        request->unsaved.constData(),
        static_cast<unsigned long>(request->unsaved.size())
    };

    size_t hash = 0;
    uint64_t lastModified = 0;
    if (request->unsaved.size()) {
        std::hash<String> h;
        hash = h(request->unsaved);
    } else {
        lastModified = sourceFile.lastModifiedMs();
    }

    const auto &options = Server::instance()->options();
    if (!cache->translationUnit) {
        cache->completionsMap.clear();
        cache->completionsList.deleteAll();
        sw.restart();
        Flags<CXTranslationUnit_Flags> flags = static_cast<CXTranslationUnit_Flags>(clang_defaultEditingTranslationUnitOptions());
        flags |= CXTranslationUnit_PrecompiledPreamble;
        flags |= CXTranslationUnit_CacheCompletionResults;
        flags |= CXTranslationUnit_SkipFunctionBodies;

        for (const auto &inc : options.includePaths) {
            request->source.includePaths << inc;
        }
        request->source.defines << options.defines;

        String clangLine;
        RTags::parseTranslationUnit(sourceFile, request->source.toCommandLine(Source::Default|Source::ExcludeDefaultArguments),
                                    cache->translationUnit, mIndex,
                                    &unsaved, request->unsaved.size() ? 1 : 0, flags, &clangLine);
        // error() << "PARSING" << clangLine;
        parseTime = sw.restart();
        if (cache->translationUnit) {
            RTags::reparseTranslationUnit(cache->translationUnit, &unsaved, request->unsaved.size() ? 1 : 0);
        }
        reparseTime = sw.elapsed();
        if (!cache->translationUnit)
            return;
        cache->unsavedHash = hash;
        cache->lastModified = lastModified;
    } else if (cache->unsavedHash != hash || cache->lastModified != lastModified) {
        cache->completionsMap.clear();
        cache->completionsList.deleteAll();
        cache->unsavedHash = hash;
        cache->lastModified = lastModified;
    } else if (!(request->flags & Refresh)) {
        const auto it = cache->completionsMap.find(request->location);
        if (it != cache->completionsMap.end()) {
            cache->completionsList.moveToEnd(it->second);
            error("Found completions (%d) in cache %s:%d:%d",
                  it->second->candidates.size(), sourceFile.constData(),
                  request->location.line(), request->location.column());
            printCompletions(it->second->candidates, request);
            return;
        }
    }

    sw.restart();
    const unsigned int completionFlags = (CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns);

    CXCodeCompleteResults *results = clang_codeCompleteAt(cache->translationUnit, sourceFile.constData(),
                                                          request->location.line(), request->location.column(),
                                                          &unsaved, unsaved.Length ? 1 : 0, completionFlags);
    completeTime = sw.restart();
    if (results) {
        std::vector<Completions::Candidate> nodes;
        nodes.reserve(results->NumResults);

        int nodeCount = 0;
        Map<Token, int> tokens;
        if (!request->unsaved.isEmpty()) {
            tokens = Token::tokenize(request->unsaved.constData(), request->unsaved.size());
            // for (Map<Token, int>::const_iterator it = tokens.begin(); it != tokens.end(); ++it) {
            //     error() << String(it->first.data, it->first.length) << it->second;
            // }
        }
        for (unsigned int i = 0; i < results->NumResults; ++i) {
            const CXCursorKind kind = results->Results[i].CursorKind;
            if (!(options.options & Server::CompletionsNoFilter) && kind == CXCursor_Destructor)
                continue;

            const CXCompletionString &string = results->Results[i].CompletionString;

            const CXAvailabilityKind availabilityKind = clang_getCompletionAvailability(string);
            if (!(options.options & Server::CompletionsNoFilter) && availabilityKind != CXAvailability_Available)
                continue;

            const int priority = clang_getCompletionPriority(string);

            if (size_t(nodeCount) == nodes.size())
                nodes.emplace_back();

            Completions::Candidate &node = nodes.back();
            node.cursorKind = kind;
            node.priority = priority;
            node.signature.reserve(256);
            const int chunkCount = clang_getNumCompletionChunks(string);
            bool ok = true;
            for (int j=0; j<chunkCount; ++j) {
                const CXCompletionChunkKind chunkKind = clang_getCompletionChunkKind(string, j);
                if (chunkKind == CXCompletionChunk_TypedText) {
                    node.completion = RTags::eatString(clang_getCompletionChunkText(string, j));
                    if (node.completion.size() > 8 && node.completion.startsWith("operator") && !isPartOfSymbol(node.completion.at(8))) {
                        ok = false;
                        break;
                    }
                    node.signature.append(node.completion);
                } else {
                    node.signature.append(RTags::eatString(clang_getCompletionChunkText(string, j)));
                    if (chunkKind == CXCompletionChunk_ResultType)
                        node.signature.append(' ');
                }
            }
            if (ok) {
                int ws = node.completion.size() - 1;
                while (ws >= 0 && isspace(node.completion.at(ws)))
                    --ws;
                if (ws >= 0) {
                    node.completion.truncate(ws + 1);
                    node.signature.replace("\n", "");
                    node.distance = tokens.value(Token(node.completion.constData(), node.completion.size()), -1);
                    if (sendDebug)
                        debug() << node.signature << node.priority << kind
                                << node.distance << clang_getCompletionAvailability(string);

                    ++nodeCount;
                    continue;
                }
            }
            node.completion.clear();
            node.signature.clear();
        }
        if (nodeCount) {
            // Sort pointers instead of shuffling candidates around
            std::vector<Completions::Candidate*> nodesPtr;
            nodesPtr.reserve(nodeCount);
            for (auto& n : nodes) nodesPtr.push_back(&n);

            std::sort(nodesPtr.begin(), nodesPtr.end(), compareCompletionCandidates);

            Completions *&c = cache->completionsMap[request->location];
            if (c) {
                cache->completionsList.moveToEnd(c);
            } else {
                enum { MaxCompletionCache = 10 }; // ### configurable?
                c = new Completions(request->location);
                cache->completionsList.append(c);
                while (cache->completionsMap.size() > MaxCompletionCache) {
                    Completions *cc = cache->completionsList.takeFirst();
                    cache->completionsMap.remove(cc->location);
                    delete cc;
                }
            }
            c->candidates.resize(nodeCount);
            for (int i=0; i<nodeCount; ++i)
                c->candidates[i] = std::move(*nodesPtr[i]);
            printCompletions(c->candidates, request);
            processTime = sw.elapsed();
            warning("Processed %s, parse %d/%d, complete %d, process %d => %d completions (unsaved %d)",
                    sourceFile.constData(), parseTime, reparseTime, completeTime, processTime, nodeCount, request->unsaved.size());
        } else {
            printCompletions(List<Completions::Candidate>(), request);
            error() << "No completion results available" << request->location << results->NumResults;
        }
        clang_disposeCodeCompleteResults(results);
    }
}
示例#30
0
void IndexerJob::execute()
{
    if (isAborted())
        return;
    mTimer.start();
    mData.reset(new IndexData);
    if (mType == Dump) {
        assert(id() != -1);
        if (shared_ptr<Project> p = project()) {
            for (int i=0; i<mSourceInformation.builds.size(); ++i) {
                parse(i);
                if (mUnits.at(i).second) {
                    DumpUserData u = { 0, this, !(queryFlags() & QueryMessage::NoContext) };
                    clang_visitChildren(clang_getTranslationUnitCursor(mUnits.at(i).second),
                                        IndexerJob::dumpVisitor, &u);
                }
            }
        }
    } else {
        {
            MutexLocker lock(&mMutex);
            mStarted = true;
        }
        int errorCount = 0;
        int unitCount = 0;
        const int buildCount = mSourceInformation.builds.size();
        for (int i=0; i<buildCount; ++i) {
            if (!parse(i)) {
                goto end;
            }
            if (mUnits.at(i).second)
                ++unitCount;
        }
        mParseTime = time(0);

        for (int i=0; i<buildCount; ++i) {
            int err = 0;
            if (!visit(i) || !diagnose(i, &err))
                goto end;
            errorCount += err;
        }
        {
            mData->message += mSourceInformation.sourceFile.toTilde();
            if (buildCount > 1)
                mData->message += String::format<16>(" (%d builds)", buildCount);
            if (!unitCount) {
                mData->message += " error";
            } else if (unitCount != buildCount) {
                mData->message += String::format<16>(" (%d errors, %d ok)", buildCount - unitCount, unitCount);
            }
            mData->message += String::format<16>(" in %sms. ", String::number(mTimer.elapsed()).constData());
            if (unitCount) {
                mData->message += String::format<1024>("(%d syms, %d symNames, %d refs, %d deps, %d files)",
                                                       mData->symbols.size(), mData->symbolNames.size(), mData->references.size(),
                                                       mData->dependencies.size(), mVisitedFiles.size());
            } else if (mData->dependencies.size()) {
                mData->message += String::format<16>("(%d deps)", mData->dependencies.size());
            }
            if (mType == Dirty)
                mData->message += " (dirty)";
        }
  end:
        shared_ptr<Project> p = project();
        if (p) {
            shared_ptr<IndexerJob> job = static_pointer_cast<IndexerJob>(shared_from_this());
            p->onJobFinished(job);
        }
    }
    for (int i=0; i<mUnits.size(); ++i) {
        if (mUnits.at(i).first)
            clang_disposeIndex(mUnits.at(i).first);
        if (mUnits.at(i).second)
            clang_disposeTranslationUnit(mUnits.at(i).second);
    }
    mUnits.clear();
}