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

Support Autosave for open buffers #3637

Merged
merged 7 commits into from
Aug 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@
- [Enable caching in visualisation functions][3618]
- [Update Scala compiler and libraries][3631]
- [Support importing module methods][3633]
- [Support Autosave for open buffers][3637]

[3227]: https://github.com/enso-org/enso/pull/3227
[3248]: https://github.com/enso-org/enso/pull/3248
Expand Down Expand Up @@ -347,6 +348,7 @@
[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
[3637]: https://github.com/enso-org/enso/pull/3637

# Enso 2.0.0-alpha.18 (2021-10-12)

Expand Down
27 changes: 27 additions & 0 deletions docs/language-server/protocol-language-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ transport formats, please look [here](./protocol-architecture).
- [`text/applyEdit`](#textapplyedit)
- [`text/applyExpressionValue`](#textapplyexpressionvalue)
- [`text/didChange`](#textdidchange)
- [`text/autoSave`](#textautosave)
- [Workspace Operations](#workspace-operations)
- [`workspace/projectInfo`](#workspaceprojectinfo)
- [Monitoring](#monitoring)
Expand Down Expand Up @@ -2876,6 +2877,32 @@ This notification must _only_ be sent for files that the client has open.
null;
```

### `text/autoSave`

This is a notification sent from the server to the clients to inform them of any
successful auto-save action.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.


- **Type:** Notification
- **Direction:** Server -> Client
- **Connection:** Protocol
- **Visibility:** Public

This notification must _only_ be sent for files that the client has open.

#### Parameters

```typescript
{
path: Path;
}
```

#### Errors

```typescript
null;
```

## Workspace Operations

The language server also has a set of operations useful for managing the client
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,11 @@ class MainModule(serverConfig: LanguageServerConfig, logLevel: LogLevel) {

lazy val bufferRegistry =
system.actorOf(
BufferRegistry.props(fileManager, runtimeConnector),
BufferRegistry.props(
fileManager,
runtimeConnector,
TimingsConfig.default().withAutoSave(6.seconds)
),
"buffer-registry"
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.enso.languageserver.boot

import scala.concurrent.duration._

/** TimingsConfig encapsulates information about timings or delays in messages being sent between services.
*
* @param autoSave a request timeout
* @param autoSave if non-empty value, determines the delay when auto-save should be triggered
*/
class TimingsConfig(
private[this] val timeout: FiniteDuration,
private[this] var autoSave: Option[FiniteDuration]
) {
def this(timeout: FiniteDuration) = {
this(timeout, None)
}

/** A request timeout.
*
* @return a duration to wait for the request to be handled
*/
def requestTimeout: FiniteDuration = timeout

/** Auto-save delay.
*
* @return if non-empty, determines the delay when auto-save should be triggered after the last edit
*/
def autoSaveDelay: Option[FiniteDuration] = autoSave

/** Sets the delay for auto-save action that should be triggered after the last edit action.
*
* @param delay delay for auto-save action
* @return updated config
*/
def withAutoSave(delay: FiniteDuration): TimingsConfig = {
autoSave = Some(delay)
this
}
}

object TimingsConfig {
def default(): TimingsConfig = new TimingsConfig(10.seconds)
}
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@ class JsonConnectionController(
case TextProtocol.TextDidChange(changes) =>
webActor ! Notification(TextDidChange, TextDidChange.Params(changes))

case TextProtocol.FileAutoSaved(path) =>
webActor ! Notification(FileAutoSaved, FileAutoSaved.Params(path))

case PathWatcherProtocol.FileEventResult(event) =>
webActor ! Notification(
EventFile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ object JsonRpc {
.registerNotification(ForceReleaseCapability)
.registerNotification(GrantCapability)
.registerNotification(TextDidChange)
.registerNotification(FileAutoSaved)
.registerNotification(EventFile)
.registerNotification(ContentRootAdded)
.registerNotification(ContentRootRemoved)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,50 @@ import org.enso.text.buffer.Rope
*
* @param file the file linked to the buffer.
* @param contents the contents of the buffer.
* @param inMemory determines if the buffer is in-memory
* @param version the current version of the buffer contents.
*/
case class Buffer(file: File, contents: Rope, version: ContentVersion)
case class Buffer(
file: File,
contents: Rope,
inMemory: Boolean,
version: ContentVersion
)

object Buffer {

/** Creates a new buffer with a freshly generated version.
*
* @param file the file linked to the buffer.
* @param contents the contents of this buffer.
* @param inMemory determines if the buffer is in-memory
* @param versionCalculator a digest calculator for content based versioning.
* @return a new buffer instance.
*/
def apply(
file: File,
contents: Rope
contents: Rope,
inMemory: Boolean
)(implicit versionCalculator: ContentBasedVersioning): Buffer =
Buffer(file, contents, versionCalculator.evalVersion(contents.toString))
Buffer(
file,
contents,
inMemory,
versionCalculator.evalVersion(contents.toString)
)

/** Creates a new buffer with a freshly generated version.
*
* @param file the file linked to the buffer.
* @param contents the contents of this buffer.
* @param inMemory determines if the buffer is in-memory
* @param versionCalculator a digest calculator for content based versioning.
* @return a new buffer instance.
*/
def apply(
file: File,
contents: String
contents: String,
inMemory: Boolean
)(implicit versionCalculator: ContentBasedVersioning): Buffer =
Buffer(file, Rope(contents))
Buffer(file, Rope(contents), inMemory)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.enso.languageserver.text

import akka.actor.{Actor, ActorRef, Props, Stash, Terminated}
import com.typesafe.scalalogging.LazyLogging
import org.enso.languageserver.boot.TimingsConfig
import org.enso.languageserver.capability.CapabilityProtocol.{
AcquireCapability,
CapabilityAcquisitionBadRequest,
Expand Down Expand Up @@ -58,10 +59,12 @@ import org.enso.text.ContentBasedVersioning
* @param fileManager a file manager
* @param runtimeConnector a gateway to the runtime
* @param versionCalculator a content based version calculator
* @param timingsConfig a config with timeout/delay values
*/
class BufferRegistry(
fileManager: ActorRef,
runtimeConnector: ActorRef
runtimeConnector: ActorRef,
timingsConfig: TimingsConfig
)(implicit
versionCalculator: ContentBasedVersioning
) extends Actor
Expand Down Expand Up @@ -100,7 +103,8 @@ class BufferRegistry(
CollaborativeBuffer.props(
path,
fileManager,
runtimeConnector
runtimeConnector,
timingsConfig = timingsConfig
)
)
context.watch(bufferRef)
Expand All @@ -117,7 +121,8 @@ class BufferRegistry(
CollaborativeBuffer.props(
path,
fileManager,
runtimeConnector
runtimeConnector,
timingsConfig = timingsConfig
)
)
context.watch(bufferRef)
Expand Down Expand Up @@ -180,14 +185,16 @@ object BufferRegistry {
* @param fileManager a file manager actor
* @param runtimeConnector a gateway to the runtime
* @param versionCalculator a content based version calculator
* @param timingsConfig a config with timout/delay values
* @return a configuration object
*/
def props(
fileManager: ActorRef,
runtimeConnector: ActorRef
runtimeConnector: ActorRef,
timingsConfig: TimingsConfig
)(implicit
versionCalculator: ContentBasedVersioning
): Props =
Props(new BufferRegistry(fileManager, runtimeConnector))
Props(new BufferRegistry(fileManager, runtimeConnector, timingsConfig))

}
Loading