Skip to content

Commit be9f2db

Browse files
committed
open documentation server in a port range and with external uri conversion
1 parent 97a2b99 commit be9f2db

File tree

10 files changed

+50
-34
lines changed

10 files changed

+50
-34
lines changed

robotcode/debugger/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ async def start_debugpy_async(
8686
) -> None:
8787
from ..utils.async_tools import run_coroutine_from_thread_async
8888
from ..utils.debugpy import enable_debugpy, wait_for_debugpy_connected
89-
from ..utils.net import check_free_port
89+
from ..utils.net import find_free_port
9090
from .dap_types import Event
9191

92-
port = check_free_port(debugpy_port)
92+
port = find_free_port(debugpy_port)
9393
if port != debugpy_port:
9494
_logger.warning(f"start debugpy session on port {port}")
9595

robotcode/language_server/common/parts/diagnostics.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ async def force_refresh_document(self, document: TextDocument, refresh: bool = T
242242
await self.refresh()
243243

244244
@_logger.call
245+
@threaded()
245246
async def on_did_close(self, sender: Any, document: TextDocument) -> None:
246247
if await self.get_diagnostics_mode(document.uri) == DiagnosticsMode.WORKSPACE:
247248
return

robotcode/language_server/common/parts/documents.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ async def get_or_open_document(
134134
) -> TextDocument:
135135
uri = Uri.from_path(path).normalized()
136136

137-
result = await self.parent.documents.get(uri)
137+
result = await self.get(uri)
138138
if result is not None:
139139
return result
140140

robotcode/language_server/common/text_document.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ async def remove_cache_entry(
236236
def set_data(self, key: Any, data: Any) -> None:
237237
self._data[key] = data
238238

239+
def remove_data(self, key: Any) -> None:
240+
self._data.pop(key)
241+
239242
def get_data(self, key: Any, default: Optional[_T] = None) -> _T:
240243
return self._data.get(key, default)
241244

robotcode/language_server/robotframework/diagnostics/namespace.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,11 @@ async def ensure_initialized(self) -> bool:
827827
except BaseException as e:
828828
if not isinstance(e, asyncio.CancelledError):
829829
self._logger.exception(e, level=logging.DEBUG)
830+
831+
if self.document is not None:
832+
self.document.remove_data(Namespace)
833+
self.document.remove_data(Namespace.DataEntry)
834+
830835
await self.invalidate()
831836
raise
832837

robotcode/language_server/robotframework/parts/code_action.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
import socket
55
import threading
66
import traceback
7+
import urllib.parse
78
from concurrent.futures import ProcessPoolExecutor
89
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
910
from threading import Thread
1011
from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Union, cast
1112
from urllib.parse import parse_qs, urlparse
1213

1314
from ....utils.logging import LoggingDescriptor
14-
from ....utils.net import check_free_port
15+
from ....utils.net import find_free_port
1516
from ...common.decorators import code_action_kinds, language_id
1617
from ...common.lsp_types import (
1718
CodeAction,
@@ -182,8 +183,9 @@ async def shutdown(self, sender: Any) -> None:
182183
self._documentation_server = None
183184

184185
def _run_server(self) -> None:
185-
self._documentation_server_port = check_free_port(3100)
186-
with DualStackServer(("", self._documentation_server_port), LibDocRequestHandler) as server:
186+
self._documentation_server_port = find_free_port(3100, 3200)
187+
188+
with DualStackServer(("127.0.0.1", self._documentation_server_port), LibDocRequestHandler) as server:
187189
self._documentation_server = server
188190
try:
189191
server.serve_forever()
@@ -316,14 +318,11 @@ async def build_url(
316318
except BaseException:
317319
pass
318320

319-
url_args = f"&args={'::'.join(args)}" if args else ""
321+
url_args = "::".join(args) if args else ""
320322

321-
url = (
322-
f"http://localhost:{self._documentation_server_port}"
323-
f"/?name={name}"
324-
f"{url_args}"
325-
f"&basedir={base_dir}"
326-
f"{'#{target}' if target else ''}"
327-
)
323+
base_url = f"http://localhost:{self._documentation_server_port}"
324+
params = urllib.parse.urlencode({"name": name, "args": url_args, "basedir": base_dir})
325+
326+
url = f"{base_url}" f"/?&{params}" f"{f'#{target}' if target else ''}"
328327

329328
return url

robotcode/utils/debugpy.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from .logging import LoggingDescriptor
2-
from .net import check_free_port
2+
from .net import find_free_port
33

44
_logger = LoggingDescriptor(name=__name__)
55

@@ -38,7 +38,7 @@ def start_debugpy(port: int, wait_for_client: bool) -> bool:
3838
if is_debugpy_installed():
3939
import debugpy
4040

41-
real_port = check_free_port(port)
41+
real_port = find_free_port(port)
4242
if real_port != port:
4343
_logger.warning(f"start debugpy session on port {real_port}")
4444
debugpy.listen(real_port)

robotcode/utils/net.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,34 @@
1+
import contextlib
12
import socket
23
from contextlib import closing
3-
from typing import cast
4+
from typing import Optional, cast
45

56
from .logging import LoggingDescriptor
67

78
_logger = LoggingDescriptor(name=__name__)
89

910

10-
def find_free_port() -> int:
11-
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
12-
s.bind(("127.0.0.1", 0))
13-
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
14-
return cast(int, s.getsockname()[1])
11+
def find_free_port(start: Optional[int] = None, end: Optional[int] = None) -> int:
12+
port = start
13+
if port is None:
14+
port = 0
15+
if end is None:
16+
end = port
1517

18+
try:
19+
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
20+
with contextlib.suppress(Exception):
21+
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
1622

17-
def check_free_port(port: int) -> int:
18-
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
19-
try:
2023
s.bind(("127.0.0.1", port))
24+
2125
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
2226
return cast(int, s.getsockname()[1])
23-
except (SystemExit, KeyboardInterrupt):
24-
raise
25-
except BaseException:
26-
_logger.warning(f"Port {port} is not free. Try to find a free port.")
27-
return find_free_port()
27+
except (SystemExit, KeyboardInterrupt):
28+
raise
29+
except BaseException:
30+
if port and end > port:
31+
return find_free_port(port + 1, end)
32+
elif start and start > 0:
33+
return find_free_port(None)
34+
raise

robotcode/utils/uri.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ def _to_path_str(self) -> str:
108108
invalid characters and semantics. Will *not* look at the scheme of this URI.
109109
"""
110110
# scheme://netloc/path;parameters?query#fragment
111-
netloc = parse.unquote(self._parts.netloc)
112-
path = parse.unquote(self._parts.path)
111+
netloc = parse.unquote(self.netloc)
112+
path = parse.unquote(self.path)
113113

114114
if self._parts.scheme != "file":
115115
raise InvalidUriError(f"Invalid URI scheme '{str(self)}'.")

vscode-client/extension.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ export async function activateAsync(context: vscode.ExtensionContext): Promise<v
3131
debugManager,
3232
testControllerManger,
3333
vscode.commands.registerCommand("robotcode.showDocumentation", async (url: string) => {
34-
// await vscode.env.openExternal(vscode.Uri.parse(url));
35-
await vscode.commands.executeCommand("simpleBrowser.api.open", url, {
34+
const uri = vscode.Uri.parse(url);
35+
const external_uri = await vscode.env.asExternalUri(uri);
36+
await vscode.commands.executeCommand("simpleBrowser.api.open", external_uri.toString(true), {
3637
preserveFocus: true,
3738
viewColumn: vscode.ViewColumn.Beside,
3839
});

0 commit comments

Comments
 (0)