浏览代码

Implement new debugging information API

micbou 8 年之前
父节点
当前提交
18aba7a582

+ 70 - 4
python/ycm/client/debug_info_request.py

@@ -1,4 +1,4 @@
-# Copyright (C) 2016 YouCompleteMe contributors
+# Copyright (C) 2016-2017 YouCompleteMe contributors
 #
 # This file is part of YouCompleteMe.
 #
@@ -40,9 +40,75 @@ class DebugInfoRequest( BaseRequest ):
 
 
   def Response( self ):
-    if not self._response:
-      return 'Server errored, no debug info from server'
-    return self._response
+    return _FormatDebugInfoResponse( self._response )
+
+
+def _FormatDebugInfoResponse( response ):
+  if not response:
+    return 'Server errored, no debug info from server\n'
+  message = _FormatYcmdDebugInfo( response )
+  completer = response[ 'completer' ]
+  if completer:
+    message += _FormatCompleterDebugInfo( completer )
+  return message
+
+
+def _FormatYcmdDebugInfo( ycmd ):
+  python = ycmd[ 'python' ]
+  clang = ycmd[ 'clang' ]
+  message = ( 'Server Python interpreter: {0}\n'
+              'Server Python version: {1}\n'
+              'Server has Clang support compiled in: {2}\n'
+              'Clang version: {3}\n'.format( python[ 'executable' ],
+                                             python[ 'version' ],
+                                             clang[ 'has_support' ],
+                                             clang[ 'version' ] ) )
+  extra_conf = ycmd[ 'extra_conf' ]
+  extra_conf_path = extra_conf[ 'path' ]
+  if not extra_conf_path:
+    message += 'No extra configuration file found\n'
+  elif not extra_conf[ 'is_loaded' ]:
+    message += ( 'Extra configuration file found but not loaded\n'
+                 'Extra configuration path: {0}\n'.format( extra_conf_path ) )
+  else:
+    message += ( 'Extra configuration file found and loaded\n'
+                 'Extra configuration path: {0}\n'.format( extra_conf_path ) )
+  return message
+
+
+def _FormatCompleterDebugInfo( completer ):
+  message = '{0} completer debug information:\n'.format( completer[ 'name' ] )
+  for server in completer[ 'servers' ]:
+    name = server[ 'name' ]
+    if server[ 'is_running' ]:
+      address = server[ 'address' ]
+      port = server[ 'port' ]
+      if address and port:
+        message += '  {0} running at: http://{1}:{2}\n'.format( name,
+                                                                address,
+                                                                port )
+      else:
+        message += '  {0} running\n'.format( name )
+      message += '  {0} process ID: {1}\n'.format( name, server[ 'pid' ] )
+    else:
+      message += '  {0} not running\n'.format( name )
+    message += '  {0} executable: {1}\n'.format( name, server[ 'executable'] )
+    logfiles = server[ 'logfiles' ]
+    if logfiles:
+      message += '  {0} logfiles:\n'.format( name )
+      for logfile in logfiles:
+        message += '    {0}\n'.format( logfile )
+    else:
+      message += '  No logfiles available\n'
+    if 'extras' in server:
+      for extra in server[ 'extras' ]:
+        message += '  {0} {1}: {2}\n'.format( name,
+                                              extra[ 'key' ],
+                                              extra[ 'value' ] )
+  for item in completer[ 'items' ]:
+    message += '  {0}: {1}\n'.format( item[ 'key' ].capitalize(),
+                                      item[ 'value' ] )
+  return message
 
 
 def SendDebugInfoRequest():

+ 184 - 0
python/ycm/tests/client/debug_info_request_test.py

