def FindRacerdBinary(user_options): """ Find path to racerd binary This function prefers the 'racerd_binary_path' value as provided in user_options if available. It then falls back to ycmd's racerd build. If that's not found, attempts to use racerd from current path. """ racerd_user_binary = user_options.get('racerd_binary_path') if racerd_user_binary: # The user has explicitly specified a path. if os.path.isfile(racerd_user_binary): return racerd_user_binary LOGGER.warning('User-provided racerd_binary_path does not exist') if os.path.isfile(RACERD_BINARY_RELEASE): return RACERD_BINARY_RELEASE # We want to support using the debug binary for the sake of debugging; also, # building the release version on Travis takes too long. if os.path.isfile(RACERD_BINARY_DEBUG): LOGGER.warning('Using racerd DEBUG binary; performance will suffer!') return RACERD_BINARY_DEBUG return utils.PathToFirstExistingExecutable(['racerd'])
def FindRacerdBinary( user_options ): """ Find path to racerd binary This function prefers the 'racerd_binary_path' value as provided in user_options if available. It then falls back to ycmd's racerd build. If that's not found, attempts to use racerd from current path. """ racerd_user_binary = user_options.get( 'racerd_binary_path' ) if racerd_user_binary: # The user has explicitly specified a path. if os.path.isfile( racerd_user_binary ): return racerd_user_binary LOGGER.warning( 'User-provided racerd_binary_path does not exist' ) if os.path.isfile( RACERD_BINARY_RELEASE ): return RACERD_BINARY_RELEASE # We want to support using the debug binary for the sake of debugging; also, # building the release version on Travis takes too long. if os.path.isfile( RACERD_BINARY_DEBUG ): LOGGER.warning( 'Using racerd DEBUG binary; performance will suffer!' ) return RACERD_BINARY_DEBUG return utils.PathToFirstExistingExecutable( [ 'racerd' ] )
def _StartServer( self, request_data ): with self._server_state_mutex: if self._server_started: return self._server_started = True LOGGER.info( 'Starting Tern server...' ) self._SetServerProjectFileAndWorkingDirectory( request_data ) self._server_port = utils.GetUnusedLocalhostPort() command = [ PATH_TO_NODE, PATH_TO_TERN_BINARY, '--port', str( self._server_port ), '--host', SERVER_HOST, '--persistent', '--no-port-file' ] if LOGGER.isEnabledFor( logging.DEBUG ): command.append( '--verbose' ) LOGGER.debug( 'Starting tern with the following command: %s', command ) self._server_stdout = utils.CreateLogfile( LOGFILE_FORMAT.format( port = self._server_port, std = 'stdout' ) ) self._server_stderr = utils.CreateLogfile( LOGFILE_FORMAT.format( port = self._server_port, std = 'stderr' ) ) # We need to open a pipe to stdin or the Tern server is killed. # See https://github.com/ternjs/tern/issues/740#issuecomment-203979749 # For unknown reasons, this is only needed on Windows and for Python # 3.4+ on other platforms. with utils.OpenForStdHandle( self._server_stdout ) as stdout: with utils.OpenForStdHandle( self._server_stderr ) as stderr: self._server_handle = utils.SafePopen( command, stdin = PIPE, stdout = stdout, stderr = stderr, cwd = self._server_working_dir ) if self._ServerIsRunning(): LOGGER.info( 'Tern Server started with pid %d listening on port %d', self._server_handle.pid, self._server_port ) LOGGER.info( 'Tern Server log files are %s and %s', self._server_stdout, self._server_stderr ) self._do_tern_project_check = True else: LOGGER.warning( 'Tern server did not start successfully' )
def _SetServerProjectFileAndWorkingDirectory(self, request_data): filepath = request_data['filepath'] self._server_project_file, is_project = FindTernProjectFile(filepath) working_dir = request_data.get('working_dir', utils.GetCurrentDirectory()) if not self._server_project_file: LOGGER.warning('No .tern-project file detected: %s', filepath) self._server_working_dir = working_dir else: LOGGER.info('Detected Tern configuration file at: %s', self._server_project_file) self._server_working_dir = (os.path.dirname( self._server_project_file) if is_project else working_dir) LOGGER.info('Tern paths are relative to: %s', self._server_working_dir)
def GetClangdCommand(user_options, third_party_clangd): """Get commands to run clangd. Look through binaries reachable through PATH or pre-built ones. Return None if no binary exists or it is out of date. """ global CLANGD_COMMAND # None stands for we tried to fetch command and failed, therefore it is not # the default. if CLANGD_COMMAND != NOT_CACHED: LOGGER.info('Returning cached clangd: %s', CLANGD_COMMAND) return CLANGD_COMMAND CLANGD_COMMAND = None resource_dir = None installed_clangd = user_options['clangd_binary_path'] if not CheckClangdVersion(installed_clangd): if installed_clangd: LOGGER.warning( 'Clangd at %s is out-of-date, trying to use pre-built ' 'version', installed_clangd) # Try looking for the pre-built binary. if not third_party_clangd: return None installed_clangd = third_party_clangd resource_dir = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', '..', '..', 'clang_includes')) # We have a clangd binary that is executable and up-to-date at this point. CLANGD_COMMAND = [installed_clangd] clangd_args = user_options['clangd_args'] put_resource_dir = False put_limit_results = False put_header_insertion_decorators = False for arg in clangd_args: CLANGD_COMMAND.append(arg) put_resource_dir = put_resource_dir or arg.startswith('-resource-dir') put_limit_results = put_limit_results or arg.startswith( '-limit-results') put_header_insertion_decorators = ( put_header_insertion_decorators or arg.startswith('-header-insertion-decorators')) if not put_header_insertion_decorators: CLANGD_COMMAND.append('-header-insertion-decorators=0') if resource_dir and not put_resource_dir: CLANGD_COMMAND.append('-resource-dir=' + resource_dir) if user_options['clangd_uses_ycmd_caching'] and not put_limit_results: CLANGD_COMMAND.append('-limit-results=500') return CLANGD_COMMAND
def ShouldEnableClangdCompleter(user_options): third_party_clangd = Get3rdPartyClangd() # User disabled clangd explicitly. if user_options['use_clangd'].lower() == 'never': return False # User haven't downloaded clangd and use_clangd is in auto mode. if not third_party_clangd and user_options['use_clangd'].lower() == 'auto': return False clangd_command = GetClangdCommand(user_options, third_party_clangd) if not clangd_command: LOGGER.warning('Not using clangd: unable to find clangd binary') return False LOGGER.info('Using clangd from %s', clangd_command) return True
def GetFileContents( request_data, filename ): """Returns the contents of the absolute path |filename| as a unicode string. If the file contents exist in |request_data| (i.e. it is open and potentially modified/dirty in the user's editor), then it is returned, otherwise the file is read from disk (assuming a UTF-8 encoding) and its contents returned.""" file_data = request_data[ 'file_data' ] if filename in file_data: return ToUnicode( file_data[ filename ][ 'contents' ] ) try: return ToUnicode( ReadFile( filename ) ) except ( OSError, UnicodeError ): LOGGER.warning( 'Error reading file "%s"', filename ) return ''
def _SetServerProjectFileAndWorkingDirectory( self, request_data ): filepath = request_data[ 'filepath' ] self._server_project_file, is_project = FindTernProjectFile( filepath ) working_dir = request_data.get( 'working_dir', utils.GetCurrentDirectory() ) if not self._server_project_file: LOGGER.warning( 'No .tern-project file detected: %s', filepath ) self._server_working_dir = working_dir else: LOGGER.info( 'Detected Tern configuration file at: %s', self._server_project_file ) self._server_working_dir = ( os.path.dirname( self._server_project_file ) if is_project else working_dir ) LOGGER.info( 'Tern paths are relative to: %s', self._server_working_dir )
def ShouldEnableClangdCompleter( user_options ): third_party_clangd = Get3rdPartyClangd() # User disabled clangd explicitly. if user_options[ 'use_clangd' ].lower() == 'never': return False # User haven't downloaded clangd and use_clangd is in auto mode. if not third_party_clangd and user_options[ 'use_clangd' ].lower() == 'auto': return False clangd_command = GetClangdCommand( user_options, third_party_clangd ) if not clangd_command: LOGGER.warning( 'Not using clangd: unable to find clangd binary' ) return False LOGGER.info( 'Using clangd from %s', clangd_command ) return True
def GetClangdCommand( user_options, third_party_clangd ): """Get commands to run clangd. Look through binaries reachable through PATH or pre-built ones. Return None if no binary exists or it is out of date. """ global CLANGD_COMMAND # None stands for we tried to fetch command and failed, therefore it is not # the default. if CLANGD_COMMAND != NOT_CACHED: LOGGER.info( 'Returning cached clangd: %s', CLANGD_COMMAND ) return CLANGD_COMMAND CLANGD_COMMAND = None resource_dir = None installed_clangd = user_options[ 'clangd_binary_path' ] if not CheckClangdVersion( installed_clangd ): if installed_clangd: LOGGER.warning( 'Clangd at %s is out-of-date, trying to use pre-built ' 'version', installed_clangd ) # Try looking for the pre-built binary. if not third_party_clangd: return None installed_clangd = third_party_clangd resource_dir = CLANG_RESOURCE_DIR # We have a clangd binary that is executable and up-to-date at this point. CLANGD_COMMAND = [ installed_clangd ] clangd_args = user_options[ 'clangd_args' ] put_resource_dir = False put_limit_results = False put_header_insertion_decorators = False for arg in clangd_args: CLANGD_COMMAND.append( arg ) put_resource_dir = put_resource_dir or arg.startswith( '-resource-dir' ) put_limit_results = put_limit_results or arg.startswith( '-limit-results' ) put_header_insertion_decorators = ( put_header_insertion_decorators or arg.startswith( '-header-insertion-decorators' ) ) if not put_header_insertion_decorators: CLANGD_COMMAND.append( '-header-insertion-decorators=0' ) if resource_dir and not put_resource_dir: CLANGD_COMMAND.append( '-resource-dir=' + resource_dir ) if user_options[ 'clangd_uses_ycmd_caching' ] and not put_limit_results: CLANGD_COMMAND.append( '-limit-results=500' ) return CLANGD_COMMAND
def ShouldEnableRustCompleter( user_options ): if ( 'rls_binary_path' in user_options and not user_options[ 'rust_toolchain_root' ] ): LOGGER.warning( 'rls_binary_path detected. ' 'Did you mean rust_toolchain_root?' ) if user_options[ 'rust_toolchain_root' ]: # Listen to what the user wanted to use ra = os.path.join( user_options[ 'rust_toolchain_root' ], 'bin', 'rust-analyzer' ) if not utils.FindExecutable( ra ): LOGGER.error( 'Not using Rust completer: no rust-analyzer ' 'executable found at %s', ra ) return False else: return True else: return bool( RA_EXECUTABLE )
def ShouldEnableTernCompleter(): """Returns whether or not the tern completer is 'installed'. That is whether or not the tern submodule has a 'node_modules' directory. This is pretty much the only way we can know if the user added '--js-completer' on install or manually ran 'npm install' in the tern submodule directory.""" if not PATH_TO_NODE: LOGGER.warning( 'Not using Tern completer: unable to find node' ) return False LOGGER.info( 'Using node binary from: %s', PATH_TO_NODE ) installed = os.path.exists( PATH_TO_TERN_BINARY ) if not installed: LOGGER.info( 'Not using Tern completer: not installed at %s', PATH_TO_TERN_BINARY ) return False return True
def ShouldEnableTernCompleter(): """Returns whether or not the tern completer is 'installed'. That is whether or not the tern submodule has a 'node_modules' directory. This is pretty much the only way we can know if the user added '--js-completer' on install or manually ran 'npm install' in the tern submodule directory.""" if not PATH_TO_NODE: LOGGER.warning('Not using Tern completer: unable to find node') return False LOGGER.info('Using node binary from: %s', PATH_TO_NODE) installed = os.path.exists(PATH_TO_TERN_BINARY) if not installed: LOGGER.info('Not using Tern completer: not installed at %s', PATH_TO_TERN_BINARY) return False return True
def __init__( self, user_options ): super( RustCompleter, self ).__init__( user_options ) self._racerd_binary = FindRacerdBinary( user_options ) self._racerd_port = None self._racerd_host = None self._server_state_lock = threading.RLock() self._keep_logfiles = user_options[ 'server_keep_logfiles' ] self._hmac_secret = '' self._rust_source_path = self._GetRustSrcPath() if not self._rust_source_path: LOGGER.warning( 'No path provided for the rustc source. Please set the ' 'rust_src_path option' ) elif not p.isdir( self._rust_source_path ): LOGGER.error( NON_EXISTING_RUST_SOURCES_PATH_MESSAGE ) raise RuntimeError( NON_EXISTING_RUST_SOURCES_PATH_MESSAGE ) if not self._racerd_binary: LOGGER.error( BINARY_NOT_FOUND_MESSAGE ) raise RuntimeError( BINARY_NOT_FOUND_MESSAGE ) self._StartServer()
def __init__(self, user_options): super(RustCompleter, self).__init__(user_options) self._racerd_binary = FindRacerdBinary(user_options) self._racerd_port = None self._racerd_host = None self._server_state_lock = threading.RLock() self._keep_logfiles = user_options['server_keep_logfiles'] self._hmac_secret = '' self._rust_source_path = self._GetRustSrcPath() if not self._rust_source_path: LOGGER.warning( 'No path provided for the rustc source. Please set the ' 'rust_src_path option') elif not p.isdir(self._rust_source_path): LOGGER.error(NON_EXISTING_RUST_SOURCES_PATH_MESSAGE) raise RuntimeError(NON_EXISTING_RUST_SOURCES_PATH_MESSAGE) if not self._racerd_binary: LOGGER.error(BINARY_NOT_FOUND_MESSAGE) raise RuntimeError(BINARY_NOT_FOUND_MESSAGE) self._StartServer()
def ShouldEnableJavaCompleter(): LOGGER.info('Looking for jdt.ls') if not PATH_TO_JAVA: LOGGER.warning("Not enabling java completion: Couldn't find java") return False if not os.path.exists(LANGUAGE_SERVER_HOME): LOGGER.warning('Not using java completion: jdt.ls is not installed') return False if not _PathToLauncherJar(): LOGGER.warning('Not using java completion: jdt.ls is not built') return False return True
def ShouldEnableJavaCompleter(): LOGGER.info( 'Looking for jdt.ls' ) if not PATH_TO_JAVA: LOGGER.warning( "Not enabling java completion: Couldn't find java" ) return False if not os.path.exists( LANGUAGE_SERVER_HOME ): LOGGER.warning( 'Not using java completion: jdt.ls is not installed' ) return False if not _PathToLauncherJar(): LOGGER.warning( 'Not using java completion: jdt.ls is not built' ) return False return True
def ShouldEnableJavaCompleter(user_options): LOGGER.info('Looking for jdt.ls') global PATH_TO_JAVA PATH_TO_JAVA = utils.FindExecutableWithFallback( user_options['java_binary_path'], utils.FindExecutable('java')) if not PATH_TO_JAVA: LOGGER.warning("Not enabling java completion: Couldn't find java 11") return False if not os.path.exists(LANGUAGE_SERVER_HOME): LOGGER.warning('Not using java completion: jdt.ls is not installed') return False if not _PathToLauncherJar(): LOGGER.warning('Not using java completion: jdt.ls is not built') return False return True