Hone logo
Hone
Problems

Minimal Python Language Server

Language servers provide features like autocompletion, go-to-definition, find-all-references, and diagnostics (linting/error checking) to IDEs and editors. This challenge asks you to build a minimal language server for Python, focusing on providing basic diagnostics (linting) using the pylint library. This is a valuable exercise in understanding how language servers work and how to integrate external tools into a standardized protocol.

Problem Description

You are tasked with creating a simple Python language server that analyzes Python files for potential errors and style issues using pylint. The server should listen for incoming requests from a Language Server Protocol (LSP) client and respond with diagnostic information. The core functionality is to take a file path as input, run pylint on that file, and return a list of diagnostic messages (errors, warnings, etc.) in the LSP format. The server should handle cases where pylint is not installed and provide appropriate error responses.

Key Requirements:

  • LSP Compliance: The server must adhere to the basic LSP protocol for diagnostics.
  • Pylint Integration: Utilize the pylint library to perform static analysis.
  • Error Handling: Gracefully handle cases where pylint is not installed.
  • Diagnostic Reporting: Return diagnostic messages with appropriate severity levels (Error, Warning, Info, etc.) and line/column information.
  • Asynchronous Operation: While not strictly required for a minimal implementation, consider using asynchronous operations (e.g., asyncio) for improved responsiveness, especially when running pylint.

Expected Behavior:

  1. The server should listen for incoming LSP requests (specifically, the textDocument/didOpen and textDocument/didChange notifications, though you can initially focus on didOpen for simplicity).
  2. Upon receiving a request with a file path, the server should:
    • Check if pylint is installed. If not, return an error response to the client.
    • Run pylint on the specified file.
    • Parse the pylint output and convert it into a list of LSP diagnostic messages.
    • Send the list of diagnostic messages back to the client.
  3. The server should be able to handle multiple file requests concurrently.

Edge Cases to Consider:

  • pylint not installed.
  • Invalid file paths.
  • Large files (consider performance implications).
  • Files with non-Python content.
  • Empty files.

Examples

Example 1:

Input: File path: "example.py" containing: "print(123)"
Output: [
    {
        "range": {
            "start": {
                "line": 1,
                "character": 0
            },
            "end": {
                "line": 1,
                "character": 15
            }
        },
        "message": "Indentation error",
        "severity": 1  // 1 represents Error in LSP
    }
]
Explanation: `pylint` might flag an indentation error (depending on the project's configuration). The output is a list of diagnostics, each with a range (line and character positions) and a message. Severity 1 indicates an error.

Example 2:

Input: File path: "example.py" containing: "x = 1 + 1"
Output: []
Explanation: If the file contains no linting errors, the output is an empty list.

Example 3: (Edge Case)

Input: File path: "nonexistent_file.py"
Output: { "code": -32000, "message": "Pylint not installed." }
Explanation: If pylint is not installed, the server should return an error response with a code and a descriptive message.

Constraints

  • Python Version: Python 3.7 or higher.
  • Dependencies: pylint (installable via pip). You may use other libraries for LSP communication (e.g., python-lsp-server, pygls).
  • Performance: The server should respond to requests within a reasonable timeframe (e.g., under 2 seconds for moderately sized files). While optimization is not the primary focus, avoid excessively slow operations.
  • LSP Version: LSP 3.17 or later.
  • File Size: Assume files are less than 1MB.

Notes

  • You don't need to implement the entire LSP specification. Focus on the core diagnostic functionality.
  • Consider using a library like python-lsp-server or pygls to simplify LSP communication. These libraries handle much of the protocol boilerplate.
  • The pylint output format can be complex. You'll need to parse it carefully to extract the relevant information (file path, line number, column number, message, severity).
  • Start with a simple example file and gradually increase the complexity.
  • Think about how to handle different pylint severity levels and map them to the LSP severity levels (Error, Warning, Info, Hint, etc.).
  • Error messages from pylint might contain extra information. Focus on extracting the core message and location.
Loading editor...
python