Deal with warnings attached to value when making widgets. (#5994)

- Fixes InvokeCallableNode to support warnings.
- Strips warnings from annotations in `get_widget_json`.
- Remove `get_full_annotations_json`.
- Fix warnings on Dialect.
This commit is contained in:
James Dunkerley 2023-03-22 10:50:19 +00:00 committed by GitHub
parent d38951d4e9
commit 546cb0c4ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 83 additions and 37 deletions

View File

@ -54,6 +54,7 @@ type Dialect
settings are supported by the given database backend.
prepare_order_descriptor : Internal_Column -> Sort_Direction -> Text_Ordering -> Order_Descriptor
prepare_order_descriptor self internal_column sort_direction text_ordering =
_ = [internal_column, sort_direction, text_ordering]
Unimplemented.throw "This is an interface only."
## PRIVATE
@ -61,12 +62,14 @@ type Dialect
proper query.
prepare_join : Connection -> Join_Kind -> Text -> From_Spec -> From_Spec -> Vector -> Vector -> Vector -> Table
prepare_join self connection join_kind new_table_name left_subquery right_subquery on_expressions where_expressions columns_to_select =
_ = [connection, join_kind, new_table_name, left_subquery, right_subquery, on_expressions, where_expressions, columns_to_select]
Unimplemented.throw "This is an interface only."
## PRIVATE
Prepares a distinct operation.
prepare_distinct : Table -> Vector -> Case_Sensitivity -> Problem_Builder -> Table
prepare_distinct self table key_columns case_sensitivity problem_builder =
_ = [table, key_columns, case_sensitivity, problem_builder]
Unimplemented.throw "This is an interface only."
## PRIVATE
@ -74,6 +77,7 @@ type Dialect
like a SQL query for the given dialect or is rather a table name.
is_probably_a_query : Text -> Boolean
is_probably_a_query self text =
_ = [text]
Unimplemented.throw "This is an interface only."
## PRIVATE

View File

@ -1,27 +1,5 @@
from Standard.Base import all
## PRIVATE
Basic preprocessor for widgets metadata visualization.
Returns simplified annotation data for all requested arguments.
Values are replaced with just Text of the code.
get_full_annotations_json : Any -> Text -> Vector Text -> Text
get_full_annotations_json value call_name argument_names =
read_annotation argument =
annotation = Meta.get_annotation value call_name argument
widget = case annotation of
_ : Function -> annotation value
_ -> annotation
js_widget = widget.to_js_object
if js_widget.get "values" . is_nothing then js_widget else
js_codes = js_widget.get "values" . map (_.get "value")
fields = js_widget.field_names
values = fields.map f-> if f=="values" then js_codes else js_widget.get f
JS_Object.from_pairs (fields.zip values)
annotations = argument_names.map (arg -> [arg, read_annotation arg])
annotations.to_json
## PRIVATE
Basic preprocessor for widgets metadata visualization.
@ -29,7 +7,7 @@ get_full_annotations_json value call_name argument_names =
get_widget_json : Any -> Text -> Vector Text -> Text
get_widget_json value call_name argument_names =
read_annotation argument =
annotation = Meta.get_annotation value call_name argument
annotation = Warning.clear <| Meta.get_annotation value call_name argument
case annotation of
_ : Function -> annotation value
_ -> annotation

View File

@ -1,9 +1,12 @@
package org.enso.interpreter.node.callable;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.SourceSection;
import java.util.UUID;
@ -22,6 +25,9 @@ import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.error.DataflowError;
import org.enso.interpreter.runtime.error.PanicException;
import org.enso.interpreter.runtime.error.PanicSentinel;
import org.enso.interpreter.runtime.error.Warning;
import org.enso.interpreter.runtime.error.WarningsLibrary;
import org.enso.interpreter.runtime.error.WithWarnings;
import org.enso.interpreter.runtime.state.State;
/**
@ -81,6 +87,7 @@ public abstract class InvokeCallableNode extends BaseNode {
@Child private InvokeConversionNode invokeConversionNode;
@Child private ThunkExecutorNode thisExecutor;
@Child private ThunkExecutorNode thatExecutor;
@Child private InvokeCallableNode childDispatch;
private final boolean canApplyThis;
private final boolean canApplyThat;
@ -251,6 +258,53 @@ public abstract class InvokeCallableNode extends BaseNode {
}
}
@Specialization(guards = "warnings.hasWarnings(warning)")
public Object invokeWarnings(
Object warning,
VirtualFrame callerFrame,
State state,
Object[] arguments,
@CachedLibrary(limit = "3") WarningsLibrary warnings) {
try {
if (childDispatch == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
Lock lock = getLock();
lock.lock();
try {
if (childDispatch == null) {
childDispatch =
insert(
build(
invokeFunctionNode.getSchema(),
invokeFunctionNode.getDefaultsExecutionMode(),
invokeFunctionNode.getArgumentsExecutionMode()));
childDispatch.setTailStatus(getTailStatus());
notifyInserted(childDispatch);
}
} finally {
lock.unlock();
}
}
var result = childDispatch.execute(
warnings.removeWarnings(warning),
callerFrame,
state,
arguments);
Warning[] extracted = warnings.getWarnings(warning, null);
if (result instanceof DataflowError) {
return result;
} else if (result instanceof WithWarnings withWarnings) {
return withWarnings.prepend(extracted);
} else {
return new WithWarnings(result, extracted);
}
} catch (UnsupportedMessageException e) {
throw CompilerDirectives.shouldNotReachHere(e);
}
}
@Fallback
public Object invokeGeneric(
Object callable, VirtualFrame callerFrame, State state, Object[] arguments) {
@ -281,6 +335,9 @@ public abstract class InvokeCallableNode extends BaseNode {
invokeFunctionNode.setTailStatus(isTail);
invokeMethodNode.setTailStatus(isTail);
invokeConversionNode.setTailStatus(isTail);
if (childDispatch != null) {
childDispatch.setTailStatus(isTail);
}
}
/** @return the source section for this node. */

View File

@ -1,5 +1,6 @@
from Standard.Base import all
import Standard.Base.Metadata.Choice
import Standard.Base.Metadata.Widget
import Standard.Base.Metadata.Display
@ -18,26 +19,29 @@ spec =
Test.group "Widgets for In-Database Connection with table types" <|
Test.specify "works for `tables`" <|
result = Widgets.get_full_annotations_json connection "tables" ["types"]
result = Widgets.get_widget_json connection "tables" ["types"]
result.contains "'TABLE'" . should_be_true
result.contains "'VIEW'" . should_be_true
Test.group "Widgets for In-Database Connection with table name sets" <|
Test.specify "works for `query` and `read`" <|
expect = [["query", Widget.Single_Choice (["'a_table'", "'another'", "'mock_table'"]) Nothing Display.Always]] . to_json
Widgets.get_full_annotations_json connection "query" ["query"] . should_equal expect
Widgets.get_full_annotations_json connection "read" ["query"] . should_equal expect
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
Test.group "Widgets for In-Database Table with column name sets" <|
mock_table = connection.query "mock_table"
Test.specify "works for `get` and `at`" <|
expect = [["selector", Widget.Single_Choice (mock_table.column_names.map .pretty) Nothing Display.Always]] . to_json
Widgets.get_full_annotations_json mock_table "get" ["selector"] . should_equal expect
Widgets.get_full_annotations_json mock_table "at" ["selector"] . should_equal expect
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
Test.specify "works for `filter`" <|
expect = [["column", Widget.Single_Choice (mock_table.column_names.map .pretty) Nothing Display.Always]] . to_json
Widgets.get_full_annotations_json mock_table "filter" ["column"] . should_equal expect
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
main = Test_Suite.run_main spec

View File

@ -1,5 +1,6 @@
from Standard.Base import all
import Standard.Base.Metadata.Choice
import Standard.Base.Metadata.Widget
import Standard.Base.Metadata.Display
@ -15,12 +16,14 @@ spec =
mock_table = Table.from_rows ["A", "B C", 'D "E"', "F.G/H\I"] []
Test.specify "works for `get` and `at`" <|
expect = [["selector", Widget.Single_Choice ["'A'", "'B C'", '\'D "E"\'', "'F.G/H\\I'"] Nothing Display.Always]] . to_json
Widgets.get_full_annotations_json mock_table "get" ["selector"] . should_equal expect
Widgets.get_full_annotations_json mock_table "at" ["selector"] . should_equal expect
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
Test.specify "works for `filter`" <|
expect = [["column", Widget.Single_Choice ["'A'", "'B C'", '\'D "E"\'', "'F.G/H\\I'"] Nothing Display.Always]] . to_json
Widgets.get_full_annotations_json mock_table "filter" ["column"] . should_equal expect
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
main = Test_Suite.run_main spec