Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable caching in visualization functions #3618

Merged
merged 16 commits into from
Aug 10, 2022
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@
- [Explicit `self`][3569]
- [Added benchmarking tool for the language server][3578]
- [Support module imports using a qualified name][3608]
- [Enable caching in visualisation functions][3618]
- [Update Scala compiler and libraries][3631]
- [Support importing module methods][3633]

Expand Down Expand Up @@ -338,7 +339,8 @@
[3562]: https://github.com/enso-org/enso/pull/3562
[3538]: https://github.com/enso-org/enso/pull/3538
[3538]: https://github.com/enso-org/enso/pull/3569
[3578]: https://github.com/enso-org/enso/pull/3578
[3618]: https://github.com/enso-org/enso/pull/3618
[3608]: https://github.com/enso-org/enso/pull/3608
[3608]: https://github.com/enso-org/enso/pull/3608
[3631]: https://github.com/enso-org/enso/pull/3631
[3633]: https://github.com/enso-org/enso/pull/3633
Expand Down
15 changes: 7 additions & 8 deletions docs/language-server/protocol-language-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ transport formats, please look [here](./protocol-architecture).
- [`ExpressionUpdate`](#expressionupdate)
- [`ExpressionUpdatePayload`](#expressionupdatepayload)
- [`VisualisationConfiguration`](#visualisationconfiguration)
- [`VisualisationExpression`](#visualisationexpression)
- [`SuggestionEntryArgument`](#suggestionentryargument)
- [`SuggestionEntry`](#suggestionentry)
- [`SuggestionEntryType`](#suggestionentrytype)
Expand Down Expand Up @@ -378,19 +379,17 @@ A configuration object for properties of the visualisation.

```typescript
interface VisualisationConfiguration {
/**
* An execution context of the visualisation.
*/
/** An execution context of the visualisation. */
executionContextId: UUID;

/**
* A qualified name of the module containing the expression which creates
* visualisation.
*/
visualisationModule: String;
/**
* The expression that creates a visualisation.
*/
expression: String;
visualisationModule?: String;

/** An expression that creates a visualisation. */
expression: String | MethodPointer;
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ final class ContextRegistry(
Api.AttachVisualisation(
visualisationId,
expressionId,
convertVisualisationConfig(cfg)
cfg.toApi
)
)
} else {
Expand All @@ -263,7 +263,7 @@ final class ContextRegistry(
Api.AttachVisualisation(
visualisationId,
expressionId,
convertVisualisationConfig(cfg)
cfg.toApi
)
)
} else {
Expand Down Expand Up @@ -301,25 +301,14 @@ final class ContextRegistry(
)
)

val configuration = convertVisualisationConfig(cfg)

handler.forward(
Api.ModifyVisualisation(visualisationId, configuration)
Api.ModifyVisualisation(visualisationId, cfg.toApi)
)
} else {
sender() ! AccessDenied
}
}

private def convertVisualisationConfig(
config: VisualisationConfiguration
): Api.VisualisationConfiguration =
Api.VisualisationConfiguration(
executionContextId = config.executionContextId,
visualisationModule = config.visualisationModule,
expression = config.expression
)

private def getRuntimeStackItem(
stackItem: StackItem
): Api.StackItem =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package org.enso.languageserver.runtime

import org.enso.polyglot.runtime.Runtime.Api

/** An object pointing to a method definition.
*
* @param module the module of the method file
* @param definedOnType method type
* @param name method name
*/
case class MethodPointer(module: String, definedOnType: String, name: String)
case class MethodPointer(module: String, definedOnType: String, name: String) {

/** Convert to corresponding [[Api]] message. */
def toApi: Api.MethodPointer =
Api.MethodPointer(module, definedOnType, name)
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,201 @@
package org.enso.languageserver.runtime

import java.util.UUID
import io.circe.generic.auto._
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Json}
import org.enso.logger.masking.ToLogString
import org.enso.polyglot.runtime.Runtime.Api

import org.enso.logger.masking.{MaskedString, ToLogString}
import java.util.UUID

/** A configuration object for properties of the visualisation.
*
* @param executionContextId an execution context of the visualisation
* @param visualisationModule a qualified name of the module containing
* the expression which creates visualisation
* @param expression the expression that creates a visualisation
* @param expression an expression that creates a visualisation
*/
case class VisualisationConfiguration(
executionContextId: UUID,
visualisationModule: String,
expression: String
expression: VisualisationExpression
) extends ToLogString {

/** A qualified module name containing the expression. */
def visualisationModule: String =
expression.module

/** @inheritdoc */
override def toLogString(shouldMask: Boolean): String =
"VisualisationConfiguration(" +
s"VisualisationConfiguration(" +
s"executionContextId=$executionContextId," +
s"visualisationModule=$visualisationModule,expression=" +
MaskedString(expression).toLogString(shouldMask) +
")"
s"expression=${expression.toLogString(shouldMask)})"

/** Convert to corresponding [[Api]] message. */
def toApi: Api.VisualisationConfiguration =
Api.VisualisationConfiguration(
executionContextId = executionContextId,
expression = expression.toApi
)

}
object VisualisationConfiguration {

/** Create a visualisation configuration.
*
* @param contextId an execution context of the visualisation
* @param module a qualified module name containing the visualisation
* @param expression a visualisation expression
* @return an instance of [[VisualisationConfiguration]]
*/
def apply(
contextId: UUID,
module: String,
expression: String
): VisualisationConfiguration =
new VisualisationConfiguration(
contextId,
VisualisationExpression.Text(module, expression)
)

/** Create a visualisation configuration.
*
* @param contextId an execution context of the visualisation
* @param expression a visualisation expression
* @return an instance of [[VisualisationConfiguration]]
*/
def apply(
contextId: UUID,
expression: MethodPointer
): VisualisationConfiguration =
new VisualisationConfiguration(
contextId,
VisualisationExpression.ModuleMethod(expression)
)

private object CodecField {

val Expression = "expression"

val ExecutionContextId = "executionContextId"

val VisualisationModule = "visualisationModule"
}

/** Json decoder that supports both old and new formats. */
implicit val decoder: Decoder[VisualisationConfiguration] =
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
Decoder.instance { cursor =>
cursor.downField(CodecField.Expression).as[String] match {
case Left(_) =>
for {
contextId <- cursor
.downField(CodecField.ExecutionContextId)
.as[UUID]
expression <- cursor
.downField(CodecField.Expression)
.as[MethodPointer]
} yield VisualisationConfiguration(contextId, expression)

case Right(expression) =>
for {
contextId <- cursor
.downField(CodecField.ExecutionContextId)
.as[UUID]
visualisationModule <- cursor
.downField(CodecField.VisualisationModule)
.as[String]
} yield VisualisationConfiguration(
contextId,
visualisationModule,
expression
)
}
}
}

/** A visualisation expression. */
sealed trait VisualisationExpression extends ToLogString {

/** A qualified module name. */
def module: String

/** Convert to corresponding [[Api]] message. */
def toApi: Api.VisualisationExpression
}
object VisualisationExpression {

/** Visualization expression represented as a text.
*
* @param module a qualified module name containing the expression
* @param expression an expression that creates a visualization
*/
case class Text(module: String, expression: String)
extends VisualisationExpression {

/** @inheritdoc */
override def toApi: Api.VisualisationExpression =
Api.VisualisationExpression.Text(module, expression)

/** @inheritdoc */
override def toLogString(shouldMask: Boolean): String =
s"Text(module=$module" +
s",expression=" +
(if (shouldMask) STUB else expression) +
")"
}

/** Visualization expression represented as a module method.
*
* @param methodPointer a pointer to a method definition
*/
case class ModuleMethod(methodPointer: MethodPointer)
extends VisualisationExpression {

/** @inheritdoc */
override val module: String = methodPointer.module

/** @inheritdoc */
override def toApi: Api.VisualisationExpression =
Api.VisualisationExpression.ModuleMethod(methodPointer.toApi)

/** @inheritdoc */
override def toLogString(shouldMask: Boolean): String =
s"ModuleMethod(methodPointer=$methodPointer)"
}

private object CodecField {

val Type = "type"
}

private object PayloadType {

val Text = "Text"

val ModuleMethod = "ModuleMethod"
}

implicit val encoder: Encoder[VisualisationExpression] =
Encoder.instance[VisualisationExpression] {
case text: VisualisationExpression.Text =>
Encoder[VisualisationExpression.Text]
.apply(text)
.deepMerge(Json.obj(CodecField.Type -> PayloadType.Text.asJson))

case moduleMethod: VisualisationExpression.ModuleMethod =>
Encoder[VisualisationExpression.ModuleMethod]
.apply(moduleMethod)
.deepMerge(
Json.obj(CodecField.Type -> PayloadType.ModuleMethod.asJson)
)
}

implicit val decoder: Decoder[VisualisationExpression] =
Decoder.instance { cursor =>
cursor.downField(CodecField.Type).as[String].flatMap {
case PayloadType.Text =>
Decoder[VisualisationExpression.Text].tryDecode(cursor)

case PayloadType.ModuleMethod =>
Decoder[VisualisationExpression.ModuleMethod].tryDecode(cursor)
}
}

}
Loading