Last active
September 12, 2024 16:20
-
-
Save pickx/ae3bd64b88681c8f2960961a061c5f7e to your computer and use it in GitHub Desktop.
Patch Pylance's VSCode check
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env -S cargo +nightly -Zscript --quiet | |
--- | |
[package] | |
edition = "2021" | |
[dependencies] | |
eyre = "0.6.12" | |
home = "0.5.9" | |
--- | |
use eyre::OptionExt; | |
use std::fs; | |
use std::io::Write; | |
use std::path::PathBuf; | |
const COMMENT_START: &str = "/*"; | |
const COMMENT_END: &str = "*/"; | |
fn file_path() -> eyre::Result<PathBuf> { | |
let home_dir = home::home_dir() | |
.filter(|dir| !dir.as_os_str().is_empty()) | |
.ok_or_eyre("could not fetch home dir")?; | |
let extensions_dir = home_dir.join(".vscode-oss/extensions"); | |
let pylance_dir = fs::read_dir(extensions_dir)? | |
.filter_map(|entry| { | |
let entry = entry.ok()?; | |
let ty = entry.file_type().ok()?; | |
let file_name = entry.file_name(); | |
if ty.is_dir() && file_name.to_str()?.starts_with("ms-python.vscode-pylance") { | |
Some(entry) | |
} else { | |
None | |
} | |
}) | |
.max_by_key(|entry| { | |
let create_time = entry.metadata().and_then(|metadata| metadata.created()); | |
create_time.ok() // `None` will always be ordered lower than `Some(time)` | |
}) | |
.ok_or_eyre("no pylance dirs found in VSCodium extension dir")? | |
.path(); | |
Ok(pylance_dir.join("dist/extension.bundle.js")) | |
} | |
fn pattern_start_and_end(s: &str) -> eyre::Result<(usize, usize)> { | |
let (start, end) = | |
find_pattern_delimiters(s).ok_or_eyre("expected pattern not found in file")?; | |
if s[..start].ends_with(COMMENT_START) || s[end..].starts_with(COMMENT_END) { | |
eyre::bail!("file already has comments at expected positions") | |
} | |
Ok((start, end)) | |
} | |
fn find_pattern_delimiters(s: &str) -> Option<(usize, usize)> { | |
let anchor = "disposables"; | |
let pattern_start = "return(0x0"; | |
let pattern_end = "};"; | |
s.match_indices(anchor) | |
.filter_map(|(start_of_anchor, _)| { | |
let end = start_of_anchor + s[start_of_anchor..].find(pattern_end)? + pattern_end.len(); | |
let start = s[..start_of_anchor].rfind(pattern_start)?; | |
Some((start, end)) | |
}) | |
.min_by_key(|(start, end)| end - start) | |
} | |
fn write_commented_out( | |
src: &[u8], | |
start: usize, | |
end: usize, | |
mut dst: impl Write, | |
) -> eyre::Result<()> { | |
dst.write_all(&src[..start])?; | |
dst.write_all(COMMENT_START.as_bytes())?; | |
dst.write_all(&src[start..end])?; | |
dst.write_all(COMMENT_END.as_bytes())?; | |
dst.write_all(&src[end..])?; | |
Ok(()) | |
} | |
fn main() -> eyre::Result<()> { | |
let file_path = file_path()?; | |
println!("found Pylance file to patch: {}", file_path.display()); | |
let content = fs::read_to_string(&file_path)?; | |
let (start, end) = pattern_start_and_end(&content)?; | |
let file = fs::File::create(&file_path)?; | |
write_commented_out(content.as_bytes(), start, end, file)?; | |
println!("file patched successfully!"); | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment