mirror of
https://github.com/enso-org/enso.git
synced 2024-12-27 02:51:35 +03:00
d1af25793a
Use the Rust parser rather than the Scala parser to parse Enso code in the IDE. Implements: - https://www.pivotaltracker.com/story/show/182975925 - https://www.pivotaltracker.com/story/show/182988419 - https://www.pivotaltracker.com/story/show/182970096 - https://www.pivotaltracker.com/story/show/182973659 - https://www.pivotaltracker.com/story/show/182974161 - https://www.pivotaltracker.com/story/show/182974205 There is additional functionality needed before the transition is fully-completed, however I think it's time for this to see review and testing, so I've opened separate issues. In rough order of urgency (these issues are also linked from the corresponding disabled tests): - #5573 - #5571 - #5572 - #5574 # Important Notes The implementation is based partly on translation, and partly on new analysis. Method- and operator-related shapes are translated to the old `Ast` variants, so that all the analysis applied to them doesn't need to be ported at this time. Everything else (mostly "macros" in the old AST) is implemented with new analysis.
136 lines
4.2 KiB
Rust
136 lines
4.2 KiB
Rust
//! This build script is responsible for ensuring that if parser targets wasm,
|
|
//! the JS Parser package is available at the expected location for
|
|
//! `wasm_bindgen` tool.
|
|
|
|
// === Features ===
|
|
#![feature(option_result_contains)]
|
|
|
|
use ide_ci::prelude::*;
|
|
|
|
|
|
|
|
// =========================
|
|
// == Hardcoded constants ==
|
|
// =========================
|
|
|
|
/// Where the crate expects to find file with compiled parser.
|
|
/// Path relative to the crate directory.
|
|
const PARSER_PATH: &str = "./pkg/scala-parser.js";
|
|
|
|
/// Commit from `enso` repository that will be used to obtain parser from.
|
|
const PARSER_COMMIT: &str = "649fe33ccf148d47deb6ba6a06f3babc48078e3e";
|
|
|
|
/// Magic code that needs to be prepended to ScalaJS generated parser due to:
|
|
/// https://github.com/scala-js/scala-js/issues/3677/
|
|
const PARSER_PREAMBLE: &str = "var __ScalaJSEnv = { global: window };";
|
|
|
|
/// Obtains a URL where this parser version can be downloaded.
|
|
pub fn parser_url(version: &ParserVersion) -> reqwest::Url {
|
|
let url_string = format!(
|
|
"https://packages.luna-lang.org/parser-js/nightly/{}/scala-parser.js",
|
|
version.commit
|
|
);
|
|
let invalid_url_msg = format!("{url_string} is an invalid URL.");
|
|
reqwest::Url::parse(&url_string).expect(&invalid_url_msg)
|
|
}
|
|
|
|
|
|
|
|
// ===================
|
|
// == ParserVersion ==
|
|
// ===================
|
|
|
|
/// Parser version described as commit hash from `enso` repository.
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct ParserVersion {
|
|
pub commit: String,
|
|
}
|
|
|
|
impl ParserVersion {
|
|
/// Create a version described by given commit hash.
|
|
pub fn from_commit(commit: String) -> ParserVersion {
|
|
ParserVersion { commit }
|
|
}
|
|
|
|
/// The JS parser version required for this crate.
|
|
pub fn required() -> ParserVersion {
|
|
ParserVersion { commit: PARSER_COMMIT.into() }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ========================
|
|
// == Downloading parser ==
|
|
// ========================
|
|
|
|
/// Stores information which parser version should be provided where.
|
|
///
|
|
/// Implementation provides methods that download desired parser version, patch it and store to the
|
|
/// file, so parser can be consumed by `wasm_bindgen`.
|
|
struct ParserProvider {
|
|
/// Required parser version.
|
|
version: ParserVersion,
|
|
/// The path where JS file needs to be provided.
|
|
parser_path: PathBuf,
|
|
}
|
|
|
|
impl ParserProvider {
|
|
/// Creates a provider that obtains given parser version to a given path.
|
|
pub fn new(version: ParserVersion, parser_path: impl AsRef<Path>) -> ParserProvider {
|
|
let parser_path = PathBuf::from(parser_path.as_ref());
|
|
ParserProvider { version, parser_path }
|
|
}
|
|
|
|
/// Downloads contents of JS parser into memory.
|
|
pub async fn download(&self) -> Result<Bytes> {
|
|
let url = parser_url(&self.version);
|
|
ide_ci::io::download_all(url.clone()).await.context("Failed to download the parser.")
|
|
}
|
|
|
|
/// Stores JS parser into file, after patching with a `PARSER_PREAMBLE`.
|
|
pub async fn patch_and_store(&self, js_parser: bytes::Bytes) -> Result {
|
|
ide_ci::fs::tokio::write_iter(&self.parser_path, [
|
|
PARSER_PREAMBLE.as_bytes(),
|
|
js_parser.as_ref(),
|
|
])
|
|
.await
|
|
}
|
|
|
|
/// Places required parser version in the target location.
|
|
pub async fn run(&self) -> Result {
|
|
let fingerprint = self.parser_path.with_file_name("parser.fingerprint");
|
|
let opt_version = ide_ci::fs::tokio::read_to_string(&fingerprint).await;
|
|
let changed = match opt_version {
|
|
Err(_) => true,
|
|
Ok(hash) => hash != PARSER_COMMIT,
|
|
};
|
|
if changed {
|
|
let parser_js = self.download().await?;
|
|
self.patch_and_store(parser_js).await?;
|
|
ide_ci::fs::tokio::write(&fingerprint, PARSER_COMMIT).await?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ==========
|
|
// == main ==
|
|
// ==========
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result {
|
|
if ide_ci::programs::cargo::build_env::targeting_wasm() {
|
|
let required_version = ParserVersion::required();
|
|
let parser_path = Path::new(PARSER_PATH).absolutize()?;
|
|
let provider = ParserProvider::new(required_version, &parser_path);
|
|
provider.run().await?;
|
|
}
|
|
println!("cargo:rerun-if-changed=build.rs");
|
|
println!("cargo:rerun-if-changed={PARSER_PATH}");
|
|
|
|
Ok(())
|
|
}
|