Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[READY] Translate libclang error codes to exceptions #861

Merged
merged 1 commit into from
Feb 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 2 additions & 38 deletions cpp/ycm/ClangCompleter/ClangCompleter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
// along with ycmd. If not, see <http://www.gnu.org/licenses/>.

#include "ClangCompleter.h"
#include "exceptions.h"
#include "Result.h"
#include "Candidate.h"
#include "TranslationUnit.h"
Expand Down Expand Up @@ -84,22 +83,15 @@ std::vector< Diagnostic > ClangCompleter::UpdateTranslationUnit(
flags,
translation_unit_created );

if ( !unit ) {
return std::vector< Diagnostic >();
}

try {
return unit->Reparse( unsaved_files );
}

catch ( ClangParseError & ) {
} catch ( const 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 );
throw;
}

return std::vector< Diagnostic >();
}


Expand All @@ -114,10 +106,6 @@ ClangCompleter::CandidatesForLocationInFile(
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 );
Expand All @@ -135,10 +123,6 @@ Location ClangCompleter::GetDeclarationLocation(
shared_ptr< TranslationUnit > unit =
translation_unit_store_.GetOrCreate( filename, unsaved_files, flags );

if ( !unit ) {
return Location();
}

return unit->GetDeclarationLocation( line, column, unsaved_files, reparse );
}

Expand All @@ -154,10 +138,6 @@ Location ClangCompleter::GetDefinitionLocation(
shared_ptr< TranslationUnit > unit =
translation_unit_store_.GetOrCreate( filename, unsaved_files, flags );

if ( !unit ) {
return Location();
}

return unit->GetDefinitionLocation( line, column, unsaved_files, reparse );
}

Expand All @@ -173,10 +153,6 @@ std::string ClangCompleter::GetTypeAtLocation(
shared_ptr< TranslationUnit > unit =
translation_unit_store_.GetOrCreate( filename, unsaved_files, flags );

if ( !unit ) {
return "no unit";
}

return unit->GetTypeAtLocation( line, column, unsaved_files, reparse );
}

