Skip to content

Commit

Permalink
Allow visualizations to define context module for preprocessor (enso-…
Browse files Browse the repository at this point in the history
  • Loading branch information
mwu-tow authored Mar 10, 2021
1 parent 7a15cdf commit 63dec53
Show file tree
Hide file tree
Showing 31 changed files with 618 additions and 391 deletions.
6 changes: 6 additions & 0 deletions ide/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
unnecessary library imports when selecting hints from node searcher. This
makes the generated textual code easier to read and reduces likelihood of
accidental name collision.
- [Visualizations can define context for preprocessor evaluation][1291]. Users
can now decide what module's context should be used for visualization
preprocessor. This allows providing visualization with standard library
functionalities or defining utilities that are shared between multiple
visualizations.

#### EnsoGL (rendering engine)

Expand All @@ -24,6 +29,7 @@ you can find their release notes
[here](https://github.com/enso-org/enso/blob/main/RELEASES.md).

[1209]: https://github.com/enso-org/ide/pull/1209
[1291]: https://github.com/enso-org/ide/pull/1291

<br/>

Expand Down
203 changes: 113 additions & 90 deletions ide/docs/product/visualizations.md

Large diffs are not rendered by default.

33 changes: 17 additions & 16 deletions ide/src/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ide/src/rust/ide/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ enso-args = { path = "lib/args" }
enso-callback = { path = "../lib/callback" }
enso-data = { version = "0.1.4" }
enso-frp = { path = "../lib/frp" }
enso-logger = { version = "0.2.2" }
enso-logger = { version = "0.2.3" }
enso-prelude = { version = "0.1.10" }
enso-shapely = { version = "0.1.4" }
ensogl = { path = "../ensogl" }
Expand All @@ -36,7 +36,7 @@ console_error_panic_hook = { version = "0.1.6" }
failure = { version = "0.1.6" }
flo_stream = { version = "0.4.0" }
futures = { version = "0.3.1" }
itertools = { version = "0.8.1" }
itertools = { version = "0.10.0" }
js-sys = { version = "0.3.28" }
mockall = { version = "0.7.1", features = ["nightly"] }
nalgebra = { version = "0.21.1", features = ["serde-serialize"] }
Expand Down
4 changes: 2 additions & 2 deletions ide/src/rust/ide/src/controller/graph/executed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ impl Handle {
/// Modify preprocessor code in visualization. See also
/// [`model::ExecutionContext::modify_visualization`].
pub async fn set_visualization_preprocessor
(&self, id:VisualizationId, code:String) -> FallibleResult {
self.execution_ctx.modify_visualization(id,Some(code),None).await
(&self, id:VisualizationId, code:String, module:model::module::QualifiedName) -> FallibleResult {
self.execution_ctx.modify_visualization(id,Some(code),Some(module)).await
}

/// Subscribe to updates about changes in this executed graph.
Expand Down
51 changes: 33 additions & 18 deletions ide/src/rust/ide/src/controller/visualization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use crate::prelude::*;
use crate::constants::VISUALIZATION_DIRECTORY;

use enso_protocol::language_server;
use ide_view::graph_editor::data::enso;
use ide_view::graph_editor::component::visualization::definition;
use ide_view::graph_editor::component::visualization;
use std::rc::Rc;
Expand All @@ -22,14 +21,30 @@ use std::rc::Rc;
/// Enumeration of errors used in `Visualization Controller`.
#[derive(Debug,Fail)]
#[allow(missing_docs)]
pub enum VisualizationError {
pub enum Error {
#[fail(display = "Visualization \"{}\" not found.", identifier)]
NotFound {
identifier : VisualizationPath
identifier:VisualizationPath
},
#[fail(display = "JavaScript visualization \"{}\" failed to be prepared.", identifier)]
Preparation {
identifier:VisualizationPath,
#[cause]
cause:failure::Error,
},
#[fail(display = "JavaScript visualization \"{}\" failed to be instantiated.", identifier)]
InstantiationError {
identifier : VisualizationPath
Instantiation {
identifier:VisualizationPath
},
}

impl Error {
/// Construct a new error regarding visualization preparation.
pub fn js_preparation_error
(identifier:VisualizationPath, error:visualization::foreign::java_script::definition::Error)
-> Self {
let cause = failure::format_err!("{}",error);
Self::Preparation {identifier,cause}
}
}

Expand Down Expand Up @@ -130,21 +145,18 @@ impl Handle {
let embedded_visualizations = self.embedded_visualizations.borrow();
let result = embedded_visualizations.get(identifier);
let identifier = visualization.clone();
let error = || VisualizationError::NotFound{identifier}.into();
let error = || Error::NotFound{identifier}.into();
result.cloned().ok_or_else(error)
},
VisualizationPath::File(path) => {
let project = visualization::path::Project::CurrentProject;
let js_code = self.language_server_rpc.read_file(&path).await?.contents;
let identifier = visualization.clone();
let error = |_| VisualizationError::InstantiationError {identifier}.into();
// FIXME: provide real library name. The name set here is discarded anyway in
// [`ide::integration::Model::prepare_visualization`] and set the Main of the
// current project. All those should be fixed in
// https://github.com/enso-org/ide/issues/1167
let module = enso::builtin_library();
// TODO: this is wrong. This is translated to InstantiationError and it is preparation error :
let js_class = visualization::java_script::Definition::new(module,&js_code).map_err(error);
js_class.map(|t| t.into())
let wrap_error = |err| {
Error::js_preparation_error(visualization.clone(),err).into()
};
visualization::java_script::Definition::new(project,&js_code)
.map(Into::into)
.map_err(wrap_error)
}
}
}
Expand All @@ -164,6 +176,7 @@ mod tests {
use enso_protocol::language_server::Path;
use ide_view::graph_editor::builtin;
use ide_view::graph_editor::component::visualization;
use ide_view::graph_editor::component::visualization::java_script as js_vis;
use json_rpc::expect_call;

use wasm_bindgen_test::wasm_bindgen_test_configure;
Expand All @@ -173,6 +186,7 @@ mod tests {

#[wasm_bindgen_test(async)]
async fn list_and_load() {

let mock_client = language_server::MockClient::default();

let root_id = uuid::Uuid::default();
Expand Down Expand Up @@ -226,8 +240,9 @@ mod tests {
assert_eq!(visualizations[2], VisualizationPath::File(path1));
assert_eq!(visualizations.len(),3);

let javascript_vis0 = visualization::java_script::Definition::new("builtin", &file_content0);
let javascript_vis1 = visualization::java_script::Definition::new("builtin", &file_content1);
let owner = visualization::Project::CurrentProject;
let javascript_vis0 = js_vis::Definition::new(owner.clone_ref(),&file_content0);
let javascript_vis1 = js_vis::Definition::new(owner,&file_content1);
let javascript_vis0 = javascript_vis0.expect("Couldn't create visualization class.");
let javascript_vis1 = javascript_vis1.expect("Couldn't create visualization class.");
let javascript_vis0:visualization::Definition = javascript_vis0.into();
Expand Down
14 changes: 14 additions & 0 deletions ide/src/rust/ide/src/double_representation/identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,20 @@ impl AsRef<str> for ReferentName {
}
}

impl TryFrom<&str> for ReferentName {
type Error = NotReferentName;
fn try_from(value:&str) -> Result<Self,Self::Error> {
Self::new(value)
}
}

impl TryFrom<String> for ReferentName {
type Error = NotReferentName;
fn try_from(value:String) -> Result<Self,Self::Error> {
Self::new(value)
}
}

impl From<ReferentName> for String {
fn from(name:ReferentName) -> Self {
name.0
Expand Down
10 changes: 9 additions & 1 deletion ide/src/rust/ide/src/double_representation/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,18 @@ impl QualifiedName {
QualifiedName {project_name,id}
}

/// Create a qualified name for the project's main module.
///
/// It is special, as its name consists only from the project name, unlike other modules'
/// qualified names.
pub fn new_main(project_name:ReferentName) -> QualifiedName {
Self::new(project_name, Id::new(std::iter::empty()))
}

/// Constructs a qualified name from its text representation.
///
/// Fails, if the text is not a valid module's qualified name.
pub fn from_text(text:impl Str) -> FallibleResult<Self> {
pub fn from_text(text:impl AsRef<str>) -> FallibleResult<Self> {
use ast::opr::predefined::ACCESS;

let text = text.as_ref();
Expand Down
Loading

0 comments on commit 63dec53

Please sign in to comment.