def ExtraConfStore_ModuleForSourceFile_WinVarEnv_test( app ): filename = PathToTestFile( 'extra_conf', 'project', 'some_file' ) module = extra_conf_store.ModuleForSourceFile( filename ) assert_that( inspect.ismodule( module ) ) assert_that( inspect.getfile( module ), equal_to( PROJECT_EXTRA_CONF ) ) assert_that( module, has_property( 'is_global_ycm_extra_conf' ) ) assert_that( module.is_global_ycm_extra_conf, equal_to( False ) )
def ExtraConfStore_ModuleForSourceFile_GlobalExtraConf_WinEnvVar_test( app ): filename = PathToTestFile( 'extra_conf', 'some_file' ) module = extra_conf_store.ModuleForSourceFile( filename ) assert_that( inspect.ismodule( module ) ) assert_that( inspect.getfile( module ), equal_to( GLOBAL_EXTRA_CONF ) ) assert_that( module, has_property( 'is_global_ycm_extra_conf' ) ) assert_that( module.is_global_ycm_extra_conf, equal_to( True ) )
def ModuleForSourceFile_GlobalExtraConf_test(self): filename = PathToTestFile('extra_conf', 'some_file') extra_conf_file = PathToTestFile('extra_conf', 'global_extra_conf.py') with UserOption('global_ycm_extra_conf', extra_conf_file): module = extra_conf_store.ModuleForSourceFile(filename) assert_that(inspect.ismodule(module)) assert_that(inspect.getfile(module), equal_to(extra_conf_file))
def _LocationForGoTo(self, goto_function, request_data, reparse=True): flags, filename = self._FlagsForRequest(request_data) if not flags: raise ValueError(NO_COMPILE_FLAGS_MESSAGE) if self._completer.UpdatingTranslationUnit(filename): raise RuntimeError(PARSING_FILE_MESSAGE) files = self.GetUnsavedFilesVector(request_data) line = request_data['line_num'] column = request_data['column_num'] if goto_function == 'GetDefinitionOrDeclarationLocation': module = extra_conf_store.ModuleForSourceFile(filename) if module: project_name = getattr(module, 'PROJECT_NAME', '') else: project_name = '' return getattr(self._completer, goto_function)(project_name, filename, request_data['filepath'], line, column, files, flags, True) else: return getattr(self._completer, goto_function)(filename, request_data['filepath'], line, column, files, flags, reparse)
def AdditionalFormattingOptions(self, request_data): module = extra_conf_store.ModuleForSourceFile(request_data['filepath']) try: settings = self.GetSettings(module, request_data) return settings.get('formatting_options', {}) except AttributeError: return {}
def _GetReferences(self, request_data): flags, filename = self._FlagsForRequest(request_data) if not flags: raise ValueError(NO_COMPILE_FLAGS_MESSAGE) if self._completer.UpdatingTranslationUnit(filename): raise RuntimeError(PARSING_FILE_MESSAGE) files = self.GetUnsavedFilesVector(request_data) line = request_data['line_num'] column = request_data['column_num'] module = extra_conf_store.ModuleForSourceFile(filename) if module: project_name = getattr(module, 'PROJECT_NAME', '') else: project_name = '' locations = getattr(self._completer, "GetReferenceLocations")(project_name, filename, request_data['filepath'], line, column, files, flags, True) # don't raise an error if no references: - leave that to the client to respond # in a nice way return responses.BuildReferenceResponse(locations)
def FlagsForFile(self, filename, add_extra_clang_flags=True, client_data=None): """Returns a tuple describing the compiler invocation required to parse the file |filename|. The tuple contains 2 entries: 1. A list of the compiler flags to use, 2. The name of the translation unit to parse. Note that the second argument might not be the same as the |filename| argument to this method in the event that the extra conf file overrides the translation unit, e.g. in the case of a "unity" build.""" # The try-catch here is to avoid a synchronisation primitive. This method # may be called from multiple threads, and python gives us # 1-python-statement synchronisation for "free" (via the GIL) try: return self.flags_for_file[filename] except KeyError: pass module = extra_conf_store.ModuleForSourceFile(filename) try: results = self._GetFlagsFromExtraConfOrDatabase( module, filename, client_data) except NoCompilationDatabase: if not self.no_extra_conf_file_warning_posted: self.no_extra_conf_file_warning_posted = True raise NoExtraConfDetected return [], filename if not results or not results.get('flags_ready', True): return [], filename return self._ParseFlagsFromExtraConfOrDatabase(filename, results, add_extra_clang_flags)
def _GetFlagsFromExtraConfOrDatabase(self, filename, client_data): # Load the flags from the extra conf file if one is found and is not global. module = extra_conf_store.ModuleForSourceFile(filename) if module and not extra_conf_store.IsGlobalExtraConfModule(module): try: return _CallExtraConfFlagsForFile(module, filename, client_data) except IgnoreExtraConf: pass # Load the flags from the compilation database if any. database = self.LoadCompilationDatabase(filename) if database: return self._GetFlagsFromCompilationDatabase(database, filename) # Load the flags from the global extra conf if set. if module: try: return _CallExtraConfFlagsForFile(module, filename, client_data) except IgnoreExtraConf: pass # No compilation database and no extra conf found. Warn the user if not # already warned. if not self.no_extra_conf_file_warning_posted: self.no_extra_conf_file_warning_posted = True raise NoExtraConfDetected return EMPTY_FLAGS
def FlagsForFile( self, filename, add_extra_clang_flags = True, client_data = None ): try: return self.flags_for_file[ filename ] except KeyError: module = extra_conf_store.ModuleForSourceFile( filename ) if not module: if not self.no_extra_conf_file_warning_posted: self.no_extra_conf_file_warning_posted = True raise NoExtraConfDetected return None results = _CallExtraConfFlagsForFile( module, filename, client_data ) if not results or not results.get( 'flags_ready', True ): return None flags = list( results[ 'flags' ] ) if not flags: return None if add_extra_clang_flags: flags += self.extra_clang_flags sanitized_flags = PrepareFlagsForClang( flags, filename ) if results[ 'do_cache' ]: self.flags_for_file[ filename ] = sanitized_flags return sanitized_flags
def ExtraConfStore_ModuleForSourceFile_SupportSymlink_test(app): with TemporarySymlink(PathToTestFile('extra_conf', 'project'), PathToTestFile('extra_conf', 'symlink')): filename = PathToTestFile('extra_conf', 'project', 'some_file') module = extra_conf_store.ModuleForSourceFile(filename) assert_that(inspect.ismodule(module)) assert_that(inspect.getfile(module), equal_to(PROJECT_EXTRA_CONF))
def ModuleForSourceFile_NoConfirmation_test(self): filename = PathToTestFile('extra_conf', 'project', 'some_file') extra_conf_file = PathToTestFile('extra_conf', 'project', '.ycm_extra_conf.py') with UserOption('confirm_extra_conf', 0): module = extra_conf_store.ModuleForSourceFile(filename) assert_that(inspect.ismodule(module)) assert_that(inspect.getfile(module), equal_to(extra_conf_file))
def ModuleForSourceFile_Whitelisted_test(self): filename = PathToTestFile('extra_conf', 'project', 'some_file') extra_conf_file = PathToTestFile('extra_conf', 'project', '.ycm_extra_conf.py') with UserOption('extra_conf_globlist', [extra_conf_file]): module = extra_conf_store.ModuleForSourceFile(filename) assert_that(inspect.ismodule(module)) assert_that(inspect.getfile(module), equal_to(extra_conf_file))
def test_ExtraConfStore_ModuleForSourceFile_NoConfirmation(self, app): filename = PathToTestFile('extra_conf', 'project', 'some_file') module = extra_conf_store.ModuleForSourceFile(filename) assert_that(inspect.ismodule(module)) assert_that(inspect.getfile(module), equal_to(PROJECT_EXTRA_CONF)) assert_that(module, has_property('is_global_ycm_extra_conf')) assert_that(module.is_global_ycm_extra_conf, equal_to(False)) assert_that(extra_conf_store.IsGlobalExtraConfModule(module), equal_to(False))
def FindSolutionPath(filepath): """ Try to find suitable solution file given a source file path using all available information sources """ # try to load ycm_extra_conf # if it needs to be verified, abort here and try again later module = extra_conf_store.ModuleForSourceFile(filepath) path_to_solutionfile = PollModule(module, filepath) if not path_to_solutionfile: # ycm_extra_conf not available or did not provide a solution file path_to_solutionfile = GuessFile(filepath) return path_to_solutionfile
def _SettingsForRequest(self, request_data): filepath = request_data['filepath'] client_data = request_data['extra_conf_data'] try: return self._settings_for_file[filepath, client_data] except KeyError: pass module = extra_conf_store.ModuleForSourceFile(filepath) settings = self._GetSettings(module, client_data) self._settings_for_file[filepath, client_data] = settings return settings
def _SendFlagsFromExtraConf(self, request_data): """Reads the flags from the extra conf of the given request and sends them to Clangd as an entry of a compilation database using the 'compilationDatabaseChanges' configuration.""" filepath = request_data['filepath'] with self._server_info_mutex: # Replicate the logic from flags.py _GetFlagsFromCompilationDatabase: # - if there's a local extra conf, use it # - otherwise if there's no database, try and use a global extra conf module = extra_conf_store.ModuleForSourceFile(filepath) if not module: # No extra conf and no global extra conf. Just let clangd handle it. return if (extra_conf_store.IsGlobalExtraConfModule(module) and CompilationDatabaseExists(filepath)): # No local extra conf, database exists: use database (i.e. clangd) return # Use our module (either local extra conf or global extra conf when no # database is found) settings = self.GetSettings(module, request_data) if 'flags' not in settings: # No flags returned. Let Clangd find the flags. return if (settings.get('do_cache', True) and filepath in self._compilation_commands): # Flags for this file have already been sent to Clangd. return flags = BuildCompilationCommand(settings['flags'], filepath) self.GetConnection().SendNotification( lsp.DidChangeConfiguration({ 'compilationDatabaseChanges': { filepath: { 'compilationCommand': flags, 'workingDirectory': settings.get('include_paths_relative_to_dir', self._project_directory) } } })) self._compilation_commands[filepath] = flags
def _GetSysPath(self, request_data, environment): settings = {'sys_path': []} settings.update(self._SettingsForRequest(request_data)) settings['interpreter_path'] = environment.executable settings['sys_path'].extend(environment.get_sys_path()) filepath = request_data['filepath'] module = extra_conf_store.ModuleForSourceFile(filepath) # We don't warn the user if no extra conf file is found. if module: if hasattr(module, 'PythonSysPath'): return module.PythonSysPath(**settings) LOGGER.debug('No PythonSysPath function defined in %s', module.__file__) return settings['sys_path']
def _GetJediProject( self, request_data, environment ): settings = { 'sys_path': [] } settings.update( self._SettingsForRequest( request_data ) ) settings[ 'interpreter_path' ] = environment.executable settings[ 'sys_path' ].extend( environment.get_sys_path() ) filepath = request_data[ 'filepath' ] module = extra_conf_store.ModuleForSourceFile( filepath ) # We don't warn the user if no extra conf file is found. if module: if hasattr( module, 'PythonSysPath' ): settings[ 'sys_path' ] = module.PythonSysPath( **settings ) LOGGER.debug( 'No PythonSysPath function defined in %s', module.__file__ ) if not settings.get( 'project_directory' ): module = extra_conf_store.ModuleForSourceFile( filepath ) if module: settings[ 'project_directory' ] = os.path.dirname( module.__file__ ) else: settings[ 'project_directory' ] = os.path.dirname( filepath ) return jedi.Project( settings[ 'project_directory' ], sys_path = settings[ 'sys_path' ], environment_path = settings[ 'interpreter_path' ] )
def ParentForFile(self, filename): """Get the file name in which filename was included. This is for code completion case like : clang --code-completion-at a.c:1:2 b.c This additional cache will consume extra memory depends on the number of souce file. """ try: return self.parent_for_file[filename] except KeyError: module = extra_conf_store.ModuleForSourceFile(filename) if not module: if not self.no_extra_conf_file_warning_posted: self.no_extra_conf_file_warning_posted = True raise NoExtraConfDetected return None result = _CallExtraConfParentForFile(module, filename) self.parent_for_file[filename] = result return result
def FlagsForFile( self, filename, add_extra_clang_flags = True, client_data = None ): # The try-catch here is to avoid a synchronisation primitive. This method # may be called from multiple threads, and python gives us # 1-python-statement synchronisation for "free" (via the GIL) try: return self.flags_for_file[ filename ] except KeyError: pass module = extra_conf_store.ModuleForSourceFile( filename ) try: results = self._GetFlagsFromExtraConfOrDatabase( module, filename, client_data ) except NoCompilationDatabase: if not self.no_extra_conf_file_warning_posted: self.no_extra_conf_file_warning_posted = True raise NoExtraConfDetected return [] if not results or not results.get( 'flags_ready', True ): return [] flags = _ExtractFlagsList( results ) if not flags: return [] if add_extra_clang_flags: flags += self.extra_clang_flags flags = _AddMacIncludePaths( flags ) sanitized_flags = PrepareFlagsForClang( flags, filename, add_extra_clang_flags, _ShouldAllowWinStyleFlags( flags ) ) if results.get( 'do_cache', True ): self.flags_for_file[ filename ] = sanitized_flags return sanitized_flags
def ExtraConfStore_ModuleForSourceFile_Blacklisted_test(app): filename = PathToTestFile('extra_conf', 'project', 'some_file') assert_that(extra_conf_store.ModuleForSourceFile(filename), none())
def ModuleForSourceFile_Blacklisted_test(self): filename = PathToTestFile('extra_conf', 'project', 'some_file') extra_conf_file = PathToTestFile('extra_conf', 'project', '.ycm_extra_conf.py') with UserOption('extra_conf_globlist', ['!' + extra_conf_file]): assert_that(extra_conf_store.ModuleForSourceFile(filename), none())
def ExtraConfStore_ModuleForSourceFile_GlobalExtraConf_UnixEnvVar_test(app): filename = PathToTestFile('extra_conf', 'some_file') module = extra_conf_store.ModuleForSourceFile(filename) assert_that(inspect.ismodule(module)) assert_that(inspect.getfile(module), equal_to(GLOBAL_EXTRA_CONF))
def ExtraConfStore_ModuleForSourceFile_UnixVarEnv_test(app): filename = PathToTestFile('extra_conf', 'project', 'some_file') module = extra_conf_store.ModuleForSourceFile(filename) assert_that(inspect.ismodule(module)) assert_that(inspect.getfile(module), equal_to(PROJECT_EXTRA_CONF))