mirror of
https://github.com/enso-org/enso.git
synced 2024-12-24 10:53:34 +03:00
Assign IDs to all nodes but few. (https://github.com/enso-org/ide/pull/425)
Original commit: 9ee7f25a9d
This commit is contained in:
parent
d65e813541
commit
963ebfc382
@ -1845,20 +1845,21 @@ mod tests {
|
||||
// === Match ===
|
||||
|
||||
fn match_() -> Match<Ast> {
|
||||
let var = Ast::var("");
|
||||
let pat = Rc::new(MacroPatternRaw::Nothing(MacroPatternRawNothing{}));
|
||||
let tok = Rc::new(MacroPatternMatchRaw::Tok(MacroPatternMatchRawTok{
|
||||
pat : MacroPatternRawTok{spaced:None, ast:Ast::var("")},
|
||||
elem : Shifted{off:0,wrapped:Ast::var("")},
|
||||
pat : MacroPatternRawTok{spaced:None, ast:var.clone()},
|
||||
elem : Shifted{off:0,wrapped:var.clone()},
|
||||
}));
|
||||
let body = Rc::new(MacroPatternMatchRaw::Seq(MacroPatternMatchRawSeq{
|
||||
pat : MacroPatternRawSeq{pat1:pat.clone(),pat2:pat.clone()},
|
||||
elem : (tok.clone(),tok.clone()),
|
||||
}));
|
||||
let segs = ShiftedVec1 {
|
||||
head : MacroMatchSegment{head:Ast::var(""),body:body.clone()},
|
||||
head : MacroMatchSegment{head:var.clone(),body:body.clone()},
|
||||
tail : vec![]
|
||||
};
|
||||
Match{pfx:Some(body),segs,resolved:Ast::var("")}
|
||||
Match{pfx:Some(body),segs,resolved:var.clone()}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1897,21 +1898,22 @@ mod tests {
|
||||
let crumb6 = MatchCrumb::Segs{val:SegmentMatchCrumb::Body{val:crumb1},index:0};
|
||||
let crumb7 = MatchCrumb::Segs{val:SegmentMatchCrumb::Body{val:crumb2},index:0};
|
||||
let match1 = match_();
|
||||
let match2 = match1.set(&crumb3,Ast::var("X")).unwrap();
|
||||
let match3 = match2.set(&crumb5,Ast::var("Y")).unwrap();
|
||||
let match4 = match3.set(&crumb7,Ast::var("Z")).unwrap();
|
||||
let ast = [match1.resolved.clone(), Ast::var("X"), Ast::var("Y"), Ast::var("Z")];
|
||||
let match2 = match1.set(&crumb3,ast[1].clone()).unwrap();
|
||||
let match3 = match2.set(&crumb5,ast[2].clone()).unwrap();
|
||||
let match4 = match3.set(&crumb7,ast[3].clone()).unwrap();
|
||||
|
||||
assert_eq!(match1.get(&crumb3).unwrap(),&Ast::var(""));
|
||||
assert_eq!(match1.get(&crumb4).unwrap(),&Ast::var(""));
|
||||
assert_eq!(match1.get(&crumb5).unwrap(),&Ast::var(""));
|
||||
assert_eq!(match1.get(&crumb6).unwrap(),&Ast::var(""));
|
||||
assert_eq!(match1.get(&crumb7).unwrap(),&Ast::var(""));
|
||||
assert_eq!(match1.get(&crumb3).unwrap(),&ast[0]);
|
||||
assert_eq!(match1.get(&crumb4).unwrap(),&ast[0]);
|
||||
assert_eq!(match1.get(&crumb5).unwrap(),&ast[0]);
|
||||
assert_eq!(match1.get(&crumb6).unwrap(),&ast[0]);
|
||||
assert_eq!(match1.get(&crumb7).unwrap(),&ast[0]);
|
||||
|
||||
assert_eq!(match4.get(&crumb3).unwrap(),&Ast::var("X"));
|
||||
assert_eq!(match4.get(&crumb4).unwrap(),&Ast::var(""));
|
||||
assert_eq!(match4.get(&crumb5).unwrap(),&Ast::var("Y"));
|
||||
assert_eq!(match4.get(&crumb6).unwrap(),&Ast::var(""));
|
||||
assert_eq!(match4.get(&crumb7).unwrap(),&Ast::var("Z"));
|
||||
assert_eq!(match4.get(&crumb3).unwrap(),&ast[1]);
|
||||
assert_eq!(match4.get(&crumb4).unwrap(),&ast[0]);
|
||||
assert_eq!(match4.get(&crumb5).unwrap(),&ast[2]);
|
||||
assert_eq!(match4.get(&crumb6).unwrap(),&ast[0]);
|
||||
assert_eq!(match4.get(&crumb7).unwrap(),&ast[3]);
|
||||
|
||||
}
|
||||
|
||||
|
@ -91,11 +91,20 @@ where for<'t> &'t Shape<Ast> : TryInto<&'t T,Error=E> {
|
||||
}
|
||||
|
||||
impl<T:Into<Shape<Ast>>> KnownAst<T> {
|
||||
/// Creates a new `KnownAst<T>` from `shape`.
|
||||
/// Creates a new `KnownAst<T>` from `shape` with random ID if id=None.
|
||||
pub fn new(shape:T, id:Option<crate::Id>) -> KnownAst<T> {
|
||||
let ast = Ast::new(shape,id);
|
||||
Self::new_unchecked(ast)
|
||||
}
|
||||
|
||||
/// Creates a new `KnownAst<T>` from `shape` with no ID.
|
||||
/// Should be only used on nodes that can't have ID because of scala AST design.
|
||||
/// Example: Module, Section.opr, MacroMatchSegment.head
|
||||
/// Tracking issue: https://github.com/luna/ide/issues/434
|
||||
pub fn new_no_id(shape:T) -> KnownAst<T> {
|
||||
let ast = Ast::new_no_id(shape);
|
||||
Self::new_unchecked(ast)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T,E> Deref for KnownAst<T>
|
||||
|
@ -231,28 +231,35 @@ impl Ast {
|
||||
self
|
||||
}
|
||||
|
||||
/// Wraps given shape with an optional ID into Ast.
|
||||
/// Wraps given shape with ID into Ast with random ID if id=None.
|
||||
/// Length will ba automatically calculated based on Shape.
|
||||
/// This constructor shouldn't be used for AST that can't have ID because of scala AST design.
|
||||
/// For more info see `Ast::new_no_id`
|
||||
pub fn new<S:Into<Shape<Ast>>>(shape:S, id:Option<Id>) -> Ast {
|
||||
let shape: Shape<Ast> = shape.into();
|
||||
let shape = shape.into();
|
||||
let id = id.unwrap_or_else(Id::new_v4);
|
||||
let length = shape.len();
|
||||
Ast::new_with_length(shape,id,length)
|
||||
Ast::from_ast_id_len(shape,Some(id),length)
|
||||
}
|
||||
|
||||
/// Wraps given shape without ID into Ast.
|
||||
/// Length will ba automatically calculated based on Shape.
|
||||
/// Should be only used on nodes that can't have ID because of scala AST design.
|
||||
/// Example: Module, Section.opr, MacroMatchSegment.head.
|
||||
/// Tracking issue: https://github.com/luna/ide/issues/434
|
||||
pub fn new_no_id<S:Into<Shape<Ast>>>(shape:S) -> Ast {
|
||||
let shape = shape.into();
|
||||
let length = shape.len();
|
||||
Ast::from_ast_id_len(shape,None,length)
|
||||
}
|
||||
|
||||
/// Just wraps shape, id and len into Ast node.
|
||||
pub fn from_ast_id_len(shape:Shape<Ast>, id:Option<Id>, len:usize) -> Ast {
|
||||
fn from_ast_id_len(shape:Shape<Ast>, id:Option<Id>, len:usize) -> Ast {
|
||||
let with_length = WithLength { wrapped:shape , len };
|
||||
let with_id = WithID { wrapped:with_length, id };
|
||||
Ast { wrapped: Rc::new(with_id) }
|
||||
}
|
||||
|
||||
/// As `new` but sets given declared length for the shape.
|
||||
pub fn new_with_length<S:Into<Shape<Ast>>>
|
||||
(shape:S, id:Option<Id>, len:usize) -> Ast {
|
||||
let shape = shape.into();
|
||||
Self::from_ast_id_len(shape,id,len)
|
||||
}
|
||||
|
||||
/// Iterates over all transitive child nodes (including self).
|
||||
pub fn iter_recursive(&self) -> impl Iterator<Item=&Ast> {
|
||||
internal::iterate_subtree(self)
|
||||
@ -260,7 +267,7 @@ impl Ast {
|
||||
|
||||
/// Returns this AST node with ID set to given value.
|
||||
pub fn with_id(&self, id:Id) -> Ast {
|
||||
Ast::from_ast_id_len(self.shape().clone(), Some(id), self.len())
|
||||
Ast::new(self.shape().clone(), Some(id))
|
||||
}
|
||||
|
||||
/// Returns this AST node with a newly generated unique ID.
|
||||
@ -272,11 +279,6 @@ impl Ast {
|
||||
pub fn with_shape<S:Into<Shape<Ast>>>(&self, shape:S) -> Ast {
|
||||
Ast::new(shape.into(),self.id)
|
||||
}
|
||||
|
||||
/// Returns this AST node with removed ID.
|
||||
pub fn without_id(&self) -> Ast {
|
||||
Ast::from_ast_id_len(self.shape().clone(), None, self.len())
|
||||
}
|
||||
}
|
||||
|
||||
/// Fills `id` with `None` by default.
|
||||
@ -348,7 +350,7 @@ impl<'de> Visitor<'de> for AstDeserializationVisitor {
|
||||
let shape = shape.ok_or_else(|| serde::de::Error::missing_field(SHAPE))?;
|
||||
let id = id.unwrap_or(None); // allow missing `id` field
|
||||
let len = len.ok_or_else(|| serde::de::Error::missing_field(LENGTH))?;
|
||||
Ok(Ast::new_with_length(shape,id,len))
|
||||
Ok(Ast::from_ast_id_len(shape,id,len))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1366,9 +1368,9 @@ mod tests {
|
||||
fn ast_updating_id() {
|
||||
let var = Var {name:"foo".into()};
|
||||
let ast = Ast::new(var, None);
|
||||
assert!(ast.id.is_none());
|
||||
assert!(ast.id.is_some());
|
||||
|
||||
let id = Uuid::default();
|
||||
let id = Id::default();
|
||||
let ast = ast.with_id(id);
|
||||
assert_eq!(ast.id, Some(id));
|
||||
}
|
||||
@ -1414,7 +1416,7 @@ mod tests {
|
||||
let ident = "foo".to_string();
|
||||
let v = Var{ name: ident.clone() };
|
||||
let ast = Ast::from(v);
|
||||
assert_eq!(ast.wrapped.id, None);
|
||||
assert!(ast.wrapped.id.is_some());
|
||||
assert_eq!(ast.wrapped.wrapped.len, ident.len());
|
||||
}
|
||||
|
||||
@ -1426,7 +1428,7 @@ mod tests {
|
||||
let ast_without_id = Ast::new(make_var(), None);
|
||||
round_trips(&ast_without_id);
|
||||
|
||||
let id = Uuid::parse_str("15").ok();
|
||||
let id = Id::parse_str("15").ok();
|
||||
let ast_with_id = Ast::new(make_var(), id);
|
||||
round_trips(&ast_with_id);
|
||||
}
|
||||
@ -1444,7 +1446,7 @@ mod tests {
|
||||
let sample_json_text = sample_json.to_string();
|
||||
let ast: Ast = serde_json::from_str(&sample_json_text).unwrap();
|
||||
|
||||
let expected_uuid = Uuid::parse_str(uuid_str).ok();
|
||||
let expected_uuid = Id::parse_str(uuid_str).ok();
|
||||
assert_eq!(ast.id, expected_uuid);
|
||||
|
||||
let expected_length = 3;
|
||||
|
@ -25,7 +25,7 @@ use std::path::PathBuf;
|
||||
const PARSER_PATH: &str = "./pkg/scala-parser.js";
|
||||
|
||||
/// Commit from `enso` repository that will be used to obtain parser from.
|
||||
const PARSER_COMMIT: &str = "9238c6b9c1d19760529ac63da8a9f9dec5d024c6";
|
||||
const PARSER_COMMIT: &str = "81bde2858900e61fcab4138dc8881757a0787dfa";
|
||||
|
||||
/// Magic code that needs to be prepended to ScalaJS generated parser due to:
|
||||
/// https://github.com/scala-js/scala-js/issues/3677/
|
||||
|
@ -42,7 +42,7 @@ fn to_json_single_line
|
||||
|
||||
impl<M:Metadata> TryFrom<&SourceFile<M>> for String {
|
||||
type Error = serde_json::Error;
|
||||
fn try_from(val:&SourceFile<M>) -> std::result::Result<String,Self::Error> {
|
||||
fn try_from(val:&SourceFile<M>) -> std::result::Result<Self,Self::Error> {
|
||||
let code = val.ast.repr();
|
||||
let ids = to_json_single_line(&val.ast.id_map())?;
|
||||
let meta = to_json_single_line(&val.metadata)?;
|
||||
|
@ -66,7 +66,7 @@ impl Fixture {
|
||||
|
||||
fn deserialize_metadata(&mut self) {
|
||||
let term = ast::Module {lines: vec![ast::BlockLine {elem:None,off:0}]};
|
||||
let ast = known::Module::new(term,None);
|
||||
let ast = known::KnownAst::new_no_id(term);
|
||||
let file = SourceFile {ast, metadata: serde_json::json!({})};
|
||||
let code = String::try_from(&file).unwrap();
|
||||
assert_eq!(self.parser.parse_with_metadata(code).unwrap(), file);
|
||||
|
@ -1,6 +1,7 @@
|
||||
use enso_prelude::*;
|
||||
|
||||
use ast::Ast;
|
||||
use ast::HasRepr;
|
||||
use ast::IdMap;
|
||||
use data::text::*;
|
||||
use parser::Parser;
|
||||
@ -20,33 +21,24 @@ fn web_test() {
|
||||
|
||||
let parser = Parser::new_or_panic();
|
||||
|
||||
let parse = |input:&str| {
|
||||
let span = Span::from_beginning(Size::new(input.len()));
|
||||
let ids = IdMap::new(vec![(span,uuid)]);
|
||||
let ast = parser.parse(String::from(input), ids).unwrap().wrapped;
|
||||
let parse = |input| parser.parse_with_metadata(input).unwrap();
|
||||
let file = |term|
|
||||
SourceFile{metadata:serde_json::json!({}), ast:ast::known::KnownAst::new_no_id(term)};
|
||||
|
||||
match Rc::try_unwrap(ast).unwrap().wrapped.wrapped {
|
||||
ast::Shape::Module(ast) => ast,
|
||||
_ => panic!("Expected module."),
|
||||
}
|
||||
};
|
||||
|
||||
let line = |term| {
|
||||
ast::Module {lines: vec![ast::BlockLine {elem:term,off:0}]}
|
||||
};
|
||||
|
||||
let app_x_y = ast::Prefix {func: Ast::var("x"), off: 3, arg: Ast::var("y")};
|
||||
let var_xy = ast::Var {name:"xy".into()};
|
||||
assert_eq!(parse(""), line(None));
|
||||
assert_eq!(parse("xy"), line(Some(Ast::new(var_xy, Some(uuid)))));
|
||||
assert_eq!(parse("x y"), line(Some(Ast::new(app_x_y, Some(uuid)))));
|
||||
let app = ast::Prefix{func:Ast::var("x"), off:3, arg:Ast::var("y")};
|
||||
let var = ast::Var{name:"x".into()};
|
||||
|
||||
let deserialize_metadata = || {
|
||||
let ast = ast::known::Module::new(line(None), None);
|
||||
let file = SourceFile {ast, metadata: serde_json::json!({})};
|
||||
let code = String::try_from(&file).unwrap();
|
||||
assert_eq!(parser.parse_with_metadata(code).unwrap(), file);
|
||||
};
|
||||
let ast = file(line(None));
|
||||
assert_eq!(parse(String::try_from(&ast).unwrap()), ast);
|
||||
|
||||
deserialize_metadata()
|
||||
let ast = file(line(Some(Ast::new(var,Some(uuid)))));
|
||||
assert_eq!(parse(String::try_from(&ast).unwrap()), ast);
|
||||
|
||||
let ast = file(line(Some(Ast::new(app,Some(uuid)))));
|
||||
assert_eq!(parse(String::try_from(&ast).unwrap()), ast);
|
||||
}
|
||||
|
@ -274,14 +274,16 @@ mod test {
|
||||
let uuid1 = Uuid::new_v4();
|
||||
let uuid2 = Uuid::new_v4();
|
||||
let uuid3 = Uuid::new_v4();
|
||||
let uuid4 = Uuid::new_v4();
|
||||
let module = "2+2";
|
||||
let id_map = ast::IdMap::new(vec!
|
||||
[ (Span::new(Index::new(0),Size::new(1)),uuid1.clone())
|
||||
, (Span::new(Index::new(2),Size::new(1)),uuid2)
|
||||
, (Span::new(Index::new(0),Size::new(3)),uuid3)
|
||||
[ (Span::new(Index::new(0),Size::new(1)),uuid1)
|
||||
, (Span::new(Index::new(1),Size::new(1)),uuid2)
|
||||
, (Span::new(Index::new(2),Size::new(1)),uuid3)
|
||||
, (Span::new(Index::new(0),Size::new(3)),uuid4)
|
||||
]);
|
||||
|
||||
let controller = Handle::new_mock(location,module,id_map,ls,parser).unwrap();
|
||||
let controller = Handle::new_mock(location,module,id_map,ls,parser).unwrap();
|
||||
|
||||
let mut text_notifications = controller.model.subscribe_text_notifications();
|
||||
let mut graph_notifications = controller.model.subscribe_graph_notifications();
|
||||
@ -289,18 +291,18 @@ mod test {
|
||||
// Change code from "2+2" to "22+2"
|
||||
let change = TextChange::insert(Index::new(1),"2".to_string());
|
||||
controller.apply_code_change(&change).unwrap();
|
||||
let expected_ast = Ast::new(ast::Module {
|
||||
let expected_ast = Ast::new_no_id(ast::Module {
|
||||
lines: vec![BlockLine {
|
||||
elem: Some(Ast::new(ast::Infix {
|
||||
larg : Ast::new(ast::Number{base:None, int:"22".to_string()}, Some(uuid1)),
|
||||
loff : 0,
|
||||
opr : Ast::new(ast::Opr {name:"+".to_string()}, None),
|
||||
opr : Ast::new(ast::Opr {name:"+".to_string()}, Some(uuid2)),
|
||||
roff : 0,
|
||||
rarg : Ast::new(ast::Number{base:None, int:"2".to_string()}, Some(uuid2)),
|
||||
}, Some(uuid3))),
|
||||
rarg : Ast::new(ast::Number{base:None, int:"2".to_string()}, Some(uuid3)),
|
||||
}, Some(uuid4))),
|
||||
off: 0
|
||||
}]
|
||||
}, None);
|
||||
});
|
||||
assert_eq!(expected_ast, controller.model.ast().into());
|
||||
|
||||
// Check emitted notifications
|
||||
|
Loading…
Reference in New Issue
Block a user