Support for showing extra info for diagstics
This was intended to show the full clang output for a given diagnostic, including notes. But it appears that libclang does not provide this functionality...
This commit is contained in:
parent
a4d344aa36
commit
daef17feb4
@ -74,6 +74,9 @@ function! youcompleteme#Enable()
|
||||
inoremap <unique> <C-Space> <C-X><C-O><C-P>
|
||||
endif
|
||||
|
||||
" TODO: make this a nicer, customizable map
|
||||
nnoremap <unique> <leader>d :call <sid>ShowDetailedDiagnostic()<cr>
|
||||
|
||||
" Calling this once solves the problem of BufRead/BufEnter not triggering for
|
||||
" the first loaded file. This should be the last command executed in this
|
||||
" function!
|
||||
@ -350,6 +353,11 @@ function! youcompleteme#OmniComplete( findstart, base )
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:ShowDetailedDiagnostic()
|
||||
py ycm_state.ShowDetailedDiagnostic()
|
||||
endfunction
|
||||
|
||||
|
||||
" This is what Syntastic calls indirectly when it decides an auto-check is
|
||||
" required (currently that's on buffer save) OR when the SyntasticCheck command
|
||||
" is invoked
|
||||
@ -357,6 +365,7 @@ function! youcompleteme#CurrentFileDiagnostics()
|
||||
return pyeval( 'ycm_state.GetDiagnosticsForCurrentFile()' )
|
||||
endfunction
|
||||
|
||||
|
||||
" This is basic vim plugin boilerplate
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
@ -123,6 +123,38 @@ std::vector< CompletionData > ToCompletionDataVector(
|
||||
}
|
||||
|
||||
|
||||
// NOTE: The passed in pointer should never be NULL!
|
||||
// TODO: move all functions that are not external into an unnamed namespace
|
||||
std::string FullDiagnosticText( CXDiagnostic cxdiagnostic )
|
||||
{
|
||||
std::string full_text = CXStringToString( clang_formatDiagnostic(
|
||||
cxdiagnostic,
|
||||
clang_defaultDiagnosticDisplayOptions() ) );
|
||||
|
||||
// Note: clang docs say that a CXDiagnosticSet retrieved with
|
||||
// clang_getChildDiagnostics do NOT need to be released with
|
||||
// clang_diposeDiagnosticSet
|
||||
CXDiagnosticSet diag_set = clang_getChildDiagnostics( cxdiagnostic );
|
||||
if ( !diag_set )
|
||||
return full_text;
|
||||
|
||||
uint num_child_diagnostics = clang_getNumDiagnosticsInSet( diag_set );
|
||||
if ( !num_child_diagnostics )
|
||||
return full_text;
|
||||
|
||||
for ( uint i = 0; i < num_child_diagnostics; ++i )
|
||||
{
|
||||
CXDiagnostic diagnostic = clang_getDiagnosticInSet( diag_set, i );
|
||||
if ( !diagnostic )
|
||||
continue;
|
||||
|
||||
full_text.append( FullDiagnosticText( diagnostic ) );
|
||||
}
|
||||
|
||||
return full_text;
|
||||
}
|
||||
|
||||
|
||||
Diagnostic CXDiagnosticToDiagnostic( CXDiagnostic cxdiagnostic )
|
||||
{
|
||||
Diagnostic diagnostic;
|
||||
@ -145,9 +177,11 @@ Diagnostic CXDiagnosticToDiagnostic( CXDiagnostic cxdiagnostic )
|
||||
&diagnostic.line_number_,
|
||||
&diagnostic.column_number_,
|
||||
&unused_offset );
|
||||
|
||||
diagnostic.filename_ = CXStringToString( clang_getFileName( file ) );
|
||||
diagnostic.text_ = CXStringToString(
|
||||
clang_getDiagnosticSpelling( cxdiagnostic ) );
|
||||
diagnostic.long_formatted_text_ = FullDiagnosticText( cxdiagnostic );
|
||||
|
||||
clang_disposeDiagnostic( cxdiagnostic );
|
||||
return diagnostic;
|
||||
|
@ -47,6 +47,8 @@ struct Diagnostic
|
||||
std::string filename_;
|
||||
|
||||
std::string text_;
|
||||
|
||||
std::string long_formatted_text_;
|
||||
};
|
||||
|
||||
} // namespace YouCompleteMe
|
||||
|
@ -54,7 +54,8 @@ BOOST_PYTHON_MODULE(ycm_core)
|
||||
.def_readonly( "column_number_", &Diagnostic::column_number_ )
|
||||
.def_readonly( "kind_", &Diagnostic::kind_ )
|
||||
.def_readonly( "filename_", &Diagnostic::filename_ )
|
||||
.def_readonly( "text_", &Diagnostic::text_ );
|
||||
.def_readonly( "text_", &Diagnostic::text_ )
|
||||
.def_readonly( "long_formatted_text_", &Diagnostic::long_formatted_text_ );
|
||||
|
||||
class_< std::vector< Diagnostic > >( "DiagnosticVec" )
|
||||
.def( vector_indexing_suite< std::vector< Diagnostic > >() );
|
||||
|
@ -78,6 +78,10 @@ class Completer( object ):
|
||||
return []
|
||||
|
||||
|
||||
def ShowDetailedDiagnostic( self ):
|
||||
pass
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def SupportedFiletypes( self ):
|
||||
pass
|
||||
|
@ -18,6 +18,7 @@
|
||||
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from completers.completer import Completer
|
||||
from collections import defaultdict
|
||||
import vim
|
||||
import vimsupport
|
||||
import ycm_core
|
||||
@ -32,7 +33,7 @@ class ClangCompleter( Completer ):
|
||||
self.completer.EnableThreading()
|
||||
self.contents_holder = []
|
||||
self.filename_holder = []
|
||||
self.last_diagnostics = []
|
||||
self.last_prepared_diagnostics = []
|
||||
self.parse_future = None
|
||||
self.flags = Flags()
|
||||
|
||||
@ -127,11 +128,38 @@ class ClangCompleter( Completer ):
|
||||
|
||||
def GetDiagnosticsForCurrentFile( self ):
|
||||
if self.DiagnosticsForCurrentFileReady():
|
||||
self.last_diagnostics = [ DiagnosticToDict( x ) for x in
|
||||
self.completer.DiagnosticsForFile(
|
||||
vim.current.buffer.name ) ]
|
||||
diagnostics = self.completer.DiagnosticsForFile( vim.current.buffer.name )
|
||||
self.diagnostic_store = DiagnosticsToDiagStructure( diagnostics )
|
||||
self.last_prepared_diagnostics = [ DiagnosticToDict( x ) for x in
|
||||
diagnostics ]
|
||||
self.parse_future = None
|
||||
return self.last_diagnostics
|
||||
return self.last_prepared_diagnostics
|
||||
|
||||
|
||||
def ShowDetailedDiagnostic( self ):
|
||||
current_line, current_column = vimsupport.CurrentLineAndColumn()
|
||||
|
||||
# CurrentLineAndColumn() numbers are 0-based, clang numbers are 1-based
|
||||
current_line += 1
|
||||
current_column += 1
|
||||
|
||||
current_file = vim.current.buffer.name
|
||||
diagnostics = self.diagnostic_store[ current_file ][ current_line ]
|
||||
|
||||
if not diagnostics:
|
||||
vimsupport.PostVimMessage( "No diagnostic for current line!" )
|
||||
return
|
||||
|
||||
closest_diagnostic = None
|
||||
distance_to_closest_diagnostic = 999
|
||||
|
||||
for diagnostic in diagnostics:
|
||||
distance = abs( current_column - diagnostic.column_number_ )
|
||||
if distance < distance_to_closest_diagnostic:
|
||||
distance_to_closest_diagnostic = distance
|
||||
closest_diagnostic = diagnostic
|
||||
|
||||
vimsupport.EchoText( closest_diagnostic.long_formatted_text_ )
|
||||
|
||||
|
||||
def ShouldUseNow( self, start_column ):
|
||||
@ -165,6 +193,14 @@ def DiagnosticToDict( diagnostic ):
|
||||
}
|
||||
|
||||
|
||||
def DiagnosticsToDiagStructure( diagnostics ):
|
||||
structure = defaultdict(lambda : defaultdict(list))
|
||||
for diagnostic in diagnostics:
|
||||
structure[ diagnostic.filename_ ][ diagnostic.line_number_ ].append(
|
||||
diagnostic )
|
||||
return structure
|
||||
|
||||
|
||||
def ClangAvailableForBuffer( buffer_object ):
|
||||
filetype = vim.eval( 'getbufvar({0}, "&ft")'.format( buffer_object.number ) )
|
||||
return filetype in CLANG_FILETYPES
|
||||
|
@ -20,6 +20,7 @@
|
||||
import vim
|
||||
|
||||
def CurrentLineAndColumn():
|
||||
"""Returns the 0-based current line."""
|
||||
# See the comment in CurrentColumn about the calculation for the line and
|
||||
# column number
|
||||
line, column = vim.current.window.cursor
|
||||
@ -28,8 +29,9 @@ def CurrentLineAndColumn():
|
||||
|
||||
|
||||
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."""
|
||||
"""Returns the 0-based current column. 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."""
|
||||
|
||||
# vim's columns are 1-based while vim.current.line columns are 0-based
|
||||
# ... but vim.current.window.cursor (which returns a (line, column) tuple)
|
||||
@ -58,6 +60,10 @@ def PostVimMessage( message ):
|
||||
.format( message ) )
|
||||
|
||||
|
||||
def EchoText( text ):
|
||||
vim.command( "echom '{0}'".format( text.replace( "'", r"''") ) )
|
||||
|
||||
|
||||
def EscapeForVim( text ):
|
||||
return text.replace( "'", "''" )
|
||||
|
||||
|
@ -106,6 +106,11 @@ class YouCompleteMe( object ):
|
||||
return []
|
||||
|
||||
|
||||
def ShowDetailedDiagnostic( self ):
|
||||
if self.FiletypeCompletionEnabledForCurrentFile():
|
||||
return self.GetFiletypeCompleterForCurrentFile().ShowDetailedDiagnostic()
|
||||
|
||||
|
||||
def OnCurrentIdentifierFinished( self ):
|
||||
self.identcomp.OnCurrentIdentifierFinished()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user