feat(editor): complete P0 and P1 authoring services

This commit is contained in:
西风逍遥游 committed 2026-08-24 22:47:23 +08:00
1 parent b5d854ba95
commit 328e37e8ec
57 files changed
+6478 -394

No files matched your search

+23 -47
View File
@@ -1,30 +1,9 @@
#include "editor/EditorDocumentService.h"
#include "editor/EditorValueJson.h"
#include <algorithm>
#include <functional>
#include <sstream>
namespace eve::editor {
namespace {
std::size_t hashValue(const EditorValue& value) {
std::size_t seed = static_cast<std::size_t>(value.type());
auto combine = [&](std::size_t next) { seed ^= next + 0x9e3779b9 + (seed << 6) + (seed >> 2); };
if (const auto* boolean = value.getIf<bool>()) combine(std::hash<bool>{}(*boolean));
if (const auto* integer = value.getIf<std::int64_t>()) combine(std::hash<std::int64_t>{}(*integer));
if (const auto* number = value.getIf<double>()) combine(std::hash<double>{}(*number));
if (const auto* string = value.getIf<std::string>()) combine(std::hash<std::string>{}(*string));
if (const auto* array = value.getIf<EditorValue::Array>())
for (const EditorValue& child : *array) combine(hashValue(child));
if (const auto* object = value.getIf<EditorValue::Object>())
for (const auto& [key, child] : *object) {
combine(std::hash<std::string>{}(key));
combine(hashValue(child));
}
return seed;
}
} // namespace
EditorResult<StoredDocument> MemoryAtomicDocumentStore::read(const std::string& resourceUri) const {
auto found = documents_.find(resourceUri);
@@ -36,18 +15,18 @@ EditorResult<StoredDocument> MemoryAtomicDocumentStore::read(const std::string&
EditorResult<StoredDocument> MemoryAtomicDocumentStore::compareAndSwap(const std::string& resourceUri,
Revision expectedRevision,
const std::string& expectedContentHash,
const EditorValue& content) {
auto found = documents_.find(resourceUri);
const Revision current = found == documents_.end() ? 0 : found->second.revision;
if (current != expectedRevision)
auto found = documents_.find(resourceUri);
const Revision current = found == documents_.end() ? 0 : found->second.revision;
const std::string currentHash = found == documents_.end() ? std::string{} : found->second.contentHash;
if (current != expectedRevision || currentHash != expectedContentHash)
return EditorResult<StoredDocument>::error(EditorStatus::Conflict, RuleId("editor.document.disk-conflict"),
"Document store revision changed before save");
StoredDocument stored;
stored.content = content;
stored.revision = current + 1;
std::ostringstream hash;
hash << std::hex << hashValue(content);
stored.contentHash = hash.str();
stored.content = content;
stored.revision = current + 1;
stored.contentHash = editorValueContentHash(content);
documents_.insert_or_assign(resourceUri, stored);
return EditorResult<StoredDocument>::applied(std::move(stored));
}
@@ -68,10 +47,11 @@ EditorResult<DocumentSnapshot> DocumentService::open(DocumentKey key, std::strin
document.snapshot.state = DocumentState::Ready;
EditorResult<StoredDocument> stored = store_->read(document.snapshot.resourceUri);
if (stored.accepted() && stored.value) {
document.content = stored.value->content;
document.snapshot.revision.disk = stored.value->revision;
document.snapshot.revision.edit = stored.value->revision;
document.snapshot.revision.saved = stored.value->revision;
document.content = stored.value->content;
document.snapshot.revision.disk = stored.value->revision;
document.snapshot.revision.edit = stored.value->revision;
document.snapshot.revision.saved = stored.value->revision;
document.snapshot.diskContentHash = stored.value->contentHash;
} else if (stored.status == EditorStatus::NotFound) {
document.content = std::move(initialContent);
} else {
@@ -105,7 +85,7 @@ EditorResult<SaveTicket> DocumentService::requestSave(const DocumentId& document
ticket.document = document;
ticket.capturedEditRevision = found->second.snapshot.revision.edit;
ticket.expectedDiskRevision = found->second.snapshot.revision.disk;
ticket.expectedContentHash = contentHash(found->second.content);
ticket.expectedContentHash = found->second.snapshot.diskContentHash;
pendingSaves_.emplace(ticket.id, PendingSave{ticket, found->second.content});
return EditorResult<SaveTicket>::applied(std::move(ticket));
}
@@ -116,9 +96,10 @@ EditorResult<DocumentSnapshot> DocumentService::executeSave(const SaveTicket& ti
if (pending == pendingSaves_.end() || document == open_.end())
return error(EditorStatus::NotFound, "editor.document.save-ticket-not-found",
"Save ticket or document is no longer available");
document->second.snapshot.state = DocumentState::Saving;
EditorResult<StoredDocument> stored = store_->compareAndSwap(document->second.snapshot.resourceUri,
ticket.expectedDiskRevision, pending->second.content);
document->second.snapshot.state = DocumentState::Saving;
EditorResult<StoredDocument> stored =
store_->compareAndSwap(document->second.snapshot.resourceUri, ticket.expectedDiskRevision,
ticket.expectedContentHash, pending->second.content);
pendingSaves_.erase(pending);
if (!stored.accepted() || !stored.value) {
document->second.snapshot.state =
@@ -130,9 +111,10 @@ EditorResult<DocumentSnapshot> DocumentService::executeSave(const SaveTicket& ti
result.diagnostics = std::move(stored.diagnostics);
return result;
}
document->second.snapshot.revision.disk = stored.value->revision;
document->second.snapshot.revision.saved = ticket.capturedEditRevision;
document->second.snapshot.state = DocumentState::Ready;
document->second.snapshot.revision.disk = stored.value->revision;
document->second.snapshot.revision.saved = ticket.capturedEditRevision;
document->second.snapshot.diskContentHash = stored.value->contentHash;
document->second.snapshot.state = DocumentState::Ready;
document->second.snapshot.diagnostics.clear();
return EditorResult<DocumentSnapshot>::applied(document->second.snapshot);
}
@@ -171,12 +153,6 @@ EditorResult<void> DocumentService::close(const DocumentId& document) {
return EditorResult<void>::applied();
}
std::string DocumentService::contentHash(const EditorValue& value) {
std::ostringstream stream;
stream << std::hex << hashValue(value);
return stream.str();
}
EditorResult<DocumentSnapshot> DocumentService::error(EditorStatus status, const char* rule, std::string message) {
return EditorResult<DocumentSnapshot>::error(status, RuleId(rule), std::move(message));
}