Recover from invalid metadata (#3982)

If corrupt metadata is encountered in a source file, log an error and continue without metadata.

See: https://www.pivotaltracker.com/story/show/184030897
This commit is contained in:
Kaz Wesley 2022-12-15 09:36:31 -08:00 committed by GitHub
parent 01f8e2976d
commit 4d2668003f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 4 deletions

View File

@ -59,7 +59,10 @@ pub extern "system" fn Java_org_enso_syntax2_Parser_parseInput(
let mut code = input;
let mut meta = None;
if let Some((meta_, code_)) = enso_parser::metadata::parse(input) {
meta = Some(meta_);
match meta_ {
Ok(meta_) => meta = Some(meta_),
Err(e) => error!("Ignoring invalid metadata: {e}."),
}
code = code_;
}
state.base = str::as_ptr(code) as usize as u64;
@ -73,7 +76,7 @@ pub extern "system" fn Java_org_enso_syntax2_Parser_parseInput(
default()
}
};
state.metadata = meta.and_then(|meta| meta.ok());
state.metadata = meta;
let result = env.new_direct_byte_buffer(&mut state.output);
result.unwrap().into_inner()
}

View File

@ -7,6 +7,8 @@ use std::collections::BTreeMap;
use std::str::FromStr;
use uuid::Uuid;
const MARKER: &str = "#### METADATA ####\n";
// ================
@ -46,7 +48,7 @@ impl From<MetadataFormat> for Metadata {
/// Given source code, if a metadata section is found: Attempt to parse it; return the result, and
/// the non-metadata portion of the input.
pub fn parse(input: &str) -> Option<(Result, &str)> {
let (code, metadata) = input.rsplit_once("#### METADATA ####\n")?;
let (code, metadata) = input.rsplit_once(MARKER)?;
Some((metadata.parse().map(|data: MetadataFormat| data.into()), code))
}
@ -57,7 +59,8 @@ impl FromStr for MetadataFormat {
type Err = String;
fn from_str(s: &str) -> Result<MetadataFormat> {
let mut lines = s.lines();
let id_map = serde_json::from_str(lines.next().unwrap()).unwrap();
let line0 = lines.next().ok_or("Expected a value.")?;
let id_map = serde_json::from_str(line0).map_err(|e| e.to_string())?;
Ok(MetadataFormat { id_map })
}
}
@ -78,3 +81,19 @@ struct Location {
struct Number {
value: usize,
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn bad_metadata() {
MetadataFormat::from_str(MARKER).expect_err("Empty metadata is error.");
MetadataFormat::from_str("[ , ]").expect_err("Invalid JSON is error.");
}
#[test]
fn empty_metadata() {
MetadataFormat::from_str("[]").expect("Empty sequence is valid.");
}
}