def _Check_FileReadyToParse_Diagnostic_Warning(ycm):
    # Tests Vim sign placement/unplacement and error/warning count python API
    # when one warning is returned.
    # Should be called after _Check_FileReadyToParse_Diagnostic_Error
    def DiagnosticResponse(*args):
        start = Location(2, 2, 'TEST_BUFFER')
        end = Location(2, 4, 'TEST_BUFFER')
        extent = Range(start, end)
        diagnostic = Diagnostic([], start, extent, 'cast', 'WARNING')
        return [BuildDiagnosticData(diagnostic)]

    with MockArbitraryBuffer('cpp'):
        with MockEventNotification(DiagnosticResponse):
            ycm.OnFileReadyToParse()
            ok_(ycm.FileParseRequestReady())
            ycm.HandleFileParseRequest()
            assert_that(
                test_utils.VIM_SIGNS,
                contains(
                    VimSign(SIGN_BUFFER_ID_INITIAL_VALUE + 1, 2, 'YcmWarning',
                            1)))
            eq_(ycm.GetErrorCount(), 0)
            eq_(ycm.GetWarningCount(), 1)

            # Consequent calls to HandleFileParseRequest shouldn't mess with
            # existing diagnostics, when there is no new parse request.
            ycm.HandleFileParseRequest()
            assert_that(
                test_utils.VIM_SIGNS,
                contains(
                    VimSign(SIGN_BUFFER_ID_INITIAL_VALUE + 1, 2, 'YcmWarning',
                            1)))
            eq_(ycm.GetErrorCount(), 0)
            eq_(ycm.GetWarningCount(), 1)
def _Check_FileReadyToParse_Diagnostic_Error( ycm ):
  # Tests Vim sign placement and error/warning count python API
  # when one error is returned.
  def DiagnosticResponse( *args ):
    start = Location( 1, 2, 'TEST_BUFFER' )
    end = Location( 1, 4, 'TEST_BUFFER' )
    extent = Range( start, end )
    diagnostic = Diagnostic( [], start, extent, 'expected ;', 'ERROR' )
    return [ BuildDiagnosticData( diagnostic ) ]

  with MockArbitraryBuffer( 'cpp' ):
    with MockEventNotification( DiagnosticResponse ):
      ycm.OnFileReadyToParse()
      assert_that( ycm.FileParseRequestReady() )
      ycm.HandleFileParseRequest()
      assert_that(
        test_utils.VIM_SIGNS,
        contains_exactly(
          VimSign( SIGN_BUFFER_ID_INITIAL_VALUE, 1, 'YcmError', 1 )
        )
      )
      assert_that( ycm.GetErrorCount(), equal_to( 1 ) )
      assert_that( ycm.GetWarningCount(), equal_to( 0 ) )

      # Consequent calls to HandleFileParseRequest shouldn't mess with
      # existing diagnostics, when there is no new parse request.
      ycm.HandleFileParseRequest()
      assert_that(
        test_utils.VIM_SIGNS,
        contains_exactly(
          VimSign( SIGN_BUFFER_ID_INITIAL_VALUE, 1, 'YcmError', 1 )
        )
      )
      assert_that( ycm.GetErrorCount(), equal_to( 1 ) )
      assert_that( ycm.GetWarningCount(), equal_to( 0 ) )

      assert_that( not ycm.ShouldResendFileParseRequest() )

      # New identical requests should result in the same diagnostics.
      ycm.OnFileReadyToParse()
      assert_that( ycm.FileParseRequestReady() )
      ycm.HandleFileParseRequest()
      assert_that(
        test_utils.VIM_SIGNS,
        contains_exactly(
          VimSign( SIGN_BUFFER_ID_INITIAL_VALUE, 1, 'YcmError', 1 )
        )
      )
      assert_that( ycm.GetErrorCount(), equal_to( 1 ) )
      assert_that( ycm.GetWarningCount(), equal_to( 0 ) )

      assert_that( not ycm.ShouldResendFileParseRequest() )
