You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've created two small reproducer scripts in Python and JavaScript.
They show the same behavior:
Python
# %%importjsonfromsubprocessimportPopen, PIPEimportrefromtypingimportAnyimportuuidfrompathlibimportPath# Path to the Rust Analyzer executable and the file to analyzerust_analyzer_path="rust-analyzer"file_path=Path("src/main.rs").absolute()
defextract_content_length(response: str) ->int:
# Split the response into lineslines=response.split("\r\n")
# Find the line that starts with "Content-Length:"content_length_line=next(
(lineforlineinlinesifline.startswith("Content-Length:")), None
)
ifcontent_length_lineisnotNone:
# Extract the number from the line using a regular expressionmatch=re.search(r"Content-Length: (\d+)", content_length_line)
ifmatch:
returnint(match.group(1))
else:
raiseValueError("No number found in Content-Length line")
else:
raiseValueError("No Content-Length line found")
defsend_request(server: Popen, request: dict[str, Any]) ->Any:
send_notification(server, request)
returnreceive_response(server)
defreceive_response(server: Popen) ->Any:
response=""assertserver.stdoutisnotNonewhilenotresponse.endswith("\r\n\r\n"):
response+=server.stdout.read(1).decode()
content_length=extract_content_length(response)
returnjson.loads(server.stdout.read(content_length).decode())
defsend_notification(server: Popen, request: dict[str, Any]) ->None:
request_json=json.dumps(request)
header=f"Content-Length: {len(request_json.encode())}\r\n\r\n"assertserver.stdinisnotNoneserver.stdin.write(header.encode())
server.stdin.write(request_json.encode())
server.stdin.flush()
# %%# Start the Rust Analyzer serverserver=Popen(
[rust_analyzer_path],
stdin=PIPE,
stdout=PIPE,
)
# %%# Initialize the LSP clientinitialize_params: dict[str, Any] = {
"processId": None,
"capabilities": {},
"initializationOptions": {"checkOnSave": {"enable": False}},
"rootUri": f"file://{file_path.parent}",
}
initalize_request_id=uuid.uuid4()
initialize_request= {
"jsonrpc": "2.0",
"id": str(initalize_request_id),
"method": "initialize",
"params": initialize_params,
}
result=send_request(server, initialize_request)
print(result)
# %%send_notification(server, {"jsonrpc": "2.0", "method": "initialized"})
# # %%# # Send textDocument/didOpen notificationdid_open_params= {
"textDocument": {
"uri": f"file://{file_path}",
"languageId": "rust",
"version": 1,
"text": file_path.read_text(),
}
}
did_open_notification= {
"jsonrpc": "2.0",
"method": "textDocument/didOpen",
"params": did_open_params,
}
send_notification(server, did_open_notification)
# %%result=receive_response(server)
print(result)
# %%# Send textDocument/didChange notificationdid_change_params= {
"textDocument": {
"uri": f"file://{file_path}",
"version": 2,
},
"contentChanges": [
{
"text": file_path.read_text(),
}
],
}
did_change_notification= {
"jsonrpc": "2.0",
"method": "textDocument/didChange",
"params": did_change_params,
}
send_notification(server, did_change_notification)
# %%result=receive_response(server)
print(result)
# %%exit_request=json.dumps(
{
"jsonrpc": "2.0",
"method": "exit",
}
)
send_notification(server, exit_request)
server.terminate()
NodeJs
const{ spawn }=require('child_process');constpath=require('path');// Path to the Rust Analyzer executable and the file to analyzeconstrustAnalyzerPath='rust-analyzer';constfilePath=path.resolve('src/main.rs');// Start the Rust Analyzer serverconstserver=spawn(rustAnalyzerPath,[],{stdio: ['pipe','pipe',process.stderr]});// Function to send a JSON-RPC request to the serverfunctionsendRequest(method,params,id){constrequest=JSON.stringify({jsonrpc: '2.0', method, params, id });constcontentLength=Buffer.byteLength(request,'utf8');server.stdin.write(`Content-Length: ${contentLength}\r\n\r\n${request}`);}// Function to send a JSON-RPC notification to the serverfunctionsendNotification(method,params){constnotification=JSON.stringify({jsonrpc: '2.0', method, params });constcontentLength=Buffer.byteLength(notification,'utf8');server.stdin.write(`Content-Length: ${contentLength}\r\n\r\n${notification}`);}// Initialize the LSP clientsendRequest('initialize',{processId: process.pid,rootPath: path.dirname(filePath),rootUri: `file://${path.dirname(filePath)}`,capabilities: {},},1);// Send the initialized notificationsendNotification('initialized',{});// Open the filesendNotification('textDocument/didOpen',{textDocument: {uri: `file://${filePath}`,languageId: 'rust',version: 1,text: require('fs').readFileSync(filePath,'utf8'),},});// Read the server's responsesserver.stdout.on('data',(data)=>{console.log('Server response:',data.toString());});// Keep the Node.js process runningsetInterval(()=>{},1000);
Activity
Add Rust analyzer support (#868)
Hofer-Julian commentedon Feb 14, 2024
I've created two small reproducer scripts in Python and JavaScript.
They show the same behavior:
Python
NodeJs
Hofer-Julian commentedon Feb 14, 2024
This is the communication between vscode and r-a (see https://rust-analyzer.github.io/manual.html#troubleshooting)
vscode-ra-communication.txt
Support analysis / types with Rust Analyzer