Adding diagnostic extraction support
Next step is to add support to Syntastic so that it uses this new functionality
This commit is contained in:
parent
bfafad4f50
commit
958a008462
@ -132,6 +132,7 @@ function! s:OnInsertLeave()
|
||||
let s:omnifunc_mode = 0
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:IdentifierFinishedOperations()
|
||||
if !pyeval( 'ycm.CurrentIdentifierFinished()' )
|
||||
return
|
||||
@ -273,6 +274,14 @@ function! youcompleteme#ClangOmniComplete( findstart, base )
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! youcompleteme#CurrentFileDiagnostics()
|
||||
if s:ClangEnabledForCurrentFile()
|
||||
return pyeval( 'clangcomp.GetDiagnosticsForCurrentFile()' )
|
||||
endif
|
||||
return []
|
||||
endfunction
|
||||
|
||||
" This is basic vim plugin boilerplate
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
@ -80,14 +80,14 @@ set_target_properties( ${PROJECT_NAME} PROPERTIES
|
||||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG )
|
||||
# We want all warnings, and warnings should be treated as errors
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror" )
|
||||
endif()
|
||||
|
||||
#############################################################################
|
||||
|
||||
# We want warnings if we accidentally use C++11 features
|
||||
if ( COMPILER_IS_CLANG )
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wc++98-compat")
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wc++98-compat" )
|
||||
endif()
|
||||
|
||||
#############################################################################
|
||||
|
@ -168,6 +168,28 @@ char CursorKindToVimKind( CXCursorKind kind )
|
||||
}
|
||||
|
||||
|
||||
char DiagnosticSeverityToType( CXDiagnosticSeverity severity )
|
||||
{
|
||||
switch ( severity )
|
||||
{
|
||||
case CXDiagnostic_Ignored:
|
||||
case CXDiagnostic_Note:
|
||||
return 'I';
|
||||
|
||||
case CXDiagnostic_Warning:
|
||||
return 'W';
|
||||
|
||||
case CXDiagnostic_Error:
|
||||
case CXDiagnostic_Fatal:
|
||||
return 'E';
|
||||
|
||||
default:
|
||||
return 'E';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: this should be a constructor
|
||||
CompletionData CompletionResultToCompletionData(
|
||||
const CXCompletionResult &completion_result )
|
||||
{
|
||||
@ -238,6 +260,34 @@ std::vector< CompletionData > ToCompletionDataVector(
|
||||
}
|
||||
|
||||
|
||||
Diagnostic CXDiagnosticToDiagnostic( CXDiagnostic cxdiagnostic )
|
||||
{
|
||||
Diagnostic diagnostic;
|
||||
diagnostic.kind_ = DiagnosticSeverityToType(
|
||||
clang_getDiagnosticSeverity( cxdiagnostic ) );
|
||||
|
||||
// If this is an "ignored" diagnostic, there's no point in continuing since we
|
||||
// won't display those to the user
|
||||
if ( diagnostic.kind_ == 'I' )
|
||||
return diagnostic;
|
||||
|
||||
CXSourceLocation location = clang_getDiagnosticLocation( cxdiagnostic );
|
||||
CXFile file;
|
||||
uint unused_offset;
|
||||
clang_getSpellingLocation( location,
|
||||
&file,
|
||||
&diagnostic.line_number_,
|
||||
&diagnostic.column_number_,
|
||||
&unused_offset );
|
||||
diagnostic.filename_ = CXStringToString( clang_getFileName( file ) );
|
||||
diagnostic.text_ = CXStringToString(
|
||||
clang_getDiagnosticSpelling( cxdiagnostic ) );
|
||||
|
||||
clang_disposeDiagnostic( cxdiagnostic );
|
||||
return diagnostic;
|
||||
}
|
||||
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
|
||||
@ -287,6 +337,32 @@ void ClangCompleter::SetFileCompileFlags(
|
||||
}
|
||||
|
||||
|
||||
std::vector< Diagnostic > ClangCompleter::DiagnosticsForFile(
|
||||
const std::string &filename )
|
||||
{
|
||||
CXTranslationUnit unit = FindWithDefault( filename_to_translation_unit_,
|
||||
filename,
|
||||
NULL );
|
||||
std::vector< Diagnostic > diagnostics;
|
||||
if ( !unit )
|
||||
return diagnostics;
|
||||
|
||||
uint num_diagnostics = clang_getNumDiagnostics( unit );
|
||||
diagnostics.reserve( num_diagnostics );
|
||||
|
||||
for ( uint i = 0; i < num_diagnostics; ++i )
|
||||
{
|
||||
Diagnostic diagnostic = CXDiagnosticToDiagnostic(
|
||||
clang_getDiagnostic( unit, i ) );
|
||||
|
||||
if ( diagnostic.kind_ != 'I' )
|
||||
diagnostics.push_back( diagnostic );
|
||||
}
|
||||
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
|
||||
bool ClangCompleter::UpdatingTranslationUnit()
|
||||
{
|
||||
lock_guard< mutex > lock( file_parse_task_mutex_ );
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "ConcurrentLatestValue.h"
|
||||
#include "Future.h"
|
||||
#include "UnsavedFile.h"
|
||||
#include "Diagnostic.h"
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
@ -60,6 +61,8 @@ public:
|
||||
void SetFileCompileFlags( const std::string &filename,
|
||||
const std::vector< std::string > &flags );
|
||||
|
||||
std::vector< Diagnostic > DiagnosticsForFile( const std::string &filename );
|
||||
|
||||
bool UpdatingTranslationUnit();
|
||||
|
||||
void UpdateTranslationUnit( const std::string &filename,
|
||||
|
@ -18,6 +18,8 @@
|
||||
#ifndef COMPLETIONDATA_H_2JCTF1NU
|
||||
#define COMPLETIONDATA_H_2JCTF1NU
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace YouCompleteMe
|
||||
{
|
||||
|
||||
|
54
cpp/ycm/Diagnostic.h
Normal file
54
cpp/ycm/Diagnostic.h
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2011, 2012 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/>.
|
||||
|
||||
#ifndef DIAGNOSTIC_H_BZH3BWIZ
|
||||
#define DIAGNOSTIC_H_BZH3BWIZ
|
||||
|
||||
#include "standard.h"
|
||||
#include <string>
|
||||
|
||||
namespace YouCompleteMe
|
||||
{
|
||||
|
||||
struct Diagnostic
|
||||
{
|
||||
bool operator== ( const Diagnostic &other ) const
|
||||
{
|
||||
return
|
||||
line_number_ == other.line_number_ &&
|
||||
column_number_ == other.column_number_ &&
|
||||
kind_ == other.kind_ &&
|
||||
text_ == other.text_;
|
||||
}
|
||||
|
||||
uint line_number_;
|
||||
uint column_number_;
|
||||
|
||||
// Vim's error "kind"
|
||||
// 'I' -> informational
|
||||
// 'W' -> warning
|
||||
// 'E' -> error
|
||||
char kind_;
|
||||
|
||||
std::string filename_;
|
||||
|
||||
std::string text_;
|
||||
};
|
||||
|
||||
} // namespace YouCompleteMe
|
||||
|
||||
#endif /* end of include guard: DIAGNOSTIC_H_BZH3BWIZ */
|
@ -55,13 +55,13 @@ bool ContainsKey( Container &container, const Key &key )
|
||||
|
||||
|
||||
template <class Container, class Key>
|
||||
const typename Container::mapped_type &
|
||||
typename Container::mapped_type
|
||||
FindWithDefault( Container &container,
|
||||
const Key &key,
|
||||
const typename Container::mapped_type &value )
|
||||
{
|
||||
typename Container::iterator it = container.find( key );
|
||||
return it != container.end() ? *it : value;
|
||||
return it != container.end() ? it->second : value;
|
||||
}
|
||||
|
||||
} // namespace YouCompleteMe
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "ClangCompleter.h"
|
||||
#include "Future.h"
|
||||
#include "CompletionData.h"
|
||||
#include "Diagnostic.h"
|
||||
#include "UnsavedFile.h"
|
||||
|
||||
#include <boost/python.hpp>
|
||||
@ -47,6 +48,16 @@ BOOST_PYTHON_MODULE(indexer)
|
||||
"CompletionVec" )
|
||||
.def( vector_indexing_suite< std::vector< CompletionData > >() );
|
||||
|
||||
class_< Diagnostic >( "Diagnostic" )
|
||||
.def_readonly( "line_number_", &Diagnostic::line_number_ )
|
||||
.def_readonly( "column_number_", &Diagnostic::column_number_ )
|
||||
.def_readonly( "kind_", &Diagnostic::kind_ )
|
||||
.def_readonly( "filename_", &Diagnostic::filename_ )
|
||||
.def_readonly( "text_", &Diagnostic::text_ );
|
||||
|
||||
class_< std::vector< Diagnostic > >( "DiagnosticVec" )
|
||||
.def( vector_indexing_suite< std::vector< Diagnostic > >() );
|
||||
|
||||
class_< Future< AsyncResults > >( "Future" )
|
||||
.def( "ResultsReady", &Future< AsyncResults >::ResultsReady )
|
||||
.def( "GetResults", &Future< AsyncResults >::GetResults );
|
||||
@ -86,6 +97,7 @@ BOOST_PYTHON_MODULE(indexer)
|
||||
.def( "EnableThreading", &ClangCompleter::EnableThreading )
|
||||
.def( "SetGlobalCompileFlags", &ClangCompleter::SetGlobalCompileFlags )
|
||||
.def( "SetFileCompileFlags", &ClangCompleter::SetFileCompileFlags )
|
||||
.def( "DiagnosticsForFile", &ClangCompleter::DiagnosticsForFile )
|
||||
.def( "UpdatingTranslationUnit", &ClangCompleter::UpdatingTranslationUnit )
|
||||
.def( "UpdateTranslationUnitAsync",
|
||||
&ClangCompleter::UpdateTranslationUnitAsync )
|
||||
|
@ -15,8 +15,9 @@
|
||||
" You should have received a copy of the GNU General Public License
|
||||
" along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if exists("g:loaded_youcompleteme")
|
||||
if exists( "g:loaded_youcompleteme" )
|
||||
finish
|
||||
" TODO: check for python too
|
||||
elseif v:version < 703 || !has( 'patch584' )
|
||||
echohl WarningMsg |
|
||||
\ echomsg "YouCompleteMe unavailable: requires Vim 7.3.584+" |
|
||||
|
@ -184,6 +184,12 @@ class ClangCompleter( Completer ):
|
||||
self.GetUnsavedFilesVector() )
|
||||
|
||||
|
||||
def GetDiagnosticsForCurrentFile( self ):
|
||||
return [ DiagnosticToDict( x ) for x in
|
||||
self.completer.DiagnosticsForFile( vim.current.buffer.name ) ]
|
||||
|
||||
|
||||
|
||||
def PostVimMessage( message ):
|
||||
# TODO: escape the message string before formating it
|
||||
vim.command( 'echohl WarningMsg | echomsg "{0}" | echohl None'
|
||||
@ -210,6 +216,18 @@ def CompletionDataToDict( completion_data ):
|
||||
}
|
||||
|
||||
|
||||
def DiagnosticToDict( diagnostic ):
|
||||
# see :h getqflist for a description of the dictionary fields
|
||||
return {
|
||||
'bufnr' : int( vim.eval( "bufnr('" + diagnostic.filename_ + "', 1)" ) ),
|
||||
'lnum' : diagnostic.line_number_,
|
||||
'col' : diagnostic.column_number_,
|
||||
'text' : diagnostic.text_,
|
||||
'type' : diagnostic.kind_,
|
||||
'valid' : 1
|
||||
}
|
||||
|
||||
|
||||
def CurrentColumn():
|
||||
"""Do NOT access the CurrentColumn in vim.current.line. It doesn't exist yet.
|
||||
Only the chars before the current column exist in vim.current.line."""
|
||||
|
Loading…
Reference in New Issue
Block a user