d63843ea4c
They were temporarily all passed by-value until server-side threading issues were resolved.
174 lines
5.1 KiB
C++
174 lines
5.1 KiB
C++
// Copyright (C) 2011-2013 Strahinja Val Markovic <val@markovic.io>
|
|
//
|
|
// This file is part of YouCompleteMe.
|
|
//
|
|
// YouCompleteMe is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// YouCompleteMe is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#include "ClangCompleter.h"
|
|
#include "exceptions.h"
|
|
#include "Result.h"
|
|
#include "Candidate.h"
|
|
#include "TranslationUnit.h"
|
|
#include "standard.h"
|
|
#include "CandidateRepository.h"
|
|
#include "CompletionData.h"
|
|
#include "Utils.h"
|
|
#include "ClangUtils.h"
|
|
|
|
#include <clang-c/Index.h>
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
|
|
using boost::shared_ptr;
|
|
using boost::unordered_map;
|
|
|
|
namespace YouCompleteMe {
|
|
|
|
ClangCompleter::ClangCompleter()
|
|
: clang_index_( clang_createIndex( 0, 0 ) ),
|
|
translation_unit_store_( clang_index_ ) {
|
|
// The libclang docs don't say what is the default value for crash recovery.
|
|
// I'm pretty sure it's turned on by default, but I'm not going to take any
|
|
// chances.
|
|
clang_toggleCrashRecovery( true );
|
|
}
|
|
|
|
|
|
ClangCompleter::~ClangCompleter() {
|
|
// We need to destroy all TUs before calling clang_disposeIndex because
|
|
// the translation units need to be destroyed before the index is destroyed.
|
|
// Technically, a thread could still be holding onto a shared_ptr<TU> object
|
|
// when we destroy the clang index, but since we're shutting down, we don't
|
|
// really care.
|
|
// In practice, this situation shouldn't happen because the server threads are
|
|
// Python deamon threads and will all be killed before the main thread exits.
|
|
translation_unit_store_.RemoveAll();
|
|
clang_disposeIndex( clang_index_ );
|
|
}
|
|
|
|
|
|
std::vector< Diagnostic > ClangCompleter::DiagnosticsForFile(
|
|
const std::string &filename ) {
|
|
shared_ptr< TranslationUnit > unit = translation_unit_store_.Get( filename );
|
|
|
|
if ( !unit )
|
|
return std::vector< Diagnostic >();
|
|
|
|
return unit->LatestDiagnostics();
|
|
}
|
|
|
|
|
|
bool ClangCompleter::UpdatingTranslationUnit( const std::string &filename ) {
|
|
shared_ptr< TranslationUnit > unit = translation_unit_store_.Get( filename );
|
|
|
|
if ( !unit )
|
|
return false;
|
|
|
|
// Thankfully, an invalid, sentinel TU always returns true for
|
|
// IsCurrentlyUpdating, so no caller will try to rely on the TU object, even
|
|
// if unit is currently pointing to a sentinel.
|
|
return unit->IsCurrentlyUpdating();
|
|
}
|
|
|
|
|
|
void ClangCompleter::UpdateTranslationUnit(
|
|
const std::string &filename,
|
|
const std::vector< UnsavedFile > &unsaved_files,
|
|
const std::vector< std::string > &flags ) {
|
|
bool translation_unit_created;
|
|
shared_ptr< TranslationUnit > unit = translation_unit_store_.GetOrCreate(
|
|
filename,
|
|
unsaved_files,
|
|
flags,
|
|
translation_unit_created );
|
|
|
|
if ( !unit )
|
|
return;
|
|
|
|
try {
|
|
// There's no point in reparsing a TU that was just created, it was just
|
|
// parsed in the TU constructor
|
|
if ( !translation_unit_created )
|
|
unit->Reparse( unsaved_files );
|
|
}
|
|
|
|
catch ( ClangParseError & ) {
|
|
// If unit->Reparse fails, then the underlying TranslationUnit object is not
|
|
// valid anymore and needs to be destroyed and removed from the filename ->
|
|
// TU map.
|
|
translation_unit_store_.Remove( filename );
|
|
}
|
|
}
|
|
|
|
|
|
std::vector< CompletionData >
|
|
ClangCompleter::CandidatesForLocationInFile(
|
|
const std::string &filename,
|
|
int line,
|
|
int column,
|
|
const std::vector< UnsavedFile > &unsaved_files,
|
|
const std::vector< std::string > &flags ) {
|
|
shared_ptr< TranslationUnit > unit =
|
|
translation_unit_store_.GetOrCreate( filename, unsaved_files, flags );
|
|
|
|
if ( !unit )
|
|
return std::vector< CompletionData >();
|
|
|
|
return unit->CandidatesForLocation( line,
|
|
column,
|
|
unsaved_files );
|
|
}
|
|
|
|
|
|
Location ClangCompleter::GetDeclarationLocation(
|
|
const std::string &filename,
|
|
int line,
|
|
int column,
|
|
const std::vector< UnsavedFile > &unsaved_files,
|
|
const std::vector< std::string > &flags ) {
|
|
shared_ptr< TranslationUnit > unit =
|
|
translation_unit_store_.GetOrCreate( filename, unsaved_files, flags );
|
|
|
|
if ( !unit ) {
|
|
return Location();
|
|
}
|
|
|
|
return unit->GetDeclarationLocation( line, column, unsaved_files );
|
|
}
|
|
|
|
|
|
Location ClangCompleter::GetDefinitionLocation(
|
|
const std::string &filename,
|
|
int line,
|
|
int column,
|
|
const std::vector< UnsavedFile > &unsaved_files,
|
|
const std::vector< std::string > &flags ) {
|
|
shared_ptr< TranslationUnit > unit =
|
|
translation_unit_store_.GetOrCreate( filename, unsaved_files, flags );
|
|
|
|
if ( !unit ) {
|
|
return Location();
|
|
}
|
|
|
|
return unit->GetDefinitionLocation( line, column, unsaved_files );
|
|
}
|
|
|
|
|
|
void ClangCompleter::DeleteCachesForFile( const std::string &filename ) {
|
|
translation_unit_store_.Remove( filename );
|
|
}
|
|
|
|
|
|
} // namespace YouCompleteMe
|