def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test(
  ycm, post_vim_message, *args ):

  contents = """int main() {
  int x, y;
  x == y
}"""

  # List of diagnostics returned by ycmd for the above code.
  diagnostics = [ {
    'kind': 'ERROR',
    'text': "expected ';' after expression",
    'location': {
      'filepath': 'buffer',
      'line_num': 3,
      'column_num': 9
    },
    # Looks strange but this is really what ycmd is returning.
    'location_extent': {
      'start': {
        'filepath': '',
        'line_num': 0,
        'column_num': 0,
      },
      'end': {
        'filepath': '',
        'line_num': 0,
        'column_num': 0,
      }
    },
    'ranges': [],
    'fixit_available': True
  }, {
    'kind': 'WARNING',
    'text': 'equality comparison result unused',
    'location': {
      'filepath': 'buffer',
      'line_num': 3,
      'column_num': 7,
    },
    'location_extent': {
      'start': {
        'filepath': 'buffer',
        'line_num': 3,
        'column_num': 5,
      },
      'end': {
        'filepath': 'buffer',
        'line_num': 3,
        'column_num': 7,
      }
    },
    'ranges': [ {
      'start': {
        'filepath': 'buffer',
        'line_num': 3,
        'column_num': 3,
      },
      'end': {
        'filepath': 'buffer',
        'line_num': 3,
        'column_num': 9,
      }
    } ],
    'fixit_available': True
  } ]

  current_buffer = VimBuffer( 'buffer',
                              filetype = 'c',
                              contents = contents.splitlines(),
                              number = 5,
                              window = 2 )

  test_utils.VIM_MATCHES = []
  test_utils.VIM_SIGNS = []

  with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 1 ) ):
    with patch( 'ycm.client.event_notification.EventNotification.Response',
                return_value = diagnostics ):
      ycm.OnFileReadyToParse()
      ycm.HandleFileParseRequest( block = True )

    # The error on the current line is echoed, not the warning.
    post_vim_message.assert_called_once_with(
      "expected ';' after expression (FixIt)",
      truncate = True, warning = False )

    # Error match is added after warning matches.
    assert_that(
      test_utils.VIM_MATCHES,
      contains(
        VimMatch( 'YcmWarningSection', '\%3l\%5c\_.\{-}\%3l\%7c' ),
        VimMatch( 'YcmWarningSection', '\%3l\%3c\_.\{-}\%3l\%9c' ),
        VimMatch( 'YcmErrorSection', '\%3l\%8c' )
      )
    )

    # Only the error sign is placed.
    assert_that(
      test_utils.VIM_SIGNS,
      contains(
        VimSign( SIGN_BUFFER_ID_INITIAL_VALUE, 3, 'YcmError', 5 )
      )
    )

  # The error is not echoed again when moving the cursor along the line.
  with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 2 ) ):
    post_vim_message.reset_mock()
    ycm.OnCursorMoved()
    post_vim_message.assert_not_called()

  # The error is cleared when moving the cursor to another line.
  with MockVimBuffers( [ current_buffer ], current_buffer, ( 2, 2 ) ):
    post_vim_message.reset_mock()
    ycm.OnCursorMoved()
    post_vim_message.assert_called_once_with( "", warning = False )

  # The error is echoed when moving the cursor back.
  with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 2 ) ):
    post_vim_message.reset_mock()
    ycm.OnCursorMoved()
    post_vim_message.assert_called_once_with(
      "expected ';' after expression (FixIt)",
      truncate = True, warning = False )

    with patch( 'ycm.client.event_notification.EventNotification.Response',
                return_value = diagnostics[ 1 : ] ):
      ycm.OnFileReadyToParse()
      ycm.HandleFileParseRequest( block = True )

    assert_that(
      test_utils.VIM_MATCHES,
      contains(
        VimMatch( 'YcmWarningSection', '\%3l\%5c\_.\{-}\%3l\%7c' ),
        VimMatch( 'YcmWarningSection', '\%3l\%3c\_.\{-}\%3l\%9c' )
      )
    )

    assert_that(
      test_utils.VIM_SIGNS,
      contains(
        VimSign( SIGN_BUFFER_ID_INITIAL_VALUE + 1, 3, 'YcmWarning', 5 )
      )
    )