Skip to content

Commit

Permalink
Translate libclang error codes to exceptions
Browse files Browse the repository at this point in the history
Do not silence the exceptions.
  • Loading branch information
micbou committed Nov 4, 2017
1 parent 0c2a614 commit ed3b504
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 170 deletions.
38 changes: 2 additions & 36 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 @@ -83,21 +82,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 @@ -112,9 +105,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 @@ -132,10 +122,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 @@ -151,10 +137,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 @@ -170,10 +152,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 @@ -189,10 +167,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 @@ -213,10 +187,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 @@ -237,10 +207,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 @@ -43,4 +43,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 "Parsing the translation unit with invalid arguments.";
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 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 @@ -94,18 +93,17 @@ TranslationUnit::TranslationUnit(
? &cxunsaved_files[ 0 ] : NULL;

// 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 @@ -352,7 +350,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 @@ -362,15 +360,18 @@ void TranslationUnit::Reparse( std::vector< CXUnsavedFile > &unsaved_files,
CXUnsavedFile *unsaved = unsaved_files.size() > 0
? &unsaved_files[ 0 ] : NULL;

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
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 @@ -41,6 +41,42 @@ YCM_DLL_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<>(
boost::python::borrowed( 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
40 changes: 0 additions & 40 deletions cpp/ycm/exceptions.h

This file was deleted.

55 changes: 0 additions & 55 deletions cpp/ycm/tests/ClangCompleter/ClangCompleter_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,59 +204,4 @@ TEST( ClangCompleterTest, GetDocString ) {
}
}


TEST( ClangCompleterTest, NoTranslationUnit ) {
ClangCompleter completer;

const std::string filename;
const std::vector< UnsavedFile > unsaved_files;
const std::vector< std::string > flags;

EXPECT_EQ( std::vector< Diagnostic >(),
completer.UpdateTranslationUnit( filename, unsaved_files, flags) );

EXPECT_EQ( std::vector< CompletionData >(),
completer.CandidatesForLocationInFile( filename,
1,
1,
unsaved_files,
flags ) );

EXPECT_EQ( Location(), completer.GetDeclarationLocation( filename,
1,
1,
unsaved_files,
flags ) );
EXPECT_EQ( Location(), completer.GetDefinitionLocation( filename,
1,
1,
unsaved_files,
flags ) );
EXPECT_EQ( std::string( "no unit" ),
completer.GetTypeAtLocation( filename,
1,
1,
unsaved_files,
flags ) );
EXPECT_EQ( std::string( "no unit" ),
completer.GetEnclosingFunctionAtLocation( filename,
1,
1,
unsaved_files,
flags ) );
EXPECT_EQ( std::vector< FixIt >(),
completer.GetFixItsForLocationInFile( filename,
1,
1,
unsaved_files,
flags ) );

EXPECT_EQ( DocumentationData(),
completer.GetDocsForLocationInFile( filename,
1,
1,
unsaved_files,
flags ) );
}

} // namespace YouCompleteMe
Loading

0 comments on commit ed3b504

Please sign in to comment.