Expand All @@ -192,10 +168,6 @@ std::string ClangCompleter::GetEnclosingFunctionAtLocation(
shared_ptr< TranslationUnit > unit =
translation_unit_store_.GetOrCreate( filename, unsaved_files, flags );

if ( !unit ) {
return "no unit";
}

return unit->GetEnclosingFunctionAtLocation( line,
column,
unsaved_files,
Expand All @@ -216,10 +188,6 @@ ClangCompleter::GetFixItsForLocationInFile(
shared_ptr< TranslationUnit > unit =
translation_unit_store_.GetOrCreate( filename, unsaved_files, flags );

if ( !unit ) {
return std::vector< FixIt >();
}

return unit->GetFixItsForLocationInFile( line,
column,
unsaved_files,
Expand All @@ -240,10 +208,6 @@ DocumentationData ClangCompleter::GetDocsForLocationInFile(
shared_ptr< TranslationUnit > unit =
translation_unit_store_.GetOrCreate( filename, unsaved_files, flags );

if ( !unit ) {
return DocumentationData();
}

return unit->GetDocsForLocationInFile( line,
column,
unsaved_files,
Expand Down
25 changes: 25 additions & 0 deletions cpp/ycm/ClangCompleter/ClangUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,29 @@ std::string ClangVersion() {
return CXStringToString( clang_getClangVersion() );
}

const char *CXErrorCodeToString( CXErrorCode code ) {
switch ( code ) {
case CXError_Success:
return "No error encountered while parsing the translation unit.";
case CXError_Failure:
return "Failed to parse the translation unit.";
case CXError_Crashed:
return "Libclang crashed while parsing the translation unit.";
case CXError_InvalidArguments:
return "Invalid arguments supplied when parsing the translation unit.";
case CXError_ASTReadError:
return "An AST deserialization error occurred "
"while parsing the translation unit.";
}
return "Unknown error while parsing the translation unit.";
}

ClangParseError::ClangParseError( const char *what_arg )
: std::runtime_error( what_arg ) {
};

ClangParseError::ClangParseError( CXErrorCode code )
: ClangParseError( CXErrorCodeToString( code ) ) {
};

} // namespace YouCompleteMe
11 changes: 11 additions & 0 deletions cpp/ycm/ClangCompleter/ClangUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define CLANGUTILS_H_9MVHQLJS

#include <clang-c/Index.h>
#include <stdexcept>
#include <string>

namespace YouCompleteMe {
Expand All @@ -37,6 +38,16 @@ std::string CXFileToFilepath( CXFile file );

std::string ClangVersion();

const char *CXErrorCodeToString( CXErrorCode code );

/**
* Thrown when libclang fails to parse (or reparse) the translation unit.
*/
struct YCM_EXPORT ClangParseError : std::runtime_error {
ClangParseError( const char *what_arg );
ClangParseError( CXErrorCode code );
};

} // namespace YouCompleteMe

#endif /* end of include guard: CLANGUTILS_H_9MVHQLJS */
Expand Down
41 changes: 21 additions & 20 deletions cpp/ycm/ClangCompleter/TranslationUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

#include "TranslationUnit.h"
#include "CompletionData.h"
#include "exceptions.h"
#include "ClangUtils.h"
#include "ClangHelpers.h"

Expand Down Expand Up @@ -95,18 +94,17 @@ TranslationUnit::TranslationUnit(
? &cxunsaved_files[ 0 ] : nullptr;

// Actually parse the translation unit.
CXErrorCode result = clang_parseTranslationUnit2FullArgv(
clang_index,
filename.c_str(),
&pointer_flags[ 0 ],
pointer_flags.size(),
const_cast<CXUnsavedFile *>( unsaved ),
cxunsaved_files.size(),
EditingOptions(),
&clang_translation_unit_ );

if ( result != CXError_Success ) {
throw( ClangParseError() );
CXErrorCode failure = clang_parseTranslationUnit2FullArgv(
clang_index,
filename.c_str(),
&pointer_flags[ 0 ],
pointer_flags.size(),
const_cast<CXUnsavedFile *>( unsaved ),
cxunsaved_files.size(),
EditingOptions(),
&clang_translation_unit_ );
if ( failure != CXError_Success ) {
throw ClangParseError( failure );
}
}

Expand Down Expand Up @@ -374,7 +372,7 @@ void TranslationUnit::Reparse(
// param though.
void TranslationUnit::Reparse( std::vector< CXUnsavedFile > &unsaved_files,
size_t parse_options ) {
int failure = 0;
CXErrorCode failure;
{
unique_lock< mutex > lock( clang_access_mutex_ );

Expand All @@ -385,15 +383,18 @@ void TranslationUnit::Reparse( std::vector< CXUnsavedFile > &unsaved_files,
CXUnsavedFile *unsaved = unsaved_files.size() > 0
? &unsaved_files[ 0 ] : nullptr;

failure = clang_reparseTranslationUnit( clang_translation_unit_,
unsaved_files.size(),
unsaved,
parse_options );
// This function should technically return a CXErrorCode enum but return an
// int instead.
failure = static_cast< CXErrorCode >(
clang_reparseTranslationUnit( clang_translation_unit_,
unsaved_files.size(),
unsaved,
parse_options ) );
}

if ( failure ) {
if ( failure != CXError_Success ) {
Destroy();
throw( ClangParseError() );
throw ClangParseError( failure );
}

UpdateLatestDiagnostics();
Expand Down
2 changes: 1 addition & 1 deletion cpp/ycm/ClangCompleter/TranslationUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class TranslationUnit {

YCM_EXPORT bool IsCurrentlyUpdating() const;

std::vector< Diagnostic > Reparse(
YCM_EXPORT std::vector< Diagnostic > Reparse(
const std::vector< UnsavedFile > &unsaved_files );

YCM_EXPORT std::vector< CompletionData > CandidatesForLocation(
Expand Down
5 changes: 2 additions & 3 deletions cpp/ycm/ClangCompleter/TranslationUnitStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include "TranslationUnitStore.h"
#include "TranslationUnit.h"
#include "Utils.h"
#include "exceptions.h"

#include <functional>

Expand Down Expand Up @@ -106,9 +105,9 @@ shared_ptr< TranslationUnit > TranslationUnitStore::GetOrCreate(
unsaved_files,
flags,
clang_index_ );
} catch ( ClangParseError & ) {
} catch ( const ClangParseError & ) {
Remove( filename );
return unit;
throw;
}

{
Expand Down
36 changes: 36 additions & 0 deletions cpp/ycm/PythonSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,42 @@ YCM_EXPORT boost::python::list FilterAndSortCandidates(
/// a string. Supports newstr and newbytes from python-future on Python 2.
std::string GetUtf8String( const boost::python::object &value );

/// Expose the C++ exception |CppException| as a Python exception inheriting
/// from the base exception |base_exception| (default being Exception) with the
/// fully qualified name <module>.|name| where <module> is the current
/// Boost.Python module. |CppException| must define a what() method (easiest way
/// is to derive it from std::runtime_error). This templated class should be
/// instantiated inside the BOOST_PYTHON_MODULE macro.
template< typename CppException >
class PythonException {
public:

PythonException( const char* name,
PyObject* base_exception = PyExc_Exception ) {
std::string module_name = boost::python::extract< std::string >(
boost::python::scope().attr( "__name__" ) );
std::string fully_qualified_name = module_name + "." + name;
// PyErr_NewException does not modify the exception name so it's safe to
// cast away constness.
char *raw_name = const_cast< char * >( fully_qualified_name.c_str() );
python_exception_ = PyErr_NewException( raw_name, base_exception, NULL );

// Add the Python exception to the current Boost.Python module.
boost::python::scope().attr( name ) = boost::python::handle<>(
python_exception_ );

boost::python::register_exception_translator< CppException >( *this );
};

void operator() ( const CppException &cpp_exception ) const {
PyErr_SetString( python_exception_, cpp_exception.what() );
}

private:
PyObject* python_exception_;

};

} // namespace YouCompleteMe

#endif /* end of include guard: PYTHONSUPPORT_H_KWGFEX0V */
Expand Down
8 changes: 0 additions & 8 deletions cpp/ycm/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,4 @@ std::string ReadUtf8File( const fs::path &filepath ) {
return std::string();
}


void WriteUtf8File( const fs::path &filepath, const std::string &contents ) {
fs::ofstream file;
file.open( filepath );
file << contents;
file.close();
}

} // namespace YouCompleteMe
5 changes: 0 additions & 5 deletions cpp/ycm/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,6 @@ YCM_EXPORT inline std::string SwapCase( const std::string &text ) {
// an exception is thrown.
std::string ReadUtf8File( const fs::path &filepath );

// Writes the entire contents of the specified file. If the file does not exist,
// an exception is thrown.
YCM_EXPORT void WriteUtf8File( const fs::path &filepath,
const std::string &contents );

template <class Container, class Key>
typename Container::mapped_type &
GetValueElseInsert( Container &container,
Expand Down
35 changes: 0 additions & 35 deletions cpp/ycm/exceptions.h

This file was deleted.

Loading