Files
whetstone_DSL/editor/src/BufferOpsProjection.h
Bill 976161dc4a Steps 266-268: Phase 10a — semantic annotation core + sidecar persistence (32/32 tests)
Step 266: 5 semantic annotation AST types (Intent, Complexity, Risk,
Contract, SemanticTag) with JSON roundtrip and compact AST integration.
Step 267: Sidecar AST persistence (.whetstone/<file>.ast.json) with
save/load/list RPC methods, MCP tools, and permission enforcement.
Step 268: Phase 10a integration tests — multi-file sidecar workflow,
all 5 types in compact view, idempotent roundtrip, source isolation.

Also includes Sprint 10 plan, GUI/installer polish, and Emacs integration fixes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 16:01:56 +00:00

90 lines
3.4 KiB
C++

#pragma once
// --- BufferOpsProjection.h ---
// Extracted from BufferOps.h (Sprint 8 cleanup).
// Projection and diff helpers.
// Included from BufferOps.h after the EditorState struct definition.
inline void EditorState::projectToLanguage(const std::string& targetLanguage) {
if (!active()) return;
Module* ast = activeAST();
if (!ast) {
notify(NotificationLevel::Error,
"Project to " + targetLanguage + ": no AST available.");
return;
}
CrossLanguageProjector projector;
auto projected = projector.project(ast, targetLanguage);
if (!projected) {
notify(NotificationLevel::Error,
"Project to " + targetLanguage + ": failed to project AST.");
return;
}
const int srcAnnoCount = countAnnotationNodes(ast);
const int projAnnoCount = countAnnotationNodes(projected.get());
const bool preserved = projector.annotationsPreserved(ast, projected.get());
std::string generated = generateForLanguage(projected.get(), targetLanguage);
std::string baseName = "(untitled-projection:" + targetLanguage + ")";
std::string projName = baseName;
int suffix = 1;
while (buffers.hasBuffer(projName)) {
projName = baseName + "-" + std::to_string(suffix++);
}
createBuffer(projName, generated, targetLanguage, defaultBufferMode());
if (active()) {
active()->readOnly = true;
active()->sync.setText(generated, targetLanguage);
active()->sync.setAST(std::move(projected));
active()->incrementalOptimizer.setRoot(active()->sync.getAST());
active()->editBuf = generated;
active()->editor.setContent(active()->editBuf, targetLanguage);
active()->mode.setLanguage(targetLanguage);
active()->highlightsDirty = true;
active()->generatedLanguage = targetLanguage;
active()->generatedMode.setLanguage(targetLanguage);
active()->generatedHighlightsDirty = true;
active()->modified = false;
}
notify(NotificationLevel::Success,
"Projected to " + targetLanguage + " in " + projName +
" (annotations " + std::to_string(srcAnnoCount) + " -> " +
std::to_string(projAnnoCount) + ", types preserved: " +
(preserved ? "yes" : "no") + ").");
}
inline void EditorState::refreshActiveTextFromAST() {
if (!active()) return;
if (!isStructured()) return;
active()->editBuf = active()->sync.getText();
active()->editor.setContent(active()->editBuf, active()->language);
active()->highlightsDirty = true;
active()->highlightRequestTime = ImGui::GetTime();
active()->modified = true;
queueLspDidChange();
analysisPending = true;
analysisLastChange = ImGui::GetTime();
}
inline void EditorState::openDiff(const std::string& beforeText,
const std::string& afterText,
bool preview,
int action,
const std::vector<std::string>& transformIds,
const std::vector<BatchMutationAPI::Mutation>& batchMutations) {
diff.active = true;
diff.preview = preview;
diff.action = action;
diff.batch = !batchMutations.empty();
diff.beforeText = beforeText;
diff.afterText = afterText;
diff.transformIds = transformIds;
diff.batchMutations = batchMutations;
LineDiff lineDiff = buildLineDiff(beforeText, afterText);
diff.beforeLines = std::move(lineDiff.beforeLines);
diff.afterLines = std::move(lineDiff.afterLines);
}