mirror of
https://github.com/enso-org/enso.git
synced 2024-11-25 21:25:20 +03:00
Drop-down widgets for extension functions via UnresolvedSymbol (#7115)
Fixes #6955 by: - using `visualisationModule` to specify the module where the visualization is to be used - referring to method in `Meta.get_annotation` with `.method_name` - e.g. unresolved symbol notation - evaluating arguments to `Meta.get_annotation` in the context of the user module (which can access the extension functions)
This commit is contained in:
parent
22259e696d
commit
477dd82670
@ -434,6 +434,7 @@ fn test_execution_context() {
|
||||
};
|
||||
let positional_arguments_expressions = vec![1, 2, 3].iter().map(|x| x.to_string()).collect();
|
||||
let visualization_config = VisualizationConfiguration {
|
||||
visualization_module: "Foo.Bar.Baz".to_string(),
|
||||
execution_context_id: context_id,
|
||||
expression,
|
||||
positional_arguments_expressions,
|
||||
@ -453,6 +454,7 @@ fn test_execution_context() {
|
||||
"definedOnType" : "[Foo.Bar.Baz]",
|
||||
"name" : "foo"
|
||||
},
|
||||
"visualizationModule" : "Foo.Bar.Baz",
|
||||
"positionalArgumentsExpressions" : ["1", "2", "3"]
|
||||
}
|
||||
}),
|
||||
@ -479,6 +481,7 @@ fn test_execution_context() {
|
||||
};
|
||||
let positional_arguments_expressions = vec!["foo"].iter().map(|x| x.to_string()).collect();
|
||||
let visualization_config = VisualizationConfiguration {
|
||||
visualization_module: "Foo.Bar.Baz".to_string(),
|
||||
execution_context_id: context_id,
|
||||
expression,
|
||||
positional_arguments_expressions,
|
||||
@ -495,6 +498,7 @@ fn test_execution_context() {
|
||||
"definedOnType" : "[Foo.Bar.Baz]",
|
||||
"name" : "foo"
|
||||
},
|
||||
"visualizationModule" : "Foo.Bar.Baz",
|
||||
"positionalArgumentsExpressions" : ["foo"]
|
||||
}
|
||||
}),
|
||||
|
@ -713,6 +713,8 @@ pub type ExpressionId = Uuid;
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[allow(missing_docs)]
|
||||
pub struct VisualizationConfiguration {
|
||||
/// Module to evaluate visualization in context of.
|
||||
pub visualization_module: String,
|
||||
/// An execution context of the visualization.
|
||||
pub execution_context_id: ContextId,
|
||||
/// An enso function that will transform the data into expected format.
|
||||
|
@ -403,10 +403,19 @@ impl Handle {
|
||||
}
|
||||
|
||||
|
||||
/// Get a fully qualified name of the module in the [`graph`]. The name is obtained from the
|
||||
/// module's path and the `project` name.
|
||||
pub fn module_qualified_name_with_project(
|
||||
&self,
|
||||
project: &dyn model::project::API,
|
||||
) -> QualifiedName {
|
||||
self.graph().module.path().qualified_module_name(project.qualified_name())
|
||||
}
|
||||
|
||||
/// Get a full qualified name of the module in the [`graph`]. The name is obtained from the
|
||||
/// module's path and the `project` name.
|
||||
pub fn module_qualified_name(&self, project: &dyn model::project::API) -> QualifiedName {
|
||||
self.graph().module.path().qualified_module_name(project.qualified_name())
|
||||
pub fn module_qualified_name(&self) -> QualifiedName {
|
||||
self.graph().module.path().qualified_module_name(self.project.qualified_name())
|
||||
}
|
||||
|
||||
/// Returns information about all the connections between graph's nodes.
|
||||
|
@ -392,7 +392,7 @@ impl QueryData {
|
||||
/// Generate visualization metadata for this query.
|
||||
fn visualization_metadata(&self) -> Metadata {
|
||||
let arguments: Vec<Code> = vec![
|
||||
Self::escape_visualization_argument(&self.method_name).into(),
|
||||
Self::as_unresolved_symbol(&self.method_name).into(),
|
||||
Self::arg_sequence(&self.arguments).into(),
|
||||
];
|
||||
|
||||
@ -410,6 +410,12 @@ impl QueryData {
|
||||
Ast::raw_text_literal(arg).repr()
|
||||
}
|
||||
|
||||
/// Creates unresolved symbol via ".name" syntax. Unresolved symbol contains name and also
|
||||
/// module scope to resolve it properly.
|
||||
fn as_unresolved_symbol(arg: &str) -> String {
|
||||
format!(".{arg}")
|
||||
}
|
||||
|
||||
/// Escape a list of strings to be used as a visualization argument. Transforms the strings into
|
||||
/// an enso expression with a list of string literals.
|
||||
fn arg_sequence(args: &[ImString]) -> String {
|
||||
|
@ -574,7 +574,7 @@ impl Searcher {
|
||||
"Standard.Visualization.AI",
|
||||
"build_ai_prompt",
|
||||
)?;
|
||||
let vis = Visualization::new(this.id, vis_ptr, vec![]);
|
||||
let vis = Visualization::new(vis_ptr.module.to_owned(), this.id, vis_ptr, vec![]);
|
||||
let mut result = graph.attach_visualization(vis.clone()).await?;
|
||||
let next = result.next().await.ok_or(NoAIVisualizationDataReceived)?;
|
||||
let prompt = std::str::from_utf8(&next)?;
|
||||
@ -1091,7 +1091,7 @@ impl Searcher {
|
||||
}
|
||||
|
||||
fn module_qualified_name(&self) -> QualifiedName {
|
||||
self.graph.module_qualified_name(&*self.project)
|
||||
self.graph.module_qualified_name_with_project(&*self.project)
|
||||
}
|
||||
|
||||
fn filter(&self) -> Filter {
|
||||
|
@ -10,6 +10,7 @@ use crate::model::execution_context::VisualizationId;
|
||||
use crate::model::execution_context::VisualizationUpdateData;
|
||||
use crate::sync::Synchronized;
|
||||
|
||||
use double_representation::name::QualifiedName;
|
||||
use futures::channel::mpsc::UnboundedReceiver;
|
||||
use futures::future::ready;
|
||||
use ide_view::graph_editor::component::visualization::Metadata;
|
||||
@ -158,6 +159,7 @@ impl Default for Status {
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Desired {
|
||||
pub module: QualifiedName,
|
||||
pub visualization_id: VisualizationId,
|
||||
pub expression_id: ast::Id,
|
||||
pub metadata: Metadata,
|
||||
@ -285,8 +287,12 @@ impl Manager {
|
||||
// Early return: requested to remove visualization that was already removed.
|
||||
return;
|
||||
};
|
||||
let prj = self.executed_graph.module_qualified_name();
|
||||
let graph = self.executed_graph.graph();
|
||||
let module = prj.new_child(graph.module.name());
|
||||
let current_id = current.as_ref().and_then(|current| current.latest_id());
|
||||
let new_desired = new_desired.map(|new_desired| Desired {
|
||||
module,
|
||||
expression_id: target,
|
||||
visualization_id: current_id.unwrap_or_else(VisualizationId::new_v4),
|
||||
metadata: new_desired,
|
||||
@ -332,6 +338,7 @@ impl Manager {
|
||||
Ok(Visualization {
|
||||
id: desired.visualization_id,
|
||||
expression_id: desired.expression_id,
|
||||
module: desired.module,
|
||||
method_pointer,
|
||||
arguments,
|
||||
})
|
||||
@ -556,13 +563,14 @@ mod tests {
|
||||
let qualified_module = inner.project.qualified_module_name(inner.module.path());
|
||||
let method_pointer = QualifiedMethodPointer {
|
||||
module: qualified_module.clone(),
|
||||
defined_on_type: qualified_module,
|
||||
defined_on_type: qualified_module.clone(),
|
||||
name: Identifier::from_text("faux").unwrap(),
|
||||
};
|
||||
let arguments = vec!["foo".to_owned()];
|
||||
let faux_vis = Visualization {
|
||||
id: default(),
|
||||
expression_id: default(),
|
||||
module: qualified_module,
|
||||
method_pointer,
|
||||
arguments,
|
||||
};
|
||||
@ -666,6 +674,7 @@ mod tests {
|
||||
// We don't attach it separately, as Manager identifies visualizations by their
|
||||
// expression ID rather than visualization ID.
|
||||
let desired_vis_3 = Desired {
|
||||
module: QualifiedName::from_text("local.Widgets.Main").unwrap(),
|
||||
visualization_id: VisualizationId::from_u128(900),
|
||||
expression_id: node_id,
|
||||
metadata: desired_vis_1,
|
||||
|
@ -323,6 +323,8 @@ pub struct Visualization {
|
||||
pub id: VisualizationId,
|
||||
/// Expression that is to be visualized.
|
||||
pub expression_id: ExpressionId,
|
||||
/// Module to evaluate visualization in context of.
|
||||
pub module: QualifiedName,
|
||||
/// A pointer to the enso method that will transform the data into expected format.
|
||||
pub method_pointer: QualifiedMethodPointer,
|
||||
/// Enso expressions for positional arguments
|
||||
@ -333,12 +335,13 @@ impl Visualization {
|
||||
/// Creates a new visualization description. The visualization will get a randomly assigned
|
||||
/// identifier.
|
||||
pub fn new(
|
||||
module: QualifiedName,
|
||||
expression_id: ExpressionId,
|
||||
method_pointer: QualifiedMethodPointer,
|
||||
arguments: Vec<String>,
|
||||
) -> Visualization {
|
||||
let id = VisualizationId::new_v4();
|
||||
Visualization { id, expression_id, method_pointer, arguments }
|
||||
Visualization { id, expression_id, module, method_pointer, arguments }
|
||||
}
|
||||
|
||||
/// Creates a `VisualizationConfiguration` that is used in communication with language server.
|
||||
@ -346,6 +349,7 @@ impl Visualization {
|
||||
let expression = self.method_pointer.clone().into();
|
||||
let positional_arguments_expressions = self.arguments.clone();
|
||||
VisualizationConfiguration {
|
||||
visualization_module: self.module.to_string_with_main_segment(),
|
||||
execution_context_id,
|
||||
expression,
|
||||
positional_arguments_expressions,
|
||||
|
@ -532,6 +532,7 @@ pub mod test {
|
||||
let arguments = vec![];
|
||||
let vis = Visualization {
|
||||
id: model::execution_context::VisualizationId::new_v4(),
|
||||
module: method_pointer.module.clone(),
|
||||
expression_id: model::execution_context::ExpressionId::new_v4(),
|
||||
method_pointer,
|
||||
arguments,
|
||||
@ -581,6 +582,7 @@ pub mod test {
|
||||
let arguments = vec!["foo".to_owned()];
|
||||
let vis = Visualization {
|
||||
id: model::execution_context::VisualizationId::new_v4(),
|
||||
module: method_pointer.module.clone(),
|
||||
expression_id: model::execution_context::ExpressionId::new_v4(),
|
||||
method_pointer,
|
||||
arguments,
|
||||
@ -618,6 +620,7 @@ pub mod test {
|
||||
let arguments = vec!["bar".to_owned()];
|
||||
let vis = Visualization {
|
||||
id: model::execution_context::VisualizationId::new_v4(),
|
||||
module: method_pointer.module.clone(),
|
||||
expression_id: model::execution_context::ExpressionId::new_v4(),
|
||||
method_pointer,
|
||||
arguments: arguments.clone(),
|
||||
@ -634,6 +637,7 @@ pub mod test {
|
||||
|
||||
let expected_config = language_server::types::VisualizationConfiguration {
|
||||
execution_context_id: data.context_id,
|
||||
visualization_module: MockData::new().module_qualified_name().to_string(),
|
||||
expression: new_expression.clone().into(),
|
||||
positional_arguments_expressions: arguments.clone(),
|
||||
};
|
||||
|
@ -140,6 +140,7 @@ async fn ls_text_protocol_test() {
|
||||
execution_context_id,
|
||||
expression,
|
||||
positional_arguments_expressions,
|
||||
visualization_module: visualization_module.to_string(),
|
||||
};
|
||||
let response =
|
||||
client.attach_visualization(&visualization_id, &expression_id, &visualization_config);
|
||||
@ -157,6 +158,7 @@ async fn ls_text_protocol_test() {
|
||||
execution_context_id,
|
||||
expression,
|
||||
positional_arguments_expressions,
|
||||
visualization_module: visualization_module.to_string(),
|
||||
};
|
||||
let response = client.modify_visualization(&visualization_id, &visualization_config).await;
|
||||
response.expect("Couldn't modify visualization.");
|
||||
@ -375,7 +377,8 @@ async fn binary_visualization_updates_test_hlp() {
|
||||
module_qualified_name,
|
||||
Identifier::from_text("quux").unwrap(),
|
||||
);
|
||||
let visualization = Visualization::new(the_node.id(), method_pointer, vec![]);
|
||||
let visualization =
|
||||
Visualization::new(method_pointer.module.clone(), the_node.id(), method_pointer, vec![]);
|
||||
let stream = graph_executed.attach_visualization(visualization.clone()).await.unwrap();
|
||||
info!("Attached the visualization {}", visualization.id);
|
||||
let mut stream = stream.boxed_local();
|
||||
|
@ -419,10 +419,10 @@ type_of value = @Builtin_Method "Meta.type_of"
|
||||
|
||||
Arguments:
|
||||
- target: The value or type to get the attribute from.
|
||||
- method_name: The name of the method or constructor to get the attribute for.
|
||||
- method: The symbol representing method or constructor to get the attribute for.
|
||||
- parameter_name: The name of the parameter to get the attribute for.
|
||||
get_annotation : Any -> Text -> Text -> Any | Nothing
|
||||
get_annotation target method_name parameter_name = @Builtin_Method "Meta.get_annotation"
|
||||
get_annotation : Any -> Any -> Text -> Any | Nothing
|
||||
get_annotation target method parameter_name = @Builtin_Method "Meta.get_annotation"
|
||||
|
||||
## PRIVATE
|
||||
Represents a polyglot language.
|
||||
|
@ -4,7 +4,7 @@ from Standard.Base import all
|
||||
Basic preprocessor for widgets metadata visualization.
|
||||
|
||||
Returns full annotation data for all requested arguments.
|
||||
get_widget_json : Any -> Text -> Vector Text -> Text
|
||||
get_widget_json : Any -> Any -> Vector Text -> Text
|
||||
get_widget_json value call_name argument_names =
|
||||
read_annotation argument =
|
||||
annotation = Warning.clear <| Meta.get_annotation value call_name argument
|
||||
|
@ -453,10 +453,9 @@ interface VisualizationConfiguration {
|
||||
executionContextId: UUID;
|
||||
|
||||
/**
|
||||
* A qualified name of the module containing the expression which creates
|
||||
* visualization.
|
||||
* A qualified name of the module to be used to evaluate the arguments for the visualization expression.
|
||||
*/
|
||||
visualizationModule?: String;
|
||||
visualizationModule: String;
|
||||
|
||||
/** An expression that creates a visualization. */
|
||||
expression: String | MethodPointer;
|
||||
|
@ -12,16 +12,16 @@ import java.util.UUID
|
||||
*
|
||||
* @param executionContextId an execution context of the visualization
|
||||
* @param expression an expression that creates a visualization
|
||||
* @param visualizationModule the name of a module to execute expression at
|
||||
* @param executionContextId an execution context of the visualization
|
||||
* @param expression an expression that creates a visualization
|
||||
*/
|
||||
case class VisualizationConfiguration(
|
||||
executionContextId: UUID,
|
||||
expression: VisualizationExpression
|
||||
expression: VisualizationExpression,
|
||||
visualizationModule: String
|
||||
) extends ToLogString {
|
||||
|
||||
/** A qualified module name containing the expression. */
|
||||
def visualizationModule: String =
|
||||
expression.module
|
||||
|
||||
/** @inheritdoc */
|
||||
override def toLogString(shouldMask: Boolean): String =
|
||||
s"VisualizationConfiguration(" +
|
||||
@ -32,7 +32,8 @@ case class VisualizationConfiguration(
|
||||
def toApi: Api.VisualizationConfiguration =
|
||||
Api.VisualizationConfiguration(
|
||||
executionContextId = executionContextId,
|
||||
expression = expression.toApi
|
||||
expression = expression.toApi,
|
||||
visualizationModule = visualizationModule
|
||||
)
|
||||
|
||||
}
|
||||
@ -52,7 +53,8 @@ object VisualizationConfiguration {
|
||||
): VisualizationConfiguration =
|
||||
new VisualizationConfiguration(
|
||||
contextId,
|
||||
VisualizationExpression.Text(module, expression)
|
||||
VisualizationExpression.Text(module, expression),
|
||||
module
|
||||
)
|
||||
|
||||
/** Create a visualization configuration.
|
||||
@ -65,6 +67,7 @@ object VisualizationConfiguration {
|
||||
*/
|
||||
def apply(
|
||||
contextId: UUID,
|
||||
module: String,
|
||||
expression: MethodPointer,
|
||||
positionalArgumentsExpressions: Vector[String]
|
||||
): VisualizationConfiguration =
|
||||
@ -73,7 +76,8 @@ object VisualizationConfiguration {
|
||||
VisualizationExpression.ModuleMethod(
|
||||
expression,
|
||||
positionalArgumentsExpressions
|
||||
)
|
||||
),
|
||||
module
|
||||
)
|
||||
|
||||
private object CodecField {
|
||||
@ -99,11 +103,15 @@ object VisualizationConfiguration {
|
||||
expression <- cursor
|
||||
.downField(CodecField.Expression)
|
||||
.as[MethodPointer]
|
||||
visualizationModule <- cursor
|
||||
.downField(CodecField.VisualizationModule)
|
||||
.as[String]
|
||||
arguments <- cursor
|
||||
.downField(CodecField.Arguments)
|
||||
.as[Option[Vector[String]]]
|
||||
} yield VisualizationConfiguration(
|
||||
contextId,
|
||||
visualizationModule,
|
||||
expression,
|
||||
arguments.getOrElse(Vector())
|
||||
)
|
||||
|
@ -204,6 +204,7 @@ object ExecutionContextJsonMessages {
|
||||
"expressionId": $expressionId,
|
||||
"visualizationConfig": {
|
||||
"executionContextId": ${configuration.executionContextId},
|
||||
"visualizationModule": ${configuration.visualizationModule},
|
||||
"expression": {
|
||||
"module": ${methodPointer.module},
|
||||
"definedOnType": ${methodPointer.definedOnType},
|
||||
@ -223,6 +224,7 @@ object ExecutionContextJsonMessages {
|
||||
"expressionId": $expressionId,
|
||||
"visualizationConfig": {
|
||||
"executionContextId": ${configuration.executionContextId},
|
||||
"visualizationModule": ${methodPointer.module},
|
||||
"expression": {
|
||||
"module": ${methodPointer.module},
|
||||
"definedOnType": ${methodPointer.definedOnType},
|
||||
|
@ -66,6 +66,7 @@ class VisualizationOperationsTest extends BaseServerTest {
|
||||
val visualizationConfig =
|
||||
VisualizationConfiguration(
|
||||
contextId,
|
||||
visualizationModule,
|
||||
MethodPointer(
|
||||
visualizationModule,
|
||||
visualizationModule,
|
||||
@ -120,6 +121,7 @@ class VisualizationOperationsTest extends BaseServerTest {
|
||||
val visualizationConfig =
|
||||
VisualizationConfiguration(
|
||||
contextId,
|
||||
visualizationModule,
|
||||
MethodPointer(
|
||||
visualizationModule,
|
||||
visualizationModule,
|
||||
|
@ -615,21 +615,20 @@ object Runtime {
|
||||
*
|
||||
* @param executionContextId an execution context of the visualization
|
||||
* @param expression the expression that creates a visualization
|
||||
* @param visualizationModule module to evaluate arguments for visualization at
|
||||
*/
|
||||
case class VisualizationConfiguration(
|
||||
executionContextId: ContextId,
|
||||
expression: VisualizationExpression
|
||||
expression: VisualizationExpression,
|
||||
visualizationModule: String
|
||||
) extends ToLogString {
|
||||
|
||||
/** A qualified module name containing the expression. */
|
||||
def visualizationModule: String =
|
||||
expression.module
|
||||
|
||||
/** @inheritdoc */
|
||||
override def toLogString(shouldMask: Boolean): String =
|
||||
s"VisualizationConfiguration(" +
|
||||
s"executionContextId=$executionContextId," +
|
||||
s"expression=${expression.toLogString(shouldMask)})"
|
||||
s"expression=${expression.toLogString(shouldMask)})" +
|
||||
s"visualizationModule=${visualizationModule})"
|
||||
}
|
||||
|
||||
/** An operation applied to the suggestion argument. */
|
||||
|
@ -59,6 +59,7 @@ class UpsertVisualizationJob(
|
||||
try {
|
||||
val maybeCallable =
|
||||
UpsertVisualizationJob.evaluateVisualizationExpression(
|
||||
config.visualizationModule,
|
||||
config.expression
|
||||
)
|
||||
|
||||
@ -180,7 +181,10 @@ object UpsertVisualizationJob {
|
||||
val expressionId = visualization.expressionId
|
||||
val visualizationId = visualization.id
|
||||
val maybeCallable =
|
||||
evaluateVisualizationExpression(visualization.config.expression)
|
||||
evaluateVisualizationExpression(
|
||||
visualizationConfig.visualizationModule,
|
||||
visualizationConfig.expression
|
||||
)
|
||||
|
||||
maybeCallable.foreach { result =>
|
||||
updateVisualization(
|
||||
@ -215,8 +219,9 @@ object UpsertVisualizationJob {
|
||||
|
||||
/** Evaluate the visualization expression in a given module.
|
||||
*
|
||||
* @param module the module where to evaluate the expression
|
||||
* @param module the module where to evaluate arguments for the expression
|
||||
* @param expression the visualization expression
|
||||
* @param expressionModule the module where to evaluate the expression
|
||||
* @param retryCount the number of attempted retries
|
||||
* @param ctx the runtime context
|
||||
* @return either the evaluation result or an evaluation failure
|
||||
@ -224,6 +229,7 @@ object UpsertVisualizationJob {
|
||||
private def evaluateModuleExpression(
|
||||
module: Module,
|
||||
expression: Api.VisualizationExpression,
|
||||
expressionModule: Module,
|
||||
retryCount: Int = 0
|
||||
)(implicit
|
||||
ctx: RuntimeContext
|
||||
@ -233,7 +239,7 @@ object UpsertVisualizationJob {
|
||||
val (callback, arguments) = expression match {
|
||||
case Api.VisualizationExpression.Text(_, expression) =>
|
||||
val callback = ctx.executionService.evaluateExpression(
|
||||
module,
|
||||
expressionModule,
|
||||
expression
|
||||
)
|
||||
val arguments = Vector()
|
||||
@ -243,7 +249,7 @@ object UpsertVisualizationJob {
|
||||
argumentExpressions
|
||||
) =>
|
||||
val callback = ctx.executionService.prepareFunctionCall(
|
||||
module,
|
||||
expressionModule,
|
||||
QualifiedName.fromString(definedOnType).item,
|
||||
name
|
||||
)
|
||||
@ -261,7 +267,12 @@ object UpsertVisualizationJob {
|
||||
Level.FINE,
|
||||
s"Evaluation of visualization was interrupted. Retrying [${retryCount + 1}]."
|
||||
)
|
||||
evaluateModuleExpression(module, expression, retryCount + 1)
|
||||
evaluateModuleExpression(
|
||||
module,
|
||||
expression,
|
||||
expressionModule,
|
||||
retryCount + 1
|
||||
)
|
||||
|
||||
case error: ThreadInterruptedException =>
|
||||
val message =
|
||||
@ -297,18 +308,25 @@ object UpsertVisualizationJob {
|
||||
|
||||
/** Evaluate the visualization expression.
|
||||
*
|
||||
* @param module module to evaluate the expression arguments at
|
||||
* @param expression the visualization expression to evaluate
|
||||
* @param ctx the runtime context
|
||||
* @return either the evaluation result or an evaluation error
|
||||
*/
|
||||
private def evaluateVisualizationExpression(
|
||||
module: String,
|
||||
expression: Api.VisualizationExpression
|
||||
)(implicit
|
||||
ctx: RuntimeContext
|
||||
): Either[EvaluationFailure, EvaluationResult] = {
|
||||
for {
|
||||
module <- findModule(expression.module)
|
||||
expression <- evaluateModuleExpression(module, expression)
|
||||
module <- findModule(module)
|
||||
expressionModule <- findModule(expression.module)
|
||||
expression <- evaluateModuleExpression(
|
||||
module,
|
||||
expression,
|
||||
expressionModule
|
||||
)
|
||||
} yield expression
|
||||
}
|
||||
|
||||
|
@ -358,7 +358,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"x -> encode x"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -476,7 +477,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"x -> encode x"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -611,7 +613,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"x -> encode x"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -739,7 +742,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"encode"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -867,7 +871,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"encode"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -919,7 +924,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"encode"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1085,7 +1091,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"x -> encode x"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1123,7 +1130,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"x -> incAndEncode x"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1192,7 +1200,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"x -> encode x"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1356,7 +1365,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"encode"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1468,7 +1478,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"x -> encode x"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1506,7 +1517,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"x -> incAndEncode x"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1600,7 +1612,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Test.Undefined",
|
||||
"x -> x"
|
||||
)
|
||||
),
|
||||
"Test.Undefined"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1666,7 +1679,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Standard.Visualization.Main",
|
||||
"x -> x.default_visualization.to_text"
|
||||
)
|
||||
),
|
||||
"Standard.Visualization.Main"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1762,7 +1776,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Main",
|
||||
"Main.does_not_exist"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Main"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1843,7 +1858,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
moduleName,
|
||||
"x -> x.visualise_me"
|
||||
)
|
||||
),
|
||||
moduleName
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -1955,7 +1971,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Visualization",
|
||||
"inc_and_encode"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -2071,7 +2088,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
moduleName,
|
||||
"x -> x.catch_primitive _.to_text"
|
||||
)
|
||||
),
|
||||
moduleName
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -2170,7 +2188,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
moduleName,
|
||||
"x -> Panic.catch_primitive x caught_panic-> caught_panic.payload.to_text"
|
||||
)
|
||||
),
|
||||
moduleName
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -2302,7 +2321,8 @@ class RuntimeVisualizationsTest
|
||||
visualizationFunction
|
||||
),
|
||||
Vector()
|
||||
)
|
||||
),
|
||||
visualizationModule
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -2403,7 +2423,8 @@ class RuntimeVisualizationsTest
|
||||
visualizationFunction
|
||||
),
|
||||
Vector()
|
||||
)
|
||||
),
|
||||
visualizationModule
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -2500,7 +2521,8 @@ class RuntimeVisualizationsTest
|
||||
"incAndEncode"
|
||||
),
|
||||
Vector()
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -2628,7 +2650,8 @@ class RuntimeVisualizationsTest
|
||||
"incAndEncode"
|
||||
),
|
||||
Vector("2", "3")
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -2698,7 +2721,8 @@ class RuntimeVisualizationsTest
|
||||
"incAndEncode"
|
||||
),
|
||||
Vector("2", "4")
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -2801,7 +2825,8 @@ class RuntimeVisualizationsTest
|
||||
"incAndEncode"
|
||||
),
|
||||
Vector()
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Visualization"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -2963,7 +2988,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Main",
|
||||
"x -> x.to_text"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Main"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -3063,7 +3089,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Main",
|
||||
"x -> x.to_text"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Main"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -3191,7 +3218,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
"Enso_Test.Test.Main",
|
||||
"x -> x.to_text"
|
||||
)
|
||||
),
|
||||
"Enso_Test.Test.Main"
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -3308,7 +3336,8 @@ class RuntimeVisualizationsTest
|
||||
Api.VisualizationExpression.Text(
|
||||
moduleName,
|
||||
"x -> x.to_text"
|
||||
)
|
||||
),
|
||||
moduleName
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -1,24 +1,23 @@
|
||||
package org.enso.interpreter.node.expression.builtin.meta;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.BaseNode;
|
||||
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
|
||||
import org.enso.interpreter.node.expression.builtin.text.util.ExpectStringNode;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.callable.Annotation;
|
||||
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.data.Type;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.state.State;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Meta",
|
||||
name = "get_annotation",
|
||||
@ -39,16 +38,22 @@ public abstract class GetAnnotationNode extends BaseNode {
|
||||
@Cached ThunkExecutorNode thunkExecutorNode,
|
||||
@Cached ExpectStringNode expectStringNode,
|
||||
@Cached TypeOfNode typeOfNode) {
|
||||
String methodName = expectStringNode.execute(method);
|
||||
|
||||
Object targetTypeResult = typeOfNode.execute(target);
|
||||
if (targetTypeResult instanceof DataflowError error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (targetTypeResult instanceof Type targetType) {
|
||||
ModuleScope scope = targetType.getDefinitionScope();
|
||||
Function methodFunction = scope.lookupMethodDefinition(targetType, methodName);
|
||||
Function methodFunction;
|
||||
if (method instanceof UnresolvedSymbol symbol) {
|
||||
methodFunction = symbol.resolveFor(targetType);
|
||||
} else {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
var ctx = EnsoContext.get(this);
|
||||
var err = ctx.getBuiltins().error();
|
||||
var payload = err.makeUnsupportedArgumentsError(new Object[] { method }, "Use .name to specify name of function");
|
||||
throw new PanicException(payload, this);
|
||||
}
|
||||
if (methodFunction != null) {
|
||||
String parameterName = expectStringNode.execute(parameter);
|
||||
Annotation annotation = methodFunction.getSchema().getAnnotation(parameterName);
|
||||
@ -59,6 +64,7 @@ public abstract class GetAnnotationNode extends BaseNode {
|
||||
}
|
||||
}
|
||||
if (target instanceof Type type) {
|
||||
String methodName = ((UnresolvedSymbol) symbol).getName();
|
||||
AtomConstructor constructor = getAtomConstructor(type, methodName);
|
||||
if (constructor != null) {
|
||||
Function constructorFunction = constructor.getConstructorFunction();
|
||||
|
@ -282,32 +282,32 @@ spec =
|
||||
(Test_Type.Value a)==(Test_Type.Value c) . should_be_false
|
||||
|
||||
Test.specify "get annotations" <|
|
||||
Meta.get_annotation Meta_Spec "test_method" "a" . should_equal 7
|
||||
Meta.get_annotation Meta_Spec "test_method" "b" . should_equal (Test_Type.Value 49)
|
||||
Meta.get_annotation Meta_Spec "test_method" "c" . should_fail_with Text
|
||||
Meta.get_annotation Meta_Spec "test_method" "c" . catch . should_equal "Error Value"
|
||||
Meta.get_annotation Meta_Spec "test_method" "x" . should_equal Nothing
|
||||
Meta.get_annotation Meta_Spec .test_method "a" . should_equal 7
|
||||
Meta.get_annotation Meta_Spec .test_method "b" . should_equal (Test_Type.Value 49)
|
||||
Meta.get_annotation Meta_Spec .test_method "c" . should_fail_with Text
|
||||
Meta.get_annotation Meta_Spec .test_method "c" . catch . should_equal "Error Value"
|
||||
Meta.get_annotation Meta_Spec .test_method "x" . should_equal Nothing
|
||||
|
||||
value = My_Type.Value 99 "bar" True
|
||||
Meta.get_annotation value "first_method" "param" . should_equal 11
|
||||
Meta.get_annotation value "second_method" "param" . should_equal Nothing
|
||||
Meta.get_annotation value "third_method" "param" . should_equal Nothing
|
||||
Meta.get_annotation value "other_method" "a" 7 . should_equal 12
|
||||
Meta.get_annotation value "other_method" "b" value . should_equal 99
|
||||
Meta.get_annotation value "other_method" "c" . should_equal Nothing
|
||||
Meta.get_annotation value .first_method "param" . should_equal 11
|
||||
Meta.get_annotation value .second_method "param" . should_equal Nothing
|
||||
Meta.get_annotation value .third_method "param" . should_equal Nothing
|
||||
Meta.get_annotation value .other_method "a" 7 . should_equal 12
|
||||
Meta.get_annotation value .other_method "b" value . should_equal 99
|
||||
Meta.get_annotation value .other_method "c" . should_equal Nothing
|
||||
|
||||
Meta.get_annotation value "my_method" "self" . should_equal "self"
|
||||
Meta.get_annotation value .my_method "self" . should_equal "self"
|
||||
|
||||
Test.specify "no constructor annotations on value" <|
|
||||
value = My_Type.Value 99 "bar" True
|
||||
Meta.get_annotation value "Value" "foo" . should_equal Nothing
|
||||
Meta.get_annotation value "Value" "bar" . should_equal Nothing
|
||||
Meta.get_annotation value "Value" "baz" . should_equal Nothing
|
||||
Meta.get_annotation value .Value "foo" . should_equal Nothing
|
||||
Meta.get_annotation value .Value "bar" . should_equal Nothing
|
||||
Meta.get_annotation value .Value "baz" . should_equal Nothing
|
||||
|
||||
Test.specify "get annotations on constructor" <|
|
||||
Meta.get_annotation My_Type "Value" "foo" 7 8 . should_equal 15
|
||||
Meta.get_annotation My_Type "Value" "bar" . should_equal Nothing
|
||||
Meta.get_annotation My_Type "Value" "baz" . should_equal (My_Type.Value 1 2 3)
|
||||
Meta.get_annotation My_Type .Value "foo" 7 8 . should_equal 15
|
||||
Meta.get_annotation My_Type .Value "bar" . should_equal Nothing
|
||||
Meta.get_annotation My_Type .Value "baz" . should_equal (My_Type.Value 1 2 3)
|
||||
|
||||
Test.group "Check Nothing and NaN" <|
|
||||
Test.specify "Nothing.is_a Nothing" <|
|
||||
|
@ -21,7 +21,7 @@ spec =
|
||||
|
||||
Test.group "Widgets for In-Database Connection with table types" <|
|
||||
Test.specify "works for `tables`" <|
|
||||
result = Widgets.get_widget_json connection "tables" ["types"]
|
||||
result = Widgets.get_widget_json connection .tables ["types"]
|
||||
result.should_contain "'TABLE'"
|
||||
result.should_contain "'VIEW'"
|
||||
|
||||
@ -29,8 +29,8 @@ spec =
|
||||
Test.specify "works for `query` and `read`" <|
|
||||
choices = ['a_table', 'another', 'mock_table'] . map n-> Choice.Option n n.pretty
|
||||
expect = [["query", Widget.Single_Choice choices Nothing Display.Always]] . to_json
|
||||
Widgets.get_widget_json connection "query" ["query"] . should_equal expect
|
||||
Widgets.get_widget_json connection "read" ["query"] . should_equal expect
|
||||
Widgets.get_widget_json connection .query ["query"] . should_equal expect
|
||||
Widgets.get_widget_json connection .read ["query"] . should_equal expect
|
||||
|
||||
Test.group "Widgets for In-Database Table with column name sets" <|
|
||||
mock_table = connection.query "mock_table"
|
||||
@ -38,17 +38,17 @@ spec =
|
||||
Test.specify "works for `get` and `at`" <|
|
||||
choices = mock_table.column_names . map n-> Choice.Option n n.pretty
|
||||
expect = [["selector", Widget.Single_Choice choices Nothing Display.Always]] . to_json
|
||||
Widgets.get_widget_json mock_table "get" ["selector"] . should_equal expect
|
||||
Widgets.get_widget_json mock_table "at" ["selector"] . should_equal expect
|
||||
Widgets.get_widget_json mock_table .get ["selector"] . should_equal expect
|
||||
Widgets.get_widget_json mock_table .at ["selector"] . should_equal expect
|
||||
|
||||
Test.specify "works for `filter`" <|
|
||||
choices = mock_table.column_names . map n-> Choice.Option n n.pretty
|
||||
expect = [["column", Widget.Single_Choice choices Nothing Display.Always]] . to_json
|
||||
Widgets.get_widget_json mock_table "filter" ["column"] . should_equal expect
|
||||
Widgets.get_widget_json mock_table .filter ["column"] . should_equal expect
|
||||
|
||||
Test.group "Widgets for Database" <|
|
||||
Test.specify "works for `connect`" <|
|
||||
result = Widgets.get_widget_json Database "connect" ["details"]
|
||||
result = Widgets.get_widget_json Database .connect ["details"]
|
||||
result.should_contain "SQLite"
|
||||
result.should_contain "Postgres"
|
||||
result.should_contain "Redshift"
|
||||
|
@ -18,12 +18,12 @@ spec =
|
||||
Test.specify "works for `get` and `at`" <|
|
||||
choices = mock_table.column_names . map n-> Choice.Option n n.pretty
|
||||
expect = [["selector", Widget.Single_Choice choices Nothing Display.Always]] . to_json
|
||||
Widgets.get_widget_json mock_table "get" ["selector"] . should_equal expect
|
||||
Widgets.get_widget_json mock_table "at" ["selector"] . should_equal expect
|
||||
Widgets.get_widget_json mock_table .get ["selector"] . should_equal expect
|
||||
Widgets.get_widget_json mock_table .at ["selector"] . should_equal expect
|
||||
|
||||
Test.specify "works for `filter`" <|
|
||||
choices = mock_table.column_names . map n-> Choice.Option n n.pretty
|
||||
expect = [["column", Widget.Single_Choice choices Nothing Display.Always]] . to_json
|
||||
Widgets.get_widget_json mock_table "filter" ["column"] . should_equal expect
|
||||
Widgets.get_widget_json mock_table .filter ["column"] . should_equal expect
|
||||
|
||||
main = Test_Suite.run_main spec
|
||||
|
@ -16,9 +16,9 @@ spec =
|
||||
mock_text = "abc def"
|
||||
default_widget = Text_Sub_Range.default_widget
|
||||
expect = [["range", default_widget]] . to_json
|
||||
json = Widgets.get_widget_json mock_text "take" ["range"]
|
||||
json = Widgets.get_widget_json mock_text .take ["range"]
|
||||
json . should_equal expect
|
||||
Widgets.get_widget_json mock_text "drop" ["range"] . should_equal expect
|
||||
Widgets.get_widget_json mock_text .drop ["range"] . should_equal expect
|
||||
obj = json.parse_json
|
||||
widget = obj.first.second
|
||||
options = widget . at "values"
|
||||
|
Loading…
Reference in New Issue
Block a user