def change_workspace_folders( self, added_folders: List[str], removed_folders: List[str] ) -> None: from robocorp_ls_core import uris import os.path added_folders_uri_name = [ {"uri": uris.from_fs_path(s), "name": os.path.basename(s)} for s in added_folders ] removed_folders_uri_name = [ {"uri": uris.from_fs_path(s), "name": os.path.basename(s)} for s in removed_folders ] self.write( { "jsonrpc": "2.0", "method": "workspace/didChangeWorkspaceFolders", "params": { "event": { "added": added_folders_uri_name, "removed": removed_folders_uri_name, } }, } )
def test_shadowing_libraries(language_server_io: ILanguageServerClient, workspace_dir): from robocorp_ls_core import uris from pathlib import Path from robocorp_ls_core.unittest_tools.fixtures import TIMEOUT language_server = language_server_io os.makedirs(workspace_dir, exist_ok=True) builtin_lib = Path(workspace_dir) / "builtin.py" case1_lib = Path(workspace_dir) / "case1.robot" case2_lib = Path(workspace_dir) / "case2.robot" builtin_lib.write_text(""" def something(): pass """) case1_lib.write_text(""" *** Settings *** Library builtin *** Test Cases *** User can call builtin Something """) case2_lib.write_text(""" *** Test Cases *** User can call builtin 2 Log Task executed """) language_server.initialize(workspace_dir, process_id=os.getpid()) uri1 = uris.from_fs_path(str(case1_lib)) uri2 = uris.from_fs_path(str(case2_lib)) for _i in range(2): message_matcher = language_server.obtain_pattern_message_matcher( {"method": "textDocument/publishDiagnostics"}) language_server.open_doc(uri1, 1, text=None) assert message_matcher.event.wait(TIMEOUT) assert message_matcher.msg["params"]["uri"] == uri1 assert message_matcher.msg["params"]["diagnostics"] == [] message_matcher = language_server.obtain_pattern_message_matcher( {"method": "textDocument/publishDiagnostics"}) language_server.open_doc(uri2, 1, text=None) assert message_matcher.event.wait(TIMEOUT) assert message_matcher.msg["params"]["uri"] == uri2 assert message_matcher.msg["params"]["diagnostics"] == [] language_server.close_doc(uri2) language_server.close_doc(uri1)
def test_customize_interpreter_add_plugins_dir( language_server_io: ILanguageServerClient, workspace_dir: str, cases: CasesFixture): from robocorp_ls_core import uris import os from pathlib import Path from robotframework_ls.impl.robot_workspace import RobotDocument language_server = language_server_io cases.copy_to("custom_env", workspace_dir) language_server.initialize(workspace_dir, process_id=os.getpid()) case1_robot: Path = Path(workspace_dir) / "env1" / "caselib1.robot" assert case1_robot.exists() uri_case1 = uris.from_fs_path(str(case1_robot)) doc = RobotDocument(uri_case1) i_line = doc.find_line_with_contents(" verify lib1") language_server.open_doc(uri_case1, 1) ret = language_server.find_definitions(uri_case1, i_line, 6) result = ret["result"] assert not result # Now, customize it with the plugins. plugins_dir = cases.get_path("custom_env/plugins") add_plugins_result = language_server.execute_command( "robot.addPluginsDir", [plugins_dir]) assert add_plugins_result["result"] ret = language_server.find_definitions(uri_case1, i_line, 6) result = ret["result"] assert result check = next(iter(result)) assert check["uri"].endswith("lib1.py") # Check with another case case2_robot: Path = Path(workspace_dir) / "env2" / "caselib2.robot" assert case2_robot.exists() uri_case2 = uris.from_fs_path(str(case2_robot)) doc = RobotDocument(uri_case2) i_line = doc.find_line_with_contents(" verify lib2") ret = language_server.find_definitions(uri_case2, i_line, 6) result = ret["result"] assert result check = next(iter(result)) assert check["uri"].endswith("lib2.py")
def test_resolve_interpreter( cases: CasesFixture, config_provider: IConfigProvider, rcc_conda_installed ) -> None: from robocorp_ls_core.constants import NULL from robocorp_code.plugins.resolve_interpreter import RobocorpResolveInterpreter from robocorp_ls_core import uris from robocorp_ls_core.pluginmanager import PluginManager from pathlib import Path from robocorp_code.plugins.resolve_interpreter import _CacheInfo from robocorp_ls_core.ep_providers import EPConfigurationProvider from robocorp_ls_core.ep_providers import EPEndPointProvider _CacheInfo._cache_hit_files = 0 pm = PluginManager() pm.set_instance(EPConfigurationProvider, config_provider) pm.set_instance(EPEndPointProvider, NULL) resolve_interpreter = RobocorpResolveInterpreter(weak_pm=weakref.ref(pm)) path = cases.get_path( "custom_envs/simple-web-scraper/tasks/simple-web-scraper.robot" ) interpreter_info = resolve_interpreter.get_interpreter_info_for_doc_uri( uris.from_fs_path(path) ) assert interpreter_info assert os.path.exists(interpreter_info.get_python_exe()) environ = interpreter_info.get_environ() assert environ assert environ["RPA_SECRET_MANAGER"] == "RPA.Robocloud.Secrets.FileSecrets" assert environ["RPA_SECRET_FILE"] == "/Users/<your-username-here>/vault.json" additional_pythonpath_entries = interpreter_info.get_additional_pythonpath_entries() assert len(additional_pythonpath_entries) == 3 found = set() for v in additional_pythonpath_entries: p = Path(v) assert p.is_dir() found.add(p.name) assert found == {"variables", "libraries", "resources"} assert _CacheInfo._cache_hit_files == 0 assert _CacheInfo._cache_hit_interpreter == 0 interpreter_info = resolve_interpreter.get_interpreter_info_for_doc_uri( uris.from_fs_path(path) ) assert _CacheInfo._cache_hit_files == 3 assert _CacheInfo._cache_hit_interpreter == 1
def _resolve_interpreter(self, params=None) -> ActionResultDict: from robocorp_ls_core.ep_resolve_interpreter import EPResolveInterpreter from robocorp_ls_core.ep_resolve_interpreter import IInterpreterInfo try: from robocorp_ls_core import uris target_robot: str = params.get("target_robot") for ep in self._pm.get_implementations(EPResolveInterpreter): interpreter_info: IInterpreterInfo = ep.get_interpreter_info_for_doc_uri( uris.from_fs_path(target_robot) ) if interpreter_info is not None: return { "success": True, "message": None, "result": { "pythonExe": interpreter_info.get_python_exe(), "environ": interpreter_info.get_environ(), "additionalPythonpathEntries": interpreter_info.get_additional_pythonpath_entries(), }, } except Exception as e: log.exception(f"Error resolving interpreter. Args: {params}") return {"success": False, "message": str(e), "result": None} # i.e.: no error but we couldn't find an interpreter. return {"success": True, "message": "", "result": None}
def m_workspace__execute_command(self, command=None, arguments=()) -> Any: if command == "robot.addPluginsDir": directory: str = arguments[0] assert os.path.isdir( directory), f"Expected: {directory} to be a directory." self._pm.load_plugins_from(Path(directory)) return True elif command == "robot.resolveInterpreter": try: from robocorp_ls_core import uris from robotframework_ls.ep_resolve_interpreter import ( EPResolveInterpreter, ) from robotframework_ls.ep_resolve_interpreter import IInterpreterInfo target_robot: str = arguments[0] for ep in self._pm.get_implementations(EPResolveInterpreter): interpreter_info: IInterpreterInfo = ep.get_interpreter_info_for_doc_uri( uris.from_fs_path(target_robot)) if interpreter_info is not None: return { "pythonExe": interpreter_info.get_python_exe(), "environ": interpreter_info.get_environ(), "additionalPythonpathEntries": interpreter_info.get_additional_pythonpath_entries( ), } except: log.exception( f"Error resolving interpreter. Args: {arguments}")
def test_keyword_completions_prefer_local_library_import( language_server_tcp: ILanguageServerClient, ws_root_path, data_regression, cases ): from robocorp_ls_core.workspace import Document from robocorp_ls_core import uris try: os.makedirs(ws_root_path) except: pass language_server = language_server_tcp language_server.initialize(ws_root_path, process_id=os.getpid()) case1_robot_path = cases.get_path("case1/case1.robot") contents = """ *** Settings *** Library case1_library *** Test Cases *** User can call library verify model 1 verify_another_mod""" uri = uris.from_fs_path(case1_robot_path) language_server.open_doc(uri, 1, text=contents) def request_completion(): doc = Document("", source=contents) line, col = doc.get_last_line_col() completions = language_server.get_completions(uri, line, col) del completions["id"] return completions data_regression.check(request_completion())
def test_code_lens_integrated(language_server_io: ILanguageServerClient, ws_root_path, data_regression): from robocorp_ls_core import uris from robotframework_ls_tests.fixtures import check_code_lens_data_regression language_server = language_server_io language_server.initialize(ws_root_path, process_id=os.getpid()) os.makedirs(ws_root_path, exist_ok=True) uri = uris.from_fs_path(os.path.join(ws_root_path, "my.robot")) txt = """ *** Test Case *** Log It Log *** Task *** Log It2 Log """ language_server.open_doc(uri, 1, txt) ret = language_server.request_code_lens(uri) found = ret["result"] check_code_lens_data_regression(data_regression, found)
def test_typing_not_shown(libspec_manager, workspace, data_regression, workspace_dir): from robocorp_ls_core import uris from os.path import os from robotframework_ls_tests.fixtures import LIBSPEC_3 from robotframework_ls.impl import keyword_completions from robotframework_ls.impl.completion_context import CompletionContext from robocorp_ls_core.lsp import TextDocumentItem workspace_dir_a = os.path.join(workspace_dir, "workspace_dir_a") os.makedirs(workspace_dir_a) with open(os.path.join(workspace_dir_a, "my.libspec"), "w") as stream: stream.write(LIBSPEC_3) libspec_manager.add_workspace_folder(uris.from_fs_path(workspace_dir_a)) assert libspec_manager.get_library_info("case3_library", create=False) is not None workspace.set_root(workspace_dir, libspec_manager=libspec_manager) doc = workspace.ws.put_document(TextDocumentItem("temp_doc.robot", text="")) doc.source = """*** Settings *** Library case3_library *** Test Cases *** Can use resource keywords Case Verify""" completions = keyword_completions.complete( CompletionContext(doc, workspace=workspace.ws)) data_regression.check(completions)
def rf_interpreter_startup(language_server_io: ILanguageServerClient, ws_root_path): from robotframework_ls.commands import ROBOT_INTERNAL_RFINTERACTIVE_START from robotframework_ls.commands import ROBOT_INTERNAL_RFINTERACTIVE_STOP from robocorp_ls_core import uris language_server = language_server_io language_server.initialize(ws_root_path, process_id=os.getpid()) os.makedirs(ws_root_path, exist_ok=True) uri = uris.from_fs_path(os.path.join(ws_root_path, "my.robot")) ret1 = language_server.execute_command(ROBOT_INTERNAL_RFINTERACTIVE_START, [{ "uri": uri }]) assert ret1["result"] == { "success": True, "message": None, "result": { "interpreter_id": 0 }, } yield _RfInterpreterInfo(interpreter_id=0, uri=uri) # Note: success could be False if it was stopped in the test... language_server.execute_command(ROBOT_INTERNAL_RFINTERACTIVE_STOP, [{ "interpreter_id": 0 }])
def test_find_definition_keywords(language_server: ILanguageServerClient, cases, workspace_dir): from robocorp_ls_core import uris cases.copy_to("case2", workspace_dir) language_server.initialize(workspace_dir, process_id=os.getpid()) case2_robot = os.path.join(workspace_dir, "case2.robot") assert os.path.exists(case2_robot) uri = uris.from_fs_path(case2_robot) language_server.open_doc(uri, 1, text=None) ret = language_server.find_definitions(uri, 7, 6) result = ret["result"] assert len(result) == 1 check = next(iter(result)) assert check["uri"].endswith("case2.robot") assert check["range"] == { "start": { "line": 1, "character": 0 }, "end": { "line": 4, "character": 5 }, }
def m_text_document__hover(self, **kwargs): """ When hovering over a png in base64 surrounded by double-quotes... something as: "iVBORw0KGgo...rest of png in base 64 contents..." i.e.: Provide the contents in markdown format to show the actual image from the locators.json. """ from robocorp_ls_core import uris from robocorp_ls_core.protocols import IDocument from robocorp_ls_core.protocols import IDocumentSelection from robocorp_ls_core.lsp import Range from robocorp_ls_core.lsp import MarkupKind from robocorp_ls_core.lsp import MarkupContent doc_uri = kwargs["textDocument"]["uri"] # Note: 0-based line: int = kwargs["position"]["line"] col: int = kwargs["position"]["character"] if not uris.to_fs_path(doc_uri).endswith("locators.json"): return None document: IDocument = self._workspace.get_document( doc_uri, accept_from_file=True) sel: IDocumentSelection = document.selection(line, col) current_line: str = sel.current_line i: int = current_line.find( '"iVBORw0KGgo' ) # I.e.: pngs in base64 always start with this prefix. if i >= 0: current_line = current_line[i + 1:] i = current_line.find('"') if i >= 0: current_line = current_line[0:i] image_path = f"data:image/png;base64,{current_line}" s = f"![Screenshot]({image_path})" return { "contents": MarkupContent(MarkupKind.Markdown, s).to_dict(), "range": Range((line, col), (line, col)).to_dict(), } # Could not find a base-64 img embedded, let's see if we have an element # with a relative path. import re p = Path(document.path).parent for found in re.findall('"(.+?)"', current_line): if found.endswith(".png"): check = p / found if check.exists(): as_uri = uris.from_fs_path(str(check)) s = f"![Screenshot]({as_uri})" return { "contents": MarkupContent(MarkupKind.Markdown, s).to_dict(), "range": Range((line, col), (line, col)).to_dict(), } return None
def test_document_from_file(workspace, workspace_dir, cases): from os.path import os from robocorp_ls_core import uris from robocorp_ls_core.lsp import TextDocumentItem cases.copy_to("case1", workspace_dir) workspace.set_root(workspace_dir) ws = workspace.ws case1_file = os.path.join(workspace_dir, "case1.robot") assert os.path.exists(case1_file) case1_doc_uri = uris.from_fs_path(case1_file) resource_doc = ws.get_document(case1_doc_uri, accept_from_file=False) assert resource_doc is None cached_doc = ws.get_document(case1_doc_uri, accept_from_file=True) assert cached_doc is not None assert "*** Settings ***" in cached_doc.source with open(case1_file, "w") as stream: stream.write("new contents") assert "*** Settings ***" in cached_doc.source # i.e.: Unchanged # When we get it again it verifies the filesystem. cached_doc2 = ws.get_document(case1_doc_uri, accept_from_file=True) assert cached_doc is not cached_doc2 # i.e.: Unchanged initial version in memory assert "*** Settings ***" in cached_doc.source assert cached_doc2.source == "new contents" # Still None if we can't accept cached. resource_doc = ws.get_document(case1_doc_uri, accept_from_file=False) assert resource_doc is None ws.put_document(TextDocumentItem(case1_doc_uri, text="rara")) resource_doc = ws.get_document(case1_doc_uri, accept_from_file=False) assert resource_doc is not None assert resource_doc is not cached_doc ws.remove_document(case1_doc_uri) resource_doc = ws.get_document(case1_doc_uri, accept_from_file=False) assert resource_doc is None cached_doc3 = ws.get_document(case1_doc_uri, accept_from_file=True) assert cached_doc3 is not None # i.e.: it should've been pruned when the doc was added. assert cached_doc3 is not cached_doc assert cached_doc3.source == "new contents" os.remove(case1_file) cached_doc4 = ws.get_document(case1_doc_uri, accept_from_file=True) assert cached_doc4 is None # The old one in memory doesn't change after the file is removed assert cached_doc3.source == "new contents"
def workspace_symbols( query: Optional[str], context: BaseContext ) -> List[SymbolInformationTypedDict]: from robotframework_ls.impl.libspec_manager import LibspecManager from robotframework_ls.impl.robot_specbuilder import LibraryDoc from robocorp_ls_core import uris from robotframework_ls.impl.protocols import IRobotWorkspace from pathlib import Path from typing import cast from robotframework_ls.impl import ast_utils ret: List[SymbolInformationTypedDict] = [] workspace: IRobotWorkspace = context.workspace libspec_manager: LibspecManager = workspace.libspec_manager folder_paths = sorted(set(workspace.get_folder_paths())) library_names: Set[str] = set() for folder_path in folder_paths: for path in Path(folder_path).glob("**/*"): if path.name.lower().endswith((".robot", ".resource", ".txt")): doc = cast( Optional[IRobotDocument], workspace.get_document( uris.from_fs_path(str(path)), accept_from_file=True ), ) if doc is not None: symbols_cache = doc.symbols_cache if symbols_cache is None: symbols_cache = _compute_symbols_from_ast(doc) doc.symbols_cache = symbols_cache add_to_ret(ret, symbols_cache, query) ast = doc.get_ast() if ast: for library_import in ast_utils.iter_library_imports(ast): library_names.add(library_import.node.name) library_names.update(libspec_manager.get_library_names()) for library_name in library_names: library_info: Optional[LibraryDoc] = libspec_manager.get_library_info( library_name, create=True ) if library_info is not None: symbols_cache = library_info.symbols_cache if symbols_cache is None: symbols_cache = _compute_symbols_from_library_info( library_name, library_info ) library_info.symbols_cache = symbols_cache add_to_ret(ret, symbols_cache, query) return ret
def _iter_all_doc_uris(self, extensions: Tuple[str, ...]) -> Iterable[str]: """ :param extensions: The extensions which are being searched (i.e.: ('.txt', '.py')). """ assert self._extensions.issuperset(extensions) dir_infos = list(self._dir_to_info.values()) for dir_info in dir_infos: for f in dir_info.files_in_directory: if f.endswith(extensions): yield uris.from_fs_path(f)
def test_completion_not_duplicated(workspace, cases, libspec_manager, workspace_dir): from robocorp_ls_core.lsp import TextDocumentItem import os.path from robocorp_ls_core import uris from robotframework_ls.robot_config import RobotConfig from robotframework_ls.impl.collect_keywords import ( collect_keyword_name_to_keyword_found, ) from robotframework_ls.impl.protocols import IKeywordFound cases.copy_to("case_inner_keywords", workspace_dir) workspace.set_root(workspace_dir, libspec_manager=libspec_manager) config = RobotConfig() config.update({"robot.pythonpath": [workspace_dir]}) libspec_manager.config = config uri = uris.from_fs_path(os.path.join(workspace_dir, "inner", "case_inner.robot")) workspace.ws.put_document( TextDocumentItem( uri, text="""*** Settings *** Resource case_root.robot *** Keywords *** Check with keyword at inner [Arguments] ${arg1} ${arg2} Should Be Equal ${arg1} ${arg2} *** Test Cases *** Testing Completion Here Check with ke""", ) ) doc = workspace.ws.get_document(uri, accept_from_file=False) from robotframework_ls.impl.completion_context import CompletionContext from robotframework_ls.impl import auto_import_completions workspace.ws.wait_for_check_done(5) context = CompletionContext(doc, workspace=workspace.ws, config=config) keyword_name_to_keyword_found: Dict[ str, List[IKeywordFound] ] = collect_keyword_name_to_keyword_found(context) completions = auto_import_completions.complete( context, keyword_name_to_keyword_found ) # I.e.: all the related symbols are already imported and will be shown # in the regular completion. assert len(completions) == 0
def get_resource_import_as_doc(self, resource_import) -> Optional[IRobotDocument]: from robocorp_ls_core import uris import os.path from robotframework_ls.impl.robot_lsp_constants import OPTION_ROBOT_PYTHONPATH ws = self._workspace for token in resource_import.tokens: if token.type == token.NAME: name_with_resolved_vars = self.token_value_resolving_variables(token) if not os.path.isabs(name_with_resolved_vars): # It's a relative resource, resolve its location based on the # current file. check_paths = [ os.path.normpath( os.path.join( os.path.dirname(self.doc.path), name_with_resolved_vars ) ) ] config = self.config if config is not None: for additional_pythonpath_entry in config.get_setting( OPTION_ROBOT_PYTHONPATH, list, [] ): check_paths.append( os.path.normpath( os.path.join( additional_pythonpath_entry, name_with_resolved_vars, ) ) ) else: check_paths = [name_with_resolved_vars] for resource_path in check_paths: doc_uri = uris.from_fs_path(resource_path) resource_doc = ws.get_document(doc_uri, accept_from_file=True) if resource_doc is None: continue return resource_doc log.info( "Unable to find: %s (checked paths: %s)", name_with_resolved_vars, check_paths, ) return None
def rf_server_api(tmpdir): from robotframework_ls_tests.fixtures import initialize_robotframework_server_api from robotframework_ls.server_api.server import RobotFrameworkServerApi from robocorp_ls_core import uris api: RobotFrameworkServerApi = initialize_robotframework_server_api( libspec_manager=None # It'll be auto-initialized as needed. ) root_uri = uris.from_fs_path(str(tmpdir)) api.m_initialize(rootUri=root_uri) yield api api.m_shutdown() api.m_exit()
def test_robotframework_integrated_completions(rf_configured_api, rf_root): from robocorp_ls_core import uris from robocorp_ls_core.workspace import Document api = rf_configured_api doc_uri = uris.from_fs_path( str(rf_root / "atest" / "robot" / "cli" / "dryrun" / "args.robot")) text = """*** Settings *** Suite Setup Run Tests --dryrun cli/dryrun/args.robot Resource atest_resource.robot *** Test Cases *** Valid positional args Check Test Case ${TESTNAME} Too few arguments Check Test Case ${TESTNAME} Too few arguments for UK Check Test Case ${TESTNAME} Too many arguments Check Test Case ${TESTNAME} Valid named args Check Test Case ${TESTNAME} Invalid named args Check Test Case ${TESTNAME} Ch""" api.m_text_document__did_open(textDocument={"uri": doc_uri, "text": text}) api.workspace.wait_for_check_done(10) doc = Document("") doc.source = text PRINT_TIMES = False if PRINT_TIMES: import time curtime = time.time() for i in range(5): line, col = doc.get_last_line_col() func = api.m_complete_all(doc_uri, line, col) assert len(func(monitor=NULL)) > 10 if PRINT_TIMES: print("Total %s: %.2fs" % (i, time.time() - curtime)) curtime = time.time()
def setup(tmpdir): from robotframework_interactive.server.rf_interpreter_server_manager import ( RfInterpreterServerManager, ) from robocorp_ls_core import uris received_messages = [] def on_interpreter_message(msg): received_messages.append(msg) uri = uris.from_fs_path(str(tmpdir.join("my.robot"))) rf_interpreter_server_manager = RfInterpreterServerManager( on_interpreter_message=on_interpreter_message, uri=uri) yield _Setup(rf_interpreter_server_manager, received_messages, uri) rf_interpreter_server_manager.interpreter_stop()
def rf_configured_api(rf_root): from robotframework_ls_tests.fixtures import initialize_robotframework_server_api from robotframework_ls.server_api.server import RobotFrameworkServerApi from robocorp_ls_core import uris api: RobotFrameworkServerApi = initialize_robotframework_server_api( libspec_manager=None # It'll be auto-initialized as needed. ) root_uri = uris.from_fs_path(str(rf_root)) api.m_initialize(rootUri=root_uri) api.m_workspace__did_change_configuration( settings={"robot.pythonpath": [str(rf_root / "atest" / "resources")]}) yield api api.m_shutdown() api.m_exit()
def m_workspace__execute_command(self, command=None, arguments=()) -> Any: if command == "robot.addPluginsDir": directory: str = arguments[0] assert os.path.isdir( directory), f"Expected: {directory} to be a directory." self._pm.load_plugins_from(Path(directory)) return True elif command == "robot.getInternalInfo": in_memory_docs = [] workspace = self.workspace if workspace: for doc in workspace.iter_documents(): in_memory_docs.append({"uri": doc.uri}) return { "settings": self.config.get_full_settings(), "inMemoryDocs": in_memory_docs, "processId": os.getpid(), } elif command == "robot.resolveInterpreter": try: from robocorp_ls_core import uris from robotframework_ls.ep_resolve_interpreter import ( EPResolveInterpreter, ) from robotframework_ls.ep_resolve_interpreter import IInterpreterInfo target_robot: str = arguments[0] for ep in self._pm.get_implementations(EPResolveInterpreter): interpreter_info: IInterpreterInfo = ep.get_interpreter_info_for_doc_uri( uris.from_fs_path(target_robot)) if interpreter_info is not None: return { "pythonExe": interpreter_info.get_python_exe(), "environ": interpreter_info.get_environ(), "additionalPythonpathEntries": interpreter_info.get_additional_pythonpath_entries( ), } except: log.exception( f"Error resolving interpreter. Args: {arguments}") elif command == "robot.getLanguageServerVersion": return __version__
def test_hover_image_integration( language_server_initialized: IRobocorpLanguageServerClient, tmpdir): from robocorp_ls_core.workspace import Document from robocorp_code_tests.fixtures import IMAGE_IN_BASE64 import base64 from robocorp_ls_core import uris locators_json = tmpdir.join("locators.json") locators_json.write_text("", "utf-8") imgs_dir = tmpdir.join(".images") imgs_dir.mkdir() img1 = imgs_dir.join("img1.png") with img1.open("wb") as stream: stream.write(base64.b64decode(IMAGE_IN_BASE64)) client = language_server_initialized uri = uris.from_fs_path(str(locators_json)) txt = """ "Image.Locator.01": { "path": ".images/img1.png", "source": ".images/img1.png" """ doc = Document("", txt) client.open_doc(uri, 1, txt) line, col = doc.get_last_line_col() ret = client.hover(uri, line, col) result = ret["result"] value = result["contents"].pop("value") assert value.startswith("![Screenshot](file://") assert value.endswith("/.images/img1.png)") assert ret["result"] == { "contents": { "kind": "markdown", # "value": "![Screenshot](file:///c:/Users/fabio/AppData/Local/Temp/pytest-of-fabio/pytest-5202/test_hover_image_integration0/.images/img1.png)", }, "range": { "start": { "line": 3, "character": 37 }, "end": { "line": 3, "character": 37 }, }, }
def _compute_symbols_from_library_info(library_name, library_info) -> SymbolsCache: from robocorp_ls_core.lsp import SymbolKind from robotframework_ls.impl.robot_specbuilder import KeywordDoc from robocorp_ls_core import uris symbols = [] keyword: KeywordDoc for keyword in library_info.keywords: source = keyword.source if not source: source = library_info.source if not source: log.info("Found no source for: %s", library_info) continue uri = uris.from_fs_path(source) lineno = keyword.lineno if lineno < 0: # This happens for some Reserved.py keywords (which should # not be shown. continue lineno -= 1 symbols.append({ "name": keyword.name, "kind": SymbolKind.Method, "location": { "uri": uri, "range": { "start": { "line": lineno, "character": 0 }, "end": { "line": lineno, "character": 0 }, }, }, "containerName": library_name, }) return SymbolsCache(symbols, library_info, None)
def test_code_lens_integrated_rf_interactive( language_server_io: ILanguageServerClient, ws_root_path, data_regression): from robocorp_ls_core import uris from robotframework_ls_tests.fixtures import check_code_lens_data_regression language_server = language_server_io language_server.initialize(ws_root_path, process_id=os.getpid()) uri_untitled = "~untitled" txt = """ *** Task *** Log It Log """ language_server.open_doc(uri_untitled, 1, txt) ret = language_server.request_code_lens(uri_untitled) found = ret["result"] assert not found # when unable to resolve path, we can't create it. os.makedirs(ws_root_path, exist_ok=True) uri = uris.from_fs_path(os.path.join(ws_root_path, "my.robot")) txt = """ *** Task *** Log It Log """ language_server.open_doc(uri, 1, txt) ret = language_server.request_code_lens(uri) found = ret["result"] for code_lens in found: if code_lens.get("data", {}).get("type") == "scratchpad": break else: raise AssertionError(f"Unable to find Scratchpad code lens in: {ret}") check_code_lens_data_regression(data_regression, [code_lens], basename="code_lens_before_resolve") ret = language_server.request_resolve_code_lens(code_lens) resolved_code_lens = ret["result"] check_code_lens_data_regression(data_regression, [resolved_code_lens], basename="code_lens_after_resolve")
def _threaded_find_definition(self, doc_uri, line, col, monitor) -> Optional[list]: from robotframework_ls.impl.find_definition import find_definition import os.path from robocorp_ls_core.lsp import Location, Range from robocorp_ls_core import uris completion_context = self._create_completion_context( doc_uri, line, col, monitor ) if completion_context is None: return None definitions = find_definition(completion_context) ret = [] for definition in definitions: if not definition.source: log.info("Found definition with empty source (%s).", definition) continue if not os.path.exists(definition.source): log.info( "Found definition: %s (but source does not exist).", definition ) continue lineno = definition.lineno if lineno is None or lineno < 0: lineno = 0 end_lineno = definition.end_lineno if end_lineno is None or end_lineno < 0: end_lineno = 0 col_offset = definition.col_offset end_col_offset = definition.end_col_offset ret.append( Location( uris.from_fs_path(definition.source), Range((lineno, col_offset), (end_lineno, end_col_offset)), ).to_dict() ) return ret
def test_lint_robot_integration( language_server_initialized: IRobocorpLanguageServerClient, tmpdir, data_regression): from robocorp_ls_core import uris from robocorp_ls_core.unittest_tools.fixtures import TIMEOUT robot_yaml = tmpdir.join("robot.yaml") robot_yaml_text = """ tasks: Obtain environment information: command: - python - get_env_info.py artifactsDir: output condaConfigFile: conda.yaml """ robot_yaml.write_text(robot_yaml_text, "utf-8") conda_yaml = tmpdir.join("conda.yaml") conda_yaml.write_text( """ channels: - defaults - conda-forge dependencies: - python=3.8 """, "utf-8", ) language_server = language_server_initialized robot_yaml_uri = uris.from_fs_path(str(robot_yaml)) message_matcher = language_server.obtain_pattern_message_matcher( {"method": "textDocument/publishDiagnostics"}) language_server.open_doc(robot_yaml_uri, 1, robot_yaml_text) assert message_matcher.event.wait(TIMEOUT) diag = message_matcher.msg["params"]["diagnostics"] data_regression.check(sort_diagnostics(diag))
def test_robotframework_integrated_go_to_def(rf_configured_api, rf_root): from robocorp_ls_core import uris from robocorp_ls_core.workspace import Document api = rf_configured_api doc_uri = uris.from_fs_path( str(rf_root / "atest" / "resources" / "foobar.robot")) text = """*** Settings *** Library TestCheckerLibrary""" api.m_text_document__did_open(textDocument={"uri": doc_uri, "text": text}) doc = Document("") doc.source = text line, col = doc.get_last_line_col() func = api.m_find_definition(doc_uri, line, col) found = func(monitor=NULL) assert len(found) == 1 found[0]["uri"].endswith("TestCheckerLibrary.py")
def scandir(self, scan_path: str, directories: Set[str], extensions: Tuple[str]): """ :param scan_path: The path to be scanned. :param directories: A set where the directories found in that path will be added to. :param extensions: The extensions which are being searched (i.e.: ('.txt', '.py')). """ assert self._extensions.issuperset(extensions) dir_info = self._dir_to_info.get(scan_path) if dir_info is None: return directories.update(dir_info.directories) for f in dir_info.files_to_mtime: if f.endswith(extensions): yield uris.from_fs_path(f)
def setup_case2_doc(workspace, cases, libspec_manager, workspace_dir): from robocorp_ls_core.lsp import TextDocumentItem import os.path from robocorp_ls_core import uris cases.copy_to("case1", workspace_dir) workspace.set_root(workspace_dir, libspec_manager=libspec_manager) uri = uris.from_fs_path(os.path.join(workspace_dir, "case2.robot")) workspace.ws.put_document( TextDocumentItem( uri, text=""" *** Test Cases *** User can call library Verify another m""", )) doc = workspace.ws.get_document(uri, accept_from_file=False) return doc