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
|
let s:omnifunc_mode = 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! s:IdentifierFinishedOperations()
|
function! s:IdentifierFinishedOperations()
|
||||||
if !pyeval( 'ycm.CurrentIdentifierFinished()' )
|
if !pyeval( 'ycm.CurrentIdentifierFinished()' )
|
||||||
return
|
return
|
||||||
@ -273,6 +274,14 @@ function! youcompleteme#ClangOmniComplete( findstart, base )
|
|||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! youcompleteme#CurrentFileDiagnostics()
|
||||||
|
if s:ClangEnabledForCurrentFile()
|
||||||
|
return pyeval( 'clangcomp.GetDiagnosticsForCurrentFile()' )
|
||||||
|
endif
|
||||||
|
return []
|
||||||
|
endfunction
|
||||||
|
|
||||||
" This is basic vim plugin boilerplate
|
" This is basic vim plugin boilerplate
|
||||||
let &cpo = s:save_cpo
|
let &cpo = s:save_cpo
|
||||||
unlet s:save_cpo
|
unlet s:save_cpo
|
||||||
|
@ -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(
|
CompletionData CompletionResultToCompletionData(
|
||||||
const CXCompletionResult &completion_result )
|
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
|
} // 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()
|
bool ClangCompleter::UpdatingTranslationUnit()
|
||||||
{
|
{
|
||||||
lock_guard< mutex > lock( file_parse_task_mutex_ );
|
lock_guard< mutex > lock( file_parse_task_mutex_ );
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "ConcurrentLatestValue.h"
|
#include "ConcurrentLatestValue.h"
|
||||||
#include "Future.h"
|
#include "Future.h"
|
||||||
#include "UnsavedFile.h"
|
#include "UnsavedFile.h"
|
||||||
|
#include "Diagnostic.h"
|
||||||
|
|
||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
@ -60,6 +61,8 @@ public:
|
|||||||
void SetFileCompileFlags( const std::string &filename,
|
void SetFileCompileFlags( const std::string &filename,
|
||||||
const std::vector< std::string > &flags );
|
const std::vector< std::string > &flags );
|
||||||
|
|
||||||
|
std::vector< Diagnostic > DiagnosticsForFile( const std::string &filename );
|
||||||
|
|
||||||
bool UpdatingTranslationUnit();
|
bool UpdatingTranslationUnit();
|
||||||
|
|
||||||
void UpdateTranslationUnit( const std::string &filename,
|
void UpdateTranslationUnit( const std::string &filename,
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
#ifndef COMPLETIONDATA_H_2JCTF1NU
|
#ifndef COMPLETIONDATA_H_2JCTF1NU
|
||||||
#define COMPLETIONDATA_H_2JCTF1NU
|
#define COMPLETIONDATA_H_2JCTF1NU
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace YouCompleteMe
|
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>
|
template <class Container, class Key>
|
||||||
const typename Container::mapped_type &
|
typename Container::mapped_type
|
||||||
FindWithDefault( Container &container,
|
FindWithDefault( Container &container,
|
||||||
const Key &key,
|
const Key &key,
|
||||||
const typename Container::mapped_type &value )
|
const typename Container::mapped_type &value )
|
||||||
{
|
{
|
||||||
typename Container::iterator it = container.find( key );
|
typename Container::iterator it = container.find( key );
|
||||||
return it != container.end() ? *it : value;
|
return it != container.end() ? it->second : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace YouCompleteMe
|
} // namespace YouCompleteMe
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "ClangCompleter.h"
|
#include "ClangCompleter.h"
|
||||||
#include "Future.h"
|
#include "Future.h"
|
||||||
#include "CompletionData.h"
|
#include "CompletionData.h"
|
||||||
|
#include "Diagnostic.h"
|
||||||
#include "UnsavedFile.h"
|
#include "UnsavedFile.h"
|
||||||
|
|
||||||
#include <boost/python.hpp>
|
#include <boost/python.hpp>
|
||||||
@ -47,6 +48,16 @@ BOOST_PYTHON_MODULE(indexer)
|
|||||||
"CompletionVec" )
|
"CompletionVec" )
|
||||||
.def( vector_indexing_suite< std::vector< CompletionData > >() );
|
.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" )
|
class_< Future< AsyncResults > >( "Future" )
|
||||||
.def( "ResultsReady", &Future< AsyncResults >::ResultsReady )
|
.def( "ResultsReady", &Future< AsyncResults >::ResultsReady )
|
||||||
.def( "GetResults", &Future< AsyncResults >::GetResults );
|
.def( "GetResults", &Future< AsyncResults >::GetResults );
|
||||||
@ -86,6 +97,7 @@ BOOST_PYTHON_MODULE(indexer)
|
|||||||
.def( "EnableThreading", &ClangCompleter::EnableThreading )
|
.def( "EnableThreading", &ClangCompleter::EnableThreading )
|
||||||
.def( "SetGlobalCompileFlags", &ClangCompleter::SetGlobalCompileFlags )
|
.def( "SetGlobalCompileFlags", &ClangCompleter::SetGlobalCompileFlags )
|
||||||
.def( "SetFileCompileFlags", &ClangCompleter::SetFileCompileFlags )
|
.def( "SetFileCompileFlags", &ClangCompleter::SetFileCompileFlags )
|
||||||
|
.def( "DiagnosticsForFile", &ClangCompleter::DiagnosticsForFile )
|
||||||
.def( "UpdatingTranslationUnit", &ClangCompleter::UpdatingTranslationUnit )
|
.def( "UpdatingTranslationUnit", &ClangCompleter::UpdatingTranslationUnit )
|
||||||
.def( "UpdateTranslationUnitAsync",
|
.def( "UpdateTranslationUnitAsync",
|
||||||
&ClangCompleter::UpdateTranslationUnitAsync )
|
&ClangCompleter::UpdateTranslationUnitAsync )
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
if exists( "g:loaded_youcompleteme" )
|
if exists( "g:loaded_youcompleteme" )
|
||||||
finish
|
finish
|
||||||
|
" TODO: check for python too
|
||||||
elseif v:version < 703 || !has( 'patch584' )
|
elseif v:version < 703 || !has( 'patch584' )
|
||||||
echohl WarningMsg |
|
echohl WarningMsg |
|
||||||
\ echomsg "YouCompleteMe unavailable: requires Vim 7.3.584+" |
|
\ echomsg "YouCompleteMe unavailable: requires Vim 7.3.584+" |
|
||||||
|
@ -184,6 +184,12 @@ class ClangCompleter( Completer ):
|
|||||||
self.GetUnsavedFilesVector() )
|
self.GetUnsavedFilesVector() )
|
||||||
|
|
||||||
|
|
||||||
|
def GetDiagnosticsForCurrentFile( self ):
|
||||||
|
return [ DiagnosticToDict( x ) for x in
|
||||||
|
self.completer.DiagnosticsForFile( vim.current.buffer.name ) ]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def PostVimMessage( message ):
|
def PostVimMessage( message ):
|
||||||
# TODO: escape the message string before formating it
|
# TODO: escape the message string before formating it
|
||||||
vim.command( 'echohl WarningMsg | echomsg "{0}" | echohl None'
|
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():
|
def CurrentColumn():
|
||||||
"""Do NOT access the CurrentColumn in vim.current.line. It doesn't exist yet.
|
"""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."""
|
Only the chars before the current column exist in vim.current.line."""
|
||||||
|
Loading…
Reference in New Issue
Block a user