@@ -0,0 +1,184 @@
+# Copyright (C) 2017 YouCompleteMe Contributors
+#
+# 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/>.
+
+from __future__ import unicode_literals
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from future import standard_library
+standard_library.install_aliases()
+from builtins import *  # noqa
+
+from copy import deepcopy
+from hamcrest import assert_that, contains_string, equal_to
+
+from ycm.client.debug_info_request import _FormatDebugInfoResponse
+
+
+GENERIC_RESPONSE = {
+  'clang': {
+    'has_support': True,
+    'version': 'Clang version'
+  },
+  'completer': {
+    'items': [
+      {
+        'key': 'key',
+        'value': 'value'
+      }
+    ],
+    'name': 'Completer name',
+    'servers': [
+      {
+        'address': '127.0.0.1',
+        'executable': '/path/to/executable',
+        'extras': [
+          {
+            'key': 'key',
+            'value': 'value'
+          }
+        ],
+        'is_running': True,
+        'logfiles': [
+          '/path/to/stdout/logfile',
+          '/path/to/stderr/logfile'
+        ],
+        'name': 'Server name',
+        'pid': 12345,
+        'port': 1234
+      }
+    ]
+  },
+  'extra_conf': {
+    'is_loaded': False,
+    'path': '/path/to/extra/conf'
+  },
+  'python': {
+    'executable': '/path/to/python/interpreter',
+    'version': 'Python version'
+  }
+}
+
+
+def FormatDebugInfoResponse_NoResponse_test():
+  assert_that(
+    _FormatDebugInfoResponse( None ),
+    equal_to( 'Server errored, no debug info from server\n' )
+  )
+
+
+def FormatDebugInfoResponse_NoExtraConf_test():
+  response = deepcopy( GENERIC_RESPONSE )
+  response[ 'extra_conf' ].update( {
+    'is_loaded': False,
+    'path': None
+  } )
+  assert_that(
+    _FormatDebugInfoResponse( response ),
+    contains_string(
+      'No extra configuration file found\n'
+    )
+  )
+
+
+def FormatDebugInfoResponse_ExtraConfFoundButNotLoaded_test():
+  response = deepcopy( GENERIC_RESPONSE )
+  response[ 'extra_conf' ].update( {
+    'is_loaded': False,
+    'path': '/path/to/extra/conf'
+  } )
+  assert_that(
+    _FormatDebugInfoResponse( response ),
+    contains_string(
+      'Extra configuration file found but not loaded\n'
+      'Extra configuration path: /path/to/extra/conf\n'
+    )
+  )
+
+
+def FormatDebugInfoResponse_ExtraConfFoundAndLoaded_test():
+  response = deepcopy( GENERIC_RESPONSE )
+  response[ 'extra_conf' ].update( {
+    'is_loaded': True,
+    'path': '/path/to/extra/conf'
+  } )
+  assert_that(
+    _FormatDebugInfoResponse( response ),
+    contains_string(
+      'Extra configuration file found and loaded\n'
+      'Extra configuration path: /path/to/extra/conf\n'
+    )
+  )
+
+
+def FormatDebugInfoResponse_Completer_ServerRunningWithHost_test():
+  response = deepcopy( GENERIC_RESPONSE )
+  assert_that(
+    _FormatDebugInfoResponse( response ),
+    contains_string(
+      'Completer name completer debug information:\n'
+      '  Server name running at: http://127.0.0.1:1234\n'
+      '  Server name process ID: 12345\n'
+      '  Server name executable: /path/to/executable\n'
+      '  Server name logfiles:\n'
+      '    /path/to/stdout/logfile\n'
+      '    /path/to/stderr/logfile\n'
+      '  Server name key: value\n'
+      '  Key: value\n'
+    )
+  )
+
+
+def FormatDebugInfoResponse_Completer_ServerRunningWithoutHost_test():
+  response = deepcopy( GENERIC_RESPONSE )
+  response[ 'completer' ][ 'servers' ][ 0 ].update( {
+    'address': None,
+    'port': None
+  } )
+  assert_that(
+    _FormatDebugInfoResponse( response ),
+    contains_string(
+      'Completer name completer debug information:\n'
+      '  Server name running\n'
+      '  Server name process ID: 12345\n'
+      '  Server name executable: /path/to/executable\n'
+      '  Server name logfiles:\n'
+      '    /path/to/stdout/logfile\n'
+      '    /path/to/stderr/logfile\n'
+      '  Server name key: value\n'
+      '  Key: value\n'
+    )
+  )
+
+
+def FormatDebugInfoResponse_Completer_ServerNotRunningWithNoLogfiles_test():
+  response = deepcopy( GENERIC_RESPONSE )
+  response[ 'completer' ][ 'servers' ][ 0 ].update( {
+    'is_running': False,
+    'logfiles': []
+  } )
+  assert_that(
+    _FormatDebugInfoResponse( response ),
+    contains_string(
+      'Completer name completer debug information:\n'
+      '  Server name not running\n'
+      '  Server name executable: /path/to/executable\n'
+      '  No logfiles available\n'
+      '  Server name key: value\n'
+      '  Key: value\n'
+    )
+  )

+ 6 - 4
python/ycm/tests/youcompleteme_test.py

@@ -1,4 +1,4 @@
-# Copyright (C) 2016 YouCompleteMe contributors
+# Copyright (C) 2016-2017 YouCompleteMe contributors
 #
 # This file is part of YouCompleteMe.
 #
@@ -23,7 +23,6 @@ from future import standard_library
 standard_library.install_aliases()
 from builtins import *  # noqa
 
-from ycm.tests import StopServer
 from ycm.tests.test_utils import ( ExtendedMock, MockVimBuffers, MockVimModule,
                                    VimBuffer )
 MockVimModule()
@@ -34,7 +33,7 @@ from hamcrest import ( assert_that, contains, empty, is_in, is_not, has_length,
                        matches_regexp )
 from mock import call, MagicMock, patch
 
-from ycm.tests import YouCompleteMeInstance
+from ycm.tests import StopServer, YouCompleteMeInstance
 from ycmd.responses import ServerError
 
 
@@ -149,8 +148,11 @@ def YouCompleteMe_DebugInfo_ServerRunning_test( ycm ):
       ycm.DebugInfo(),
       matches_regexp(
         'Client logfile: .+\n'
+        'Server Python interpreter: .+\n'
+        'Server Python version: .+\n'
         'Server has Clang support compiled in: (True|False)\n'
-        '(Clang version: .+\n)?'
+        'Clang version: .+\n'
+        'No extra configuration file found\n'
         'Server running at: .+\n'
         'Server process ID: \d+\n'
         'Server logfiles:\n'

+ 7 - 6
python/ycm/youcompleteme.py

@@ -1,5 +1,5 @@
 # Copyright (C) 2011-2012 Google Inc.
-#               2016      YouCompleteMe contributors
+#               2016-2017 YouCompleteMe contributors
 #
 # This file is part of YouCompleteMe.
 #
@@ -650,11 +650,12 @@ class YouCompleteMe( object ):
     if self.IsServerAlive():
       debug_info += SendDebugInfoRequest()
     else:
-      debug_info += 'Server crashed, no debug info from server'
-    debug_info += '\nServer running at: {0}\n'.format(
-        BaseRequest.server_location )
-    debug_info += 'Server process ID: {0}\n'.format( self._server_popen.pid )
-    if self._server_stderr or self._server_stdout:
+      debug_info += 'Server crashed, no debug info from server\n'
+    debug_info += (
+      'Server running at: {0}\n'
+      'Server process ID: {1}\n'.format( BaseRequest.server_location,
+                                         self._server_popen.pid ) )
+    if self._server_stdout and self._server_stderr:
       debug_info += ( 'Server logfiles:\n'
                       '  {0}\n'
                       '  {1}'.format( self._server_stdout,

+ 1 - 1
third_party/ycmd

@@ -1 +1 @@
-Subproject commit d19f9c5e8e5ca47a9784a78a3aa39a49f8c3e7c6
+Subproject commit ec4f335676351eb89e554d0c0b45f01e22243e1a