Skip to content

Commit

Permalink
Merge branch 'develop' into wip/vitvakatu/gui2-top-bar
Browse files Browse the repository at this point in the history
  • Loading branch information
somebody1234 committed Sep 26, 2023
2 parents c0971da + f8c4f9e commit b720369
Show file tree
Hide file tree
Showing 106 changed files with 7,055 additions and 711 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,7 @@
- [Support runtime checks of intersection types][7769]
- [Merge `Small_Integer` and `Big_Integer` types][7636]
- [Inline type ascriptions][7796]
- [Always persist `TRACE` level logs to a file][7825]
- [Downloadable VSCode extension][7861]
- [New `project/status` route for reporting LS state][7801]

Expand Down Expand Up @@ -1106,6 +1107,7 @@
[7636]: https://github.com/enso-org/enso/pull/7636
[7796]: https://github.com/enso-org/enso/pull/7796
[7801]: https://github.com/enso-org/enso/pull/7801
[7825]: https://github.com/enso-org/enso/pull/7825
[7861]: https://github.com/enso-org/enso/pull/7861

# Enso 2.0.0-alpha.18 (2021-10-12)
Expand Down
13 changes: 10 additions & 3 deletions app/gui/language/span-tree/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,21 @@ impl<'a> Implementation for node::Ref<'a> {
let mut inserted_positional_placeholder_at = None;
let new_ast = modify_preserving_id(ast, |ast| {
if let Some(mut infix) = extended_infix {
let item = ArgWithOffset { arg: new, offset: DEFAULT_OFFSET };
let has_target = infix.target.is_some();
let has_arg = infix.args.last().unwrap().operand.is_some();
let offset = infix
.enumerate_non_empty_operands()
.last()
.map_or(DEFAULT_OFFSET, |op| op.offset);
let last_elem = infix.args.last_mut().unwrap();
let item = ArgWithOffset { arg: new, offset };
let has_target = infix.target.is_some();
last_elem.offset = DEFAULT_OFFSET;
match kind {
ExpectedTarget => infix.target = Some(item),
BeforeArgument(0 | 1) if !has_target => infix.target = Some(item),
BeforeArgument(idx) => infix.insert_operand(*idx, item),
Append if has_arg => infix.push_operand(item),
Append => last_elem.operand = Some(item),
Append | ExpectedOperand => last_elem.operand = Some(item),
ExpectedArgument { .. } => unreachable!(
"Expected arguments should be filtered out before this if block"
),
Expand Down Expand Up @@ -183,6 +188,8 @@ impl<'a> Implementation for node::Ref<'a> {
};
prefix.args.push(item)
}
ExpectedTarget | ExpectedOperand =>
unreachable!("Wrong insertion point in method call"),
}
Ok(prefix.into_ast())
}
Expand Down
91 changes: 87 additions & 4 deletions app/gui/language/span-tree/src/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,12 @@ fn generate_node_for_opr_chain(
let node = target.arg.generate_node(kind, context)?;
Ok((node, target.offset))
}
None => Ok((Node::new().with_kind(InsertionPointType::BeforeArgument(0)), 0)),
None => {
let application_id = this.args.first().and_then(|app| app.infix_id);
let port_id =
application_id.map(|application| PortId::ArgPlaceholder { application, index: 0 });
Ok((Node::new().with_kind(InsertionPointType::ExpectedTarget).with_port_id(port_id), 0))
}
};

// In this fold we pass last generated node and offset after it, wrapped in Result.
Expand All @@ -448,6 +453,7 @@ fn generate_node_for_opr_chain(
let is_first = i == 0;
let is_last = i + 1 == this.args.len();
let has_left = !node.is_insertion_point();
let has_right = elem.operand.is_some();
let opr_crumbs = elem.crumb_to_operator(has_left);
let opr_ast = Located::new(opr_crumbs, elem.operator.ast());
let left_crumbs = if has_left { vec![elem.crumb_to_previous()] } else { vec![] };
Expand Down Expand Up @@ -477,7 +483,7 @@ fn generate_node_for_opr_chain(
}
}

let infix_right_argument_info = if !app_base.uses_method_notation {
let mut infix_right_argument_info = if !app_base.uses_method_notation {
app_base.set_call_id(elem.infix_id);
app_base.resolve(context).and_then(|mut resolved| {
// For resolved infix arguments, the arity should always be 2. First always
Expand Down Expand Up @@ -515,13 +521,21 @@ fn generate_node_for_opr_chain(
};
let argument = gen.generate_ast_node(arg_ast, argument_kind, context)?;

if let Some((index, info)) = infix_right_argument_info {
if let Some((index, info)) = infix_right_argument_info.take() {
argument.node.set_argument_info(info);
argument.node.set_definition_index(index);
}
} else if !app_base.uses_method_notation {
let argument = gen.generate_empty_node(InsertionPointType::ExpectedOperand);
argument.port_id =
elem.infix_id.map(|application| PortId::ArgPlaceholder { application, index: 1 });
if let Some((index, info)) = infix_right_argument_info.take() {
argument.node.set_argument_info(info);
argument.node.set_definition_index(index);
}
}

if is_last && !app_base.uses_method_notation {
if is_last && has_right && !app_base.uses_method_notation {
gen.generate_empty_node(InsertionPointType::Append);
}

Expand Down Expand Up @@ -1387,6 +1401,75 @@ mod test {
.build();
clear_expression_ids(&mut tree.root);
clear_parameter_infos(&mut tree.root);
assert_eq!(tree, expected)
}

#[test]
fn generate_span_tree_for_unfinished_infix() {
let parser = Parser::new();
let this_param = |call_id| ArgumentInfo {
name: Some("self".to_owned()),
tp: Some("Any".to_owned()),
call_id,
..default()
};
let param1 = |call_id| ArgumentInfo {
name: Some("arg1".to_owned()),
tp: Some("Number".to_owned()),
call_id,
..default()
};


// === SectionLeft ===
let mut id_map = IdMap::default();
let call_id = id_map.generate(0..2);
let ast = parser.parse_line_ast_with_id_map("2+", id_map).unwrap();
let invocation_info =
CalledMethodInfo { parameters: vec![this_param(ast.id), param1(ast.id)], ..default() };
let ctx = MockContext::new_single(ast.id.unwrap(), invocation_info);
let mut tree: SpanTree = SpanTree::new(&ast, &ctx).unwrap();
match tree.root_ref().leaf_iter().collect_vec().as_slice() {
[_before, arg0, _opr, arg1] => {
assert_eq!(arg0.argument_info(), Some(&this_param(Some(call_id))));
assert_eq!(arg1.argument_info(), Some(&param1(Some(call_id))));
}
sth_else => panic!("There should be 4 leaves, found: {}", sth_else.len()),
}
let expected = TreeBuilder::new(2)
.add_empty_child(0, BeforeArgument(0))
.add_leaf(0, 1, node::Kind::argument().indexed(0), SectionLeftCrumb::Arg)
.add_leaf(1, 1, node::Kind::Operation, SectionLeftCrumb::Opr)
.add_empty_child(2, ExpectedOperand)
.build();
clear_expression_ids(&mut tree.root);
clear_parameter_infos(&mut tree.root);
assert_eq!(tree, expected);


// === SectionRight ===
let mut id_map = IdMap::default();
let call_id = id_map.generate(0..2);
let ast = parser.parse_line_ast_with_id_map("+2", id_map).unwrap();
let invocation_info =
CalledMethodInfo { parameters: vec![this_param(ast.id), param1(ast.id)], ..default() };
let ctx = MockContext::new_single(ast.id.unwrap(), invocation_info);
let mut tree: SpanTree = SpanTree::new(&ast, &ctx).unwrap();
match tree.root_ref().leaf_iter().collect_vec().as_slice() {
[arg0, _opr, arg1, _append] => {
assert_eq!(arg0.argument_info(), Some(&this_param(Some(call_id))));
assert_eq!(arg1.argument_info(), Some(&param1(Some(call_id))));
}
sth_else => panic!("There should be 4 leaves, found: {}", sth_else.len()),
}
let expected = TreeBuilder::new(2)
.add_empty_child(0, ExpectedTarget)
.add_leaf(0, 1, node::Kind::Operation, SectionRightCrumb::Opr)
.add_leaf(1, 1, node::Kind::argument().indexed(1), SectionRightCrumb::Arg)
.add_empty_child(2, Append)
.build();
clear_expression_ids(&mut tree.root);
clear_parameter_infos(&mut tree.root);
assert_eq!(tree, expected);
}

Expand Down
9 changes: 9 additions & 0 deletions app/gui/language/span-tree/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,18 @@ impl Node {
pub fn is_positional_insertion_point(&self) -> bool {
self.kind.is_positional_insertion_point()
}

pub fn is_expected_argument(&self) -> bool {
self.kind.is_expected_argument()
}

pub fn is_expected_operand(&self) -> bool {
self.kind.is_expected_operand()
}

pub fn is_placeholder(&self) -> bool {
self.is_expected_argument() || self.is_expected_operand()
}
}


Expand Down
17 changes: 16 additions & 1 deletion app/gui/language/span-tree/src/node/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,25 @@ impl Kind {
/// Match the value with `Kind::InsertionPoint{..}` but not
/// `Kind::InsertionPoint(ExpectedArgument(_))`.
pub fn is_positional_insertion_point(&self) -> bool {
self.is_insertion_point() && !self.is_expected_argument()
self.is_insertion_point() && !self.is_expected_argument() && !self.is_expected_operand()
}

/// Match the value with `Kind::InsertionPoint(ExpectedArgument(_))`.
pub fn is_expected_argument(&self) -> bool {
matches!(self, Self::InsertionPoint(t) if t.kind.is_expected_argument())
}

/// Check if given kind is an insertino point for expected operand of an unfinished infix.
pub fn is_expected_operand(&self) -> bool {
matches!(
self,
Self::InsertionPoint(InsertionPoint {
kind: InsertionPointType::ExpectedOperand | InsertionPointType::ExpectedTarget,
..
})
)
}

/// Match the argument in a prefix method application.
pub fn is_prefix_argument(&self) -> bool {
matches!(self, Self::Argument(a) if a.in_prefix_chain)
Expand Down Expand Up @@ -374,6 +385,10 @@ pub enum InsertionPointType {
index: usize,
named: bool,
},
/// Expected target of unfinished infix expression.
ExpectedTarget,
/// Expected operand of unfinished infix expression.
ExpectedOperand,
}

// === Matchers ===
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1651,7 +1651,7 @@ impl<'a> TreeBuilder<'a> {
let ptr_usage = self.pointer_usage.entry(main_ptr).or_default();
let widget_id = main_ptr.to_identity(ptr_usage);

let is_placeholder = span_node.is_expected_argument();
let is_placeholder = span_node.is_expected_argument() || span_node.is_expected_operand();
let sibling_offset = span_node.sibling_offset.as_usize();
let usage_type = span_node.ast_id.and_then(|id| self.usage_type_map.get(&id)).cloned();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl SpanWidget for Widget {
}

fn configure(&mut self, _: &Config, ctx: ConfigContext) {
let is_placeholder = ctx.span_node.is_expected_argument();
let is_placeholder = ctx.span_node.is_placeholder();

let expr = ctx.span_expression();
let content = if is_placeholder || ctx.info.connection.is_some() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ impl SpanWidget for Widget {
type Config = Config;

fn match_node(ctx: &ConfigContext) -> Score {
let is_placeholder = ctx.span_node.is_expected_argument();
let is_placeholder = ctx.span_node.is_placeholder();
let decl_type = ctx.span_node.kind.tp().map(|t| t.as_str());

let first_decl_is_vector =
Expand Down
1 change: 1 addition & 0 deletions app/gui2/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dist
dist-ssr
coverage
*.local
*.tsbuildinfo

# Editor directories and files
.vscode/*
Expand Down
6 changes: 6 additions & 0 deletions app/gui2/env.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/// <reference types="vite/client" />

declare const PROJECT_MANAGER_URL: string

// This is an augmentation to the built-in `ImportMeta` interface.
// This file MUST NOT contain any top-level imports.
interface ImportMeta {
vitest: typeof import('vitest') | undefined
}
2 changes: 1 addition & 1 deletion app/gui2/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<title>Enso GUI</title>
</head>
<body>
<div id="app"></div>
Expand Down
6 changes: 6 additions & 0 deletions app/gui2/node.env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ module 'tailwindcss/nesting' {
declare const plugin: PluginCreator<unknown>
export default plugin
}

// This is an augmentation to the built-in `ImportMeta` interface.
// This file MUST NOT contain any top-level imports.
interface ImportMeta {
vitest: typeof import('vitest') | undefined
}
16 changes: 16 additions & 0 deletions app/gui2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,41 @@
"preinstall": "npm run build-rust-ffi"
},
"dependencies": {
"@babel/parser": "^7.22.16",
"@open-rpc/client-js": "^1.8.1",
"@vueuse/core": "^10.4.1",
"codemirror": "^6.0.1",
"enso-authentication": "^1.0.0",
"install": "^0.13.0",
"hash-sum": "^2.0.0",
"isomorphic-ws": "^5.0.0",
"lib0": "^0.2.83",
"magic-string": "^0.30.3",
"pinia": "^2.1.6",
"postcss-inline-svg": "^6.0.0",
"postcss-nesting": "^12.0.1",
"sha3": "^2.1.4",
"sucrase": "^3.34.0",
"vue": "^3.3.4",
"vue-codemirror": "^6.1.1",
"ws": "^8.13.0",
"y-codemirror.next": "^0.3.2",
"y-protocols": "^1.0.5",
"y-textarea": "^1.0.0",
"y-websocket": "^1.5.0",
"yjs": "^13.6.7"
},
"devDependencies": {
"@danmarshall/deckgl-typings": "^4.9.28",
"@eslint/eslintrc": "^2.1.2",
"@eslint/js": "^8.49.0",
"@playwright/test": "^1.37.0",
"@rushstack/eslint-patch": "^1.3.2",
"@tsconfig/node18": "^18.2.0",
"@types/d3": "^7.4.0",
"@types/hash-sum": "^1.0.0",
"@types/jsdom": "^21.1.1",
"@types/mapbox-gl": "^2.7.13",
"@types/node": "^18.17.5",
"@types/shuffle-seed": "^1.1.0",
"@types/ws": "^8.5.5",
Expand All @@ -54,6 +67,8 @@
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/test-utils": "^2.4.1",
"@vue/tsconfig": "^0.4.0",
"ag-grid-community": "^30.1.0",
"ag-grid-enterprise": "^30.1.0",
"esbuild": "^0.19.3",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.16.1",
Expand All @@ -62,6 +77,7 @@
"prettier": "^3.0.0",
"prettier-plugin-organize-imports": "^3.2.3",
"shuffle-seed": "^1.1.6",
"sql-formatter": "^13.0.0",
"tailwindcss": "^3.2.7",
"typescript": "~5.2.2",
"vite": "^4.4.9",
Expand Down
Loading

0 comments on commit b720369

Please sign in to comment.