Fix cached method pointers in expression updates (#11060)

close #11028

Changelog:
- update: hide cached method pointer info in expression updates of evaluated values

# Important Notes
https://github.com/user-attachments/assets/861bb2c8-7613-4fcf-a976-0e37acff4ec0
This commit is contained in:
Dmitry Bushev 2024-09-13 14:02:30 +03:00 committed by GitHub
parent 8eb9e21e40
commit e77a6067a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 132 additions and 14 deletions

View File

@ -728,15 +728,23 @@ object ProgramExecutionSupport {
* @param value the expression value. * @param value the expression value.
* @return the method call info * @return the method call info
*/ */
private def toMethodCall(value: ExpressionValue): Option[Api.MethodCall] = private def toMethodCall(value: ExpressionValue): Option[Api.MethodCall] = {
// While hiding the cached method pointer info for evaluated values, it is a
// good idea to return the cached method pointer value for dataflow errors
// (the one before the value turned into a dataflow error) to continue
// displaying widgets on child nodes even after those nodes become errors.
def notCachedAndNotDataflowError: Boolean =
!value.wasCached() && !value.getValue.isInstanceOf[DataflowError]
for { for {
call <- call <-
if (Types.isPanic(value.getType)) Option(value.getCallInfo) if (Types.isPanic(value.getType) || notCachedAndNotDataflowError)
Option(value.getCallInfo)
else Option(value.getCallInfo).orElse(Option(value.getCachedCallInfo)) else Option(value.getCallInfo).orElse(Option(value.getCachedCallInfo))
methodPointer <- toMethodPointer(call.functionPointer) methodPointer <- toMethodPointer(call.functionPointer)
} yield { } yield {
Api.MethodCall(methodPointer, call.notAppliedArguments.toVector) Api.MethodCall(methodPointer, call.notAppliedArguments.toVector)
} }
}
/** Extract the method pointer information form the provided runtime function /** Extract the method pointer information form the provided runtime function
* pointer. * pointer.

View File

@ -925,16 +925,7 @@ class RuntimeErrorsTest
TestMessages.update( TestMessages.update(
contextId, contextId,
xId, xId,
ConstantsGen.INTEGER, ConstantsGen.INTEGER
methodCall = Some(
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Error",
"Standard.Base.Error.Error",
"throw"
)
)
)
), ),
TestMessages.update( TestMessages.update(
contextId, contextId,

View File

@ -1160,6 +1160,127 @@ class RuntimeServerTest
) )
} }
it should "send method pointer updates of when autoscope constructor changes to a value" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Enso_Test.Test.Main"
val metadata = new Metadata
val idA = metadata.addItem(44, 3, "aa")
val code =
"""type Xyz
|
|type T
| A
|
|main =
| a = test Xyz
| a
|
|test t:(Xyz | T) = t
|""".stripMargin.linesIterator.mkString("\n")
val contents = metadata.appendToCode(code)
val mainFile = context.writeMain(contents)
metadata.assertInCode(idA, code, "Xyz")
// create context
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
context.receive shouldEqual Some(
Api.Response(requestId, Api.CreateContextResponse(contextId))
)
// open file
context.send(
Api.Request(requestId, Api.OpenFileRequest(mainFile, contents))
)
context.receive shouldEqual Some(
Api.Response(Some(requestId), Api.OpenFileResponse)
)
// push main
context.send(
Api.Request(
requestId,
Api.PushContextRequest(
contextId,
Api.StackItem.ExplicitCall(
Api.MethodPointer(moduleName, moduleName, "main"),
None,
Vector()
)
)
)
)
context.receiveN(3) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
TestMessages.update(
contextId,
idA,
"Enso_Test.Test.Main.Xyz"
),
context.executionComplete(contextId)
)
// Modify the file /Xyz/..A/
context.send(
Api.Request(
Api.EditFileNotification(
mainFile,
Seq(
model.TextEdit(
model.Range(model.Position(6, 13), model.Position(6, 16)),
"..A"
)
),
execute = true,
idMap = None
)
)
)
context.receiveN(3) should contain theSameElementsAs Seq(
TestMessages.pending(contextId, idA),
TestMessages.update(
contextId,
idA,
"Enso_Test.Test.Main.T",
Api.MethodCall(
Api.MethodPointer("Enso_Test.Test.Main", "Enso_Test.Test.Main.T", "A")
)
),
context.executionComplete(contextId)
)
// Modify the file /..A/Xyz/
context.send(
Api.Request(
Api.EditFileNotification(
mainFile,
Seq(
model.TextEdit(
model.Range(model.Position(6, 13), model.Position(6, 16)),
"Xyz"
)
),
execute = true,
idMap = None
)
)
)
context.receiveN(3) should contain theSameElementsAs Seq(
TestMessages.pending(contextId, idA),
TestMessages.update(
contextId,
idA,
"Enso_Test.Test.Main.Xyz"
),
context.executionComplete(contextId)
)
}
it should "send method pointer updates of builtin operators" in { it should "send method pointer updates of builtin operators" in {
val contextId = UUID.randomUUID() val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID() val requestId = UUID.randomUUID()
@ -3926,7 +4047,6 @@ class RuntimeServerTest
contextId, contextId,
idMainA, idMainA,
ConstantsGen.TEXT, ConstantsGen.TEXT,
Api.MethodCall(Api.MethodPointer(moduleName, moduleName, "hie")),
fromCache = false, fromCache = false,
typeChanged = true typeChanged = true
), ),

View File

@ -370,7 +370,6 @@ class RuntimeTypesTest
TestMessages.panic( TestMessages.panic(
contextId, contextId,
id_x, id_x,
Api.MethodCall(Api.MethodPointer(moduleName, s"$moduleName.T", "C")),
Api.ExpressionUpdate.Payload.Panic("Compile_Error", List(id_x)), Api.ExpressionUpdate.Payload.Panic("Compile_Error", List(id_x)),
builtin = true builtin = true
), ),