diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 834ac7a2df..103cd5ed25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: matrix: vim: [ 'new', 'old' ] arch: [ 'x86_64' ] - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 container: 'youcompleteme/ycm-vim-${{ matrix.arch }}-py3:test' env: COVERAGE: true diff --git a/README.md b/README.md index dff492b4f6..4a69cddc87 100644 --- a/README.md +++ b/README.md @@ -1795,12 +1795,20 @@ in the Vim gutter, the relevant groups are: `error` if they exist - `YcmWarningSign`, which falls back to group `SyntasticWarningSign` and then `todo` if they exist +- `YcmInformationSign`, which falls back to group `SyntasticInformationSign` and then + `added` if they exist +- `YcmHintSign`, which falls back to group `SyntasticHintSign` and then + `changed` if they exist You can also style the line that has the warning/error with these groups: - `YcmErrorLine`, which falls back to group `SyntasticErrorLine` if it exists - `YcmWarningLine`, which falls back to group `SyntasticWarningLine` if it exists +- `YcmInformationLine`, which falls back to group `SyntasticInformationLine` if it + exists +- `YcmHintLine`, which falls back to group `SyntasticHintLine` if it + exists Finally, you can also style the popup for the detailed diagnostics (it is shown if `g:ycm_show_detailed_diag_in_popup` is set) using the group `YcmErrorPopup`, @@ -1820,6 +1828,10 @@ The syntax groups used to highlight regions of text with errors/warnings: then `SpellBad` - `YcmWarningSection`, which falls back to group `SyntasticWarning` if it exists and then `SpellCap` +- `YcmInformationSection`, which falls back to group `SyntasticInformation` if it exists + and then `SpellLocal` +- `YcmHintSection`, which falls back to group `SyntasticHint` if it exists + and then `SpellRare` Here's how you'd change the style for a group: @@ -2942,8 +2954,8 @@ let g:ycm_warning_symbol = '>>' ### The `g:ycm_enable_diagnostic_signs` option When this option is set, YCM will put icons in Vim's gutter on lines that have a -diagnostic set. Turning this off will also turn off the `YcmErrorLine` and -`YcmWarningLine` highlighting. +diagnostic set. Turning this off will also turn off the `YcmErrorLine`, +`YcmWarningLine`, `YcmInformationLine` and `YcmHintLine` highlighting. This option is part of the Syntastic compatibility layer; if the option is not set, YCM will fall back to the value of the `g:syntastic_enable_signs` option diff --git a/autoload/youcompleteme.vim b/autoload/youcompleteme.vim index ec8109ea24..af4937a311 100644 --- a/autoload/youcompleteme.vim +++ b/autoload/youcompleteme.vim @@ -400,6 +400,22 @@ function! s:SetUpSigns() endif endif + if !hlexists( 'YcmInformationSign' ) + if hlexists( 'SyntasticInformationSign') + highlight default link YcmInformationSign SyntasticInformationSign + else + highlight default link YcmInformationSign added + endif + endif + + if !hlexists( 'YcmHintSign' ) + if hlexists( 'SyntasticHintSign') + highlight default link YcmHintSign SyntasticHintSign + else + highlight default link YcmHintSign changed + endif + endif + if !hlexists( 'YcmErrorLine' ) highlight default link YcmErrorLine SyntasticErrorLine endif @@ -408,6 +424,14 @@ function! s:SetUpSigns() highlight default link YcmWarningLine SyntasticWarningLine endif + if !hlexists( 'YcmInformationLine' ) + highlight default link YcmInformationLine SyntasticInformationLine + endif + + if !hlexists( 'YcmHintLine' ) + highlight default link YcmHintLine SyntasticHintLine + endif + call sign_define( [ \ { 'name': 'YcmError', \ 'text': g:ycm_error_symbol, @@ -418,6 +442,16 @@ function! s:SetUpSigns() \ 'text': g:ycm_warning_symbol, \ 'texthl': 'YcmWarningSign', \ 'linehl': 'YcmWarningLine', + \ 'group': 'ycm_signs' }, + \ { 'name': 'YcmInformation', + \ 'text': g:ycm_information_symbol, + \ 'texthl': 'YcmInformationSign', + \ 'linehl': 'YcmInformationLine', + \ 'group': 'ycm_signs' }, + \ { 'name': 'YcmHint', + \ 'text': g:ycm_hint_symbol, + \ 'texthl': 'YcmHintSign', + \ 'linehl': 'YcmHintLine', \ 'group': 'ycm_signs' } \ ] ) @@ -476,6 +510,32 @@ function! s:SetUpSyntaxHighlighting() hi default link YcmWarningText Conceal endif endif + if !hlexists( 'YcmInformationText' ) + if exists( '*hlget' ) + let YcmInformationText = hlget( 'SpellLocal', v:true )[ 0 ] + let YcmInformationText.name = 'YcmInformationText' + let YcmInformationText.cterm = {} + let YcmInformationText.gui = {} + let YcmInformationText.term = {} + call hlset( [ YcmInformationText] ) + else + " Lame approximation + hi default link YcmInformationText Conceal + endif + endif + if !hlexists( 'YcmHintText' ) + if exists( '*hlget' ) + let YcmHintText = hlget( 'SpellRare', v:true )[ 0 ] + let YcmHintText.name = 'YcmHintText' + let YcmHintText.cterm = {} + let YcmHintText.gui = {} + let YcmHintText.term = {} + call hlset( [ YcmHintText] ) + else + " Lame approximation + hi default link YcmHintText Conceal + endif + endif if s:PropertyTypeNotDefined( 'YcmVirtDiagError' ) call prop_type_add( 'YcmVirtDiagError', { @@ -489,6 +549,18 @@ function! s:SetUpSyntaxHighlighting() \ 'priority': 19, \ 'combine': 0 } ) endif + if s:PropertyTypeNotDefined( 'YcmVirtDiagInformation' ) + call prop_type_add( 'YcmVirtDiagInformation', { + \ 'highlight': 'YcmInformationText', + \ 'priority': 18, + \ 'combine': 0 } ) + endif + if s:PropertyTypeNotDefined( 'YcmVirtDiagHint' ) + call prop_type_add( 'YcmVirtDiagHint', { + \ 'highlight': 'YcmHintText', + \ 'priority': 17, + \ 'combine': 0 } ) + endif if s:PropertyTypeNotDefined( 'YcmVirtDiagPadding' ) @@ -513,6 +585,36 @@ function! s:SetUpSyntaxHighlighting() \ 'override': 1 } ) endif + if !hlexists( 'YcmInformationSection' ) + if hlexists( 'SyntasticInformation' ) + highlight default link YcmInformationSection SyntasticInformation + else + highlight default link YcmInformationSection SpellLocal + endif + endif + if s:PropertyTypeNotDefined( 'YcmInformationProperty' ) + call prop_type_add( 'YcmInformationProperty', { + \ 'highlight': 'YcmInformationSection', + \ 'priority': 28, + \ 'combine': 0, + \ 'override': 1 } ) + endif + + if !hlexists( 'YcmHintSection' ) + if hlexists( 'SyntasticHint' ) + highlight default link YcmHintSection SyntasticHint + else + highlight default link YcmHintSection SpellRare + endif + endif + if s:PropertyTypeNotDefined( 'YcmHintProperty' ) + call prop_type_add( 'YcmHintProperty', { + \ 'highlight': 'YcmHintSection', + \ 'priority': 27, + \ 'combine': 0, + \ 'override': 1 } ) + endif + if !hlexists( 'YcmErrorPopup' ) highlight default link YcmErrorPopup ErrorMsg endif diff --git a/doc/youcompleteme.txt b/doc/youcompleteme.txt index 3837a9703c..b98fd26e4e 100644 --- a/doc/youcompleteme.txt +++ b/doc/youcompleteme.txt @@ -2052,11 +2052,21 @@ in the Vim gutter, the relevant groups are: - 'YcmWarningSign', which falls back to group 'SyntasticWarningSign' and then 'todo' if they exist +- 'YcmInformationSign', which falls back to group 'SyntasticInformationSign' and then + 'added' if they exist + +- 'YcmHintSign', which falls back to group 'SyntasticHintSign' and then + 'changed' if they exist + You can also style the line that has the warning/error with these groups: - 'YcmErrorLine', which falls back to group 'SyntasticErrorLine' if it exists - 'YcmWarningLine', which falls back to group 'SyntasticWarningLine' if it exists +- 'YcmInformationLine', which falls back to group 'SyntasticInformationLine' if it + exists +- 'YcmHintLine', which falls back to group 'SyntasticHintLine' if it + exists Finally, you can also style the popup for the detailed diagnostics (it is shown if |g:ycm_show_detailed_diag_in_popup| is set) using the group 'YcmErrorPopup', @@ -2073,6 +2083,10 @@ The syntax groups used to highlight regions of text with errors/warnings: - 'YcmErrorSection', which falls back to group 'SyntasticError' if it exists and then 'SpellBad' - 'YcmWarningSection', which falls back to group 'SyntasticWarning' if it exists and then 'SpellCap' + - 'YcmInformationSection', which falls back to group +'SyntasticInformation' if it exists and then 'SpellLocal' + - 'YcmHintSection', which falls back to group +'SyntasticHint' if it exists and then 'SpellRare' Here's how you'd change the style for a group: > @@ -3217,8 +3231,8 @@ Default: '>>' The *g:ycm_enable_diagnostic_signs* option When this option is set, YCM will put icons in Vim's gutter on lines that have -a diagnostic set. Turning this off will also turn off the 'YcmErrorLine' and -'YcmWarningLine' highlighting. +a diagnostic set. Turning this off will also turn off the 'YcmErrorLine', +'YcmWarningLine', 'YcmInformationLine' and 'YcmHintLine' highlighting. This option is part of the Syntastic compatibility layer; if the option is not set, YCM will fall back to the value of the 'g:syntastic_enable_signs' option diff --git a/plugin/youcompleteme.vim b/plugin/youcompleteme.vim index 5c0ab1d37b..c7e9007178 100644 --- a/plugin/youcompleteme.vim +++ b/plugin/youcompleteme.vim @@ -174,6 +174,14 @@ let g:ycm_warning_symbol = \ get( g:, 'ycm_warning_symbol', \ get( g:, 'syntastic_warning_symbol', '>>' ) ) +let g:ycm_information_symbol = + \ get( g:, 'ycm_information_symbol', + \ get( g:, 'syntastic_information_symbol', '--' ) ) + +let g:ycm_hint_symbol = + \ get( g:, 'ycm_hint_symbol', + \ get( g:, 'syntastic_hint_symbol', '? ' ) ) + let g:ycm_complete_in_comments = \ get( g:, 'ycm_complete_in_comments', 0 ) diff --git a/python/ycm/diagnostic_filter.py b/python/ycm/diagnostic_filter.py index 48ff0b0dc6..19957c3780 100644 --- a/python/ycm/diagnostic_filter.py +++ b/python/ycm/diagnostic_filter.py @@ -83,7 +83,7 @@ def FilterRegex( diagnostic ): def CompileLevel( level ): - # valid kinds are WARNING and ERROR; + # valid kinds are WARNING, ERROR, INFORMATION and HINT; # expected input levels are `warning` and `error` # NOTE: we don't validate the input... expected_kind = level.upper() diff --git a/python/ycm/diagnostic_interface.py b/python/ycm/diagnostic_interface.py index 40697fc962..b0c9082980 100644 --- a/python/ycm/diagnostic_interface.py +++ b/python/ycm/diagnostic_interface.py @@ -138,7 +138,9 @@ def _ClearCurrentDiagnostic( self, will_be_replaced=False ): tp.ClearTextProperties( self._bufnr, prop_types = [ 'YcmVirtDiagPadding', 'YcmVirtDiagError', - 'YcmVirtDiagWarning' ] ) + 'YcmVirtDiagWarning' + 'YcmVirtDiagInformation', + 'YcmVirtDiagHint' ] ) else: if not will_be_replaced: vimsupport.PostVimMessage( '', warning = False ) @@ -175,7 +177,9 @@ def MakeVritualTextProperty( prop_type, text, position='after' ): ' ' * vim.buffers[ self._bufnr ].options[ 'shiftwidth' ] ), MakeVritualTextProperty( 'YcmVirtDiagError' if _DiagnosticIsError( first_diag ) - else 'YcmVirtDiagWarning', + else 'YcmVirtDiagWarning' if _DiagnosticIsWarning( first_diag ) + else 'YcmVirtDiagInformation' if _DiagnosticIsInformation( first_diag ) + else 'YcmVirtDiagHint', marker + ' ' + [ line for line in text.splitlines() if line ][ 0 ] ) else: if not text: @@ -259,7 +263,10 @@ def _UpdateSigns( self ): # We always go for the first diagnostic on the line because diagnostics # are sorted by errors in priority and Vim can only display one sign by # line. - name = 'YcmError' if _DiagnosticIsError( diags[ 0 ] ) else 'YcmWarning' + name = ( 'YcmError' if _DiagnosticIsError( diags[ 0 ] ) + else 'YcmWarning' if _DiagnosticIsWarning( diags[ 0 ] ) + else 'YcmInformation' if _DiagnosticIsInformation( diags[ 0 ] ) + else 'YcmHint' ) sign = { 'lnum': line, 'name': name, @@ -286,14 +293,30 @@ def _ConvertDiagListToDict( self ): self._line_to_diags[ line_number ].append( diag ) for diags in self._line_to_diags.values(): - # We also want errors to be listed before warnings so that errors aren't - # hidden by the warnings; Vim won't place a sign over an existing one. - diags.sort( key = lambda diag: ( diag[ 'kind' ], + # We also want sorted by kind priority (e.g. errors than warning etc) so + # that the most important sign is applied first; Vim won't place a sign + # over an existing one. + diags.sort( key = lambda diag: ( _DiagnosticKindSortKey( diag ), diag[ 'location' ][ 'column_num' ] ) ) +def _DiagnosticKindSortKey( diag ): + if _DiagnosticIsError( diag ): + return 1 + elif _DiagnosticIsWarning( diag ): + return 2 + elif _DiagnosticIsInformation( diag ): + return 3 + elif _DiagnosticIsHint( diag ): + return 4 + else: + return 5 + + _DiagnosticIsError = CompileLevel( 'error' ) _DiagnosticIsWarning = CompileLevel( 'warning' ) +_DiagnosticIsInformation = CompileLevel( 'information' ) +_DiagnosticIsHint = CompileLevel( 'information' ) def _NormalizeDiagnostic( diag ): @@ -310,7 +333,9 @@ def _ConvertDiagnosticToTextProperties( bufnr, diagnostic ): properties = [] name = ( 'YcmErrorProperty' if _DiagnosticIsError( diagnostic ) else - 'YcmWarningProperty' ) + 'YcmWarningProperty' if _DiagnosticIsWarning( diagnostic ) else + 'YcmInformationProperty' if _DiagnosticIsInformation( diagnostic ) + else 'YcmHintProperty' ) if vimsupport.VimIsNeovim(): name = name.replace( 'Property', 'Section' ) diff --git a/python/ycm/tests/diagnostic_interface_test.py b/python/ycm/tests/diagnostic_interface_test.py index f3f3b6487f..f5798afe24 100644 --- a/python/ycm/tests/diagnostic_interface_test.py +++ b/python/ycm/tests/diagnostic_interface_test.py @@ -25,9 +25,10 @@ MockVimModule() -def SimpleDiagnosticToJson( start_line, start_col, end_line, end_col ): +def SimpleDiagnosticToJson( start_line, start_col, end_line, end_col, + kind = "ERROR" ): return { - 'kind': 'ERROR', + 'kind': kind, 'location': { 'line_num': start_line, 'column_num': start_col }, 'location_extent': { 'start': { @@ -94,11 +95,12 @@ def SimpleDiagnosticToJsonWithInvalidLineNum( start_line, start_col, } -def YcmTextPropertyTupleMatcher( start_line, start_col, end_line, end_col ): +def YcmTextPropertyTupleMatcher( start_line, start_col, end_line, end_col, + highlight_group = 'YcmErrorProperty' ): return has_item( contains_exactly( start_line, start_col, - 'YcmErrorProperty', + highlight_group, has_entries( { 'end_col': end_col, 'end_lnum': end_line } ) ) ) @@ -111,11 +113,23 @@ def test_ConvertDiagnosticToTextProperties( self ): [ 'Highlight this error please' ], YcmTextPropertyTupleMatcher( 1, 16, 1, 23 ) ], - # Error at the end of the line + # Warning at the end of the line [ - SimpleDiagnosticToJson( 1, 16, 1, 21 ), + SimpleDiagnosticToJson( 1, 16, 1, 21, 'WARNING' ), [ 'Highlight this warning' ], - YcmTextPropertyTupleMatcher( 1, 16, 1, 21 ) + YcmTextPropertyTupleMatcher( 1, 16, 1, 21, 'YcmWarningProperty' ) + ], + # Info at the start of the line + [ + SimpleDiagnosticToJson( 1, 1, 1, 5, 'INFORMATION' ), + [ 'Highlight this information' ], + YcmTextPropertyTupleMatcher( 1, 1, 1, 5, 'YcmInformationProperty' ) + ], + # Hint at the start of the line + [ + SimpleDiagnosticToJson( 1, 5, 1, 5, 'HINT' ), + [ 'Highlight this hint' ], + YcmTextPropertyTupleMatcher( 1, 5, 1, 5, 'YcmHintProperty' ) ], [ SimpleDiagnosticToJson( 1, 16, 1, 19 ), diff --git a/python/ycm/vimsupport.py b/python/ycm/vimsupport.py index 2a29b1ede1..561465ac44 100644 --- a/python/ycm/vimsupport.py +++ b/python/ycm/vimsupport.py @@ -302,8 +302,12 @@ def GetTextPropertyForDiag( buffer_number, line_number, diag ): column = 1 if diag[ 'kind' ] == 'ERROR': property_name = 'YcmErrorProperty' - else: + elif diag[ 'kind' ] == 'WARNING': property_name = 'YcmWarningProperty' + elif diag[ 'kind' ] == 'INFORMATION': + property_name = 'YcmInformationProperty' + else: + property_name = 'YcmHintProperty' vim_props = vim.eval( f'prop_list( { line_number }, ' f'{{ "bufnr": { buffer_number }, ' f'"types": [ "{ property_name }" ] }} )' ) @@ -327,7 +331,9 @@ def GetTextProperties( buffer_number ): f'{{ "bufnr": { buffer_number }, ' '"end_lnum": -1, ' '"types": [ "YcmErrorProperty", ' - '"YcmWarningProperty" ] } )' ) ] + '"YcmWarningProperty", ' + '"YcmInformationProperty", ' + '"YcmHintProperty" ] } )' ) ] else: ext_marks = vim.eval( f'nvim_buf_get_extmarks( { buffer_number }, ' @@ -566,7 +572,8 @@ def ConvertDiagnosticToQfFormat( diagnostic ): 'lnum' : line_num, 'col' : location[ 'column_num' ], 'text' : text, - 'type' : diagnostic[ 'kind' ][ 0 ], + 'type' : "n" if diagnostic[ 'kind' ] == "HINT" + else diagnostic[ 'kind' ][ 0 ], 'valid' : 1 } diff --git a/test/diagnostics.test.vim b/test/diagnostics.test.vim index f8f82d48c1..80ba2dfdc2 100644 --- a/test/diagnostics.test.vim +++ b/test/diagnostics.test.vim @@ -104,6 +104,8 @@ function! Test_Disable_Diagnostics_Update_In_insert_Mode() \ 1, { 'end_lnum': -1, \ 'types': [ 'YcmVirtDiagWarning', \ 'YcmVirtDiagError', + \ 'YcmVirtDiagInformation', + \ 'YcmVirtDiagHint', \ 'YcmVirtDiagPadding' ] } ) ) ) } ) endfunction