diff --git a/codeflash/cli_cmds/cli.py b/codeflash/cli_cmds/cli.py index 3f8f8767..f95403c6 100644 --- a/codeflash/cli_cmds/cli.py +++ b/codeflash/cli_cmds/cli.py @@ -111,7 +111,7 @@ def process_and_validate_cmd_args(args: Namespace) -> Namespace: from codeflash.code_utils.github_utils import require_github_app_or_exit is_init: bool = args.command.startswith("init") if args.command else False - if args.verbose: + if args.verbose or is_LSP_enabled(): logging_config.set_level(logging.DEBUG, echo_setting=not is_init) else: logging_config.set_level(logging.INFO, echo_setting=not is_init) diff --git a/codeflash/cli_cmds/console.py b/codeflash/cli_cmds/console.py index ca8e29e2..61877971 100644 --- a/codeflash/cli_cmds/console.py +++ b/codeflash/cli_cmds/console.py @@ -1,10 +1,10 @@ from __future__ import annotations +import json import logging -import os from contextlib import contextmanager from itertools import cycle -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any from rich.console import Console from rich.logging import RichHandler @@ -20,6 +20,7 @@ from codeflash.cli_cmds.console_constants import SPINNER_TYPES from codeflash.cli_cmds.logging_config import BARE_LOGGING_FORMAT +from codeflash.lsp.helpers import enhanced_log, is_LSP_enabled if TYPE_CHECKING: from collections.abc import Generator @@ -30,7 +31,7 @@ console = Console() -if os.getenv("CODEFLASH_LSP"): +if is_LSP_enabled(): console.quiet = True logging.basicConfig( @@ -42,6 +43,18 @@ logger = logging.getLogger("rich") logging.getLogger("parso").setLevel(logging.WARNING) +# override the logger to reformat the messages for the lsp +for level in ("info", "debug", "warning", "error"): + real_fn = getattr(logger, level) + setattr(logger, level, lambda msg, *args, _real_fn=real_fn, **kwargs: enhanced_log(msg, _real_fn, *args, **kwargs)) + + +def lsp_log(serializable: dict[str, Any], *args: Any, **kwargs: Any) -> None: # noqa: ANN401 + if not is_LSP_enabled(): + return + msg_str = json.dumps(serializable) + logger.info(msg_str, *args, **kwargs) + def paneled_text( text: str, panel_args: dict[str, str | bool] | None = None, text_args: dict[str, str] | None = None @@ -62,8 +75,13 @@ def code_print(code_str: str) -> None: """Print code with syntax highlighting.""" from rich.syntax import Syntax + formatted_code = Syntax(code_str, "python", line_numbers=True, theme="github-dark") + # if is_LSP_enabled(): + # logger.debug(formatted_code.__str__()) + # return + console.rule() - console.print(Syntax(code_str, "python", line_numbers=True, theme="github-dark")) + console.print(formatted_code) console.rule() diff --git a/codeflash/lsp/helpers.py b/codeflash/lsp/helpers.py index dc8f8c5d..27f10565 100644 --- a/codeflash/lsp/helpers.py +++ b/codeflash/lsp/helpers.py @@ -1,7 +1,27 @@ import os from functools import lru_cache +from typing import Any, Callable @lru_cache(maxsize=1) def is_LSP_enabled() -> bool: return os.getenv("CODEFLASH_LSP", default="false").lower() == "true" + + +def enhanced_log(msg: str, actual_log_fn: Callable[[str, Any, Any], None], *args: Any, **kwargs: Any) -> None: # noqa: ANN401 + lsp_enabled = is_LSP_enabled() + + # normal cli moded + if not lsp_enabled: + actual_log_fn(msg, *args, **kwargs) + return + + #### LSP mode #### + if type(msg) != str: # noqa: E721 + return + + if msg.startswith("Nonzero return code"): + # skip logging the failed tests msg to the client + return + + actual_log_fn(f"::::{msg}", *args, **kwargs) diff --git a/codeflash/lsp/server_entry.py b/codeflash/lsp/server_entry.py index 5ea30cde..a905ab0b 100644 --- a/codeflash/lsp/server_entry.py +++ b/codeflash/lsp/server_entry.py @@ -16,17 +16,15 @@ # Configure logging to stderr for VS Code output channel def setup_logging() -> logging.Logger: # Clear any existing handlers to prevent conflicts - root_logger = logging.getLogger() + root_logger = logging.getLogger("rich") root_logger.handlers.clear() # Set up stderr handler for VS Code output channel with [LSP-Server] prefix handler = logging.StreamHandler(sys.stderr) - # adding the :::: here for the client to easily extract the message from the log - handler.setFormatter(logging.Formatter("[LSP-Server] %(asctime)s [%(levelname)s]::::%(message)s")) + handler.setLevel(logging.DEBUG) # Configure root logger root_logger.addHandler(handler) - root_logger.setLevel(logging.INFO) # Also configure the pygls logger specifically pygls_logger = logging.getLogger("pygls") diff --git a/codeflash/optimization/function_optimizer.py b/codeflash/optimization/function_optimizer.py index c523dcbc..3fbf6463 100644 --- a/codeflash/optimization/function_optimizer.py +++ b/codeflash/optimization/function_optimizer.py @@ -169,10 +169,12 @@ def _process_refinement_results(self) -> OptimizedCandidate | None: for candidate in refinement_response: self.candidate_queue.put(candidate) - self.candidate_len += len(refinement_response) - logger.info( - f"Added {len(refinement_response)} candidates from refinement, total candidates now: {self.candidate_len}" - ) + if len(refinement_response) > 0: + self.candidate_len += len(refinement_response) + logger.info( + f"Added {len(refinement_response)} candidates from refinement, total candidates now: {self.candidate_len}" + ) + self.refinement_done = True return self.get_next_candidate()