Files
whetstone_DSL/editor/src/SCIPEmitter.h
Bill 94f61dc97c Sprints 273-276: Polyglot FFI Glue, Symbol Index, and LSP Proxy (steps 1893-1912)
Sprint 273 — PolyglotFFIGlueGenerator (steps 1893-1897):
  ABIBoundaryExtractor, CHeaderEmitter, RustPythonBindingEmitter,
  GoCppBindingEmitter. Extracts exported symbols from toComponent provider
  and emits C ABI + language-specific bindings.

Sprint 274 — More Binding Pairs + DWARF (steps 1898-1902):
  CppJSBindingEmitter (N-API), RustGoBindingEmitter (#[no_mangle]),
  DWARFBoundaryAnnotator (DW_TAG_* + crossLangBoundary),
  FFIGlueDispatcher (routes by fromLang→toLang pair),
  MCP tool whetstone_generate_ffi_glue (#92).

Sprint 275 — Cross-Language Symbol Index (steps 1903-1907):
  SCIPEmitter (SCIP JSON, one doc/language, caller+provider roles),
  CrossLanguageSymbolTable (byLangName_ + byScip_ dual index),
  SymbolIndexUpdater (nodeKey diff, clear-and-rebuild),
  SymbolIndexOrchestrator (orchestrate + update),
  MCP tool whetstone_emit_symbol_index (#93).

Sprint 276 — LSP Proxy Core (steps 1908-1912):
  LSPProxyServer (JSON-RPC 2.0 dispatcher),
  LanguageServerRouter (routeByUri/routeByLanguageId),
  CrossLanguageBoundaryDetector (detect/detectWithUri/detectInLanguage),
  CrossLanguageDefinitionResolver (resolve/resolveFromUri → DefinitionLocation).
  End-to-end: Python call site goto-def resolves to Rust sort-core provider.

100/100 tests passing across all four sprints. Architecture gate clean.
LoRA sessions recorded for all sprints (~14k tokens captured).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 18:41:32 -07:00

62 lines
2.0 KiB
C++

#pragma once
#include "ABIBoundaryExtractor.h"
#include <nlohmann/json.hpp>
#include <map>
#include <string>
#include <vector>
namespace whetstone {
class SCIPEmitter {
public:
// Emit a SCIP-format index for the given boundary nodes.
// Returns: {"schemaVersion":"0.1", "documents":[{language, uri, symbols:[...]}, ...]}
// Each node appears in both its fromLanguage and toLanguage documents.
static nlohmann::json emit(const std::vector<ABIBoundaryNode>& nodes) {
// language → document stub
struct DocStub {
std::string uri;
nlohmann::json symbols = nlohmann::json::array();
};
std::map<std::string, DocStub> docs;
for (const auto& node : nodes) {
// Provider side (toLanguage document)
auto& toDoc = docs[node.toLanguage];
if (toDoc.uri.empty()) toDoc.uri = "scip://" + node.toComponent;
toDoc.symbols.push_back(makeSymbol(node, "provider"));
// Caller side (fromLanguage document)
auto& fromDoc = docs[node.fromLanguage];
if (fromDoc.uri.empty()) fromDoc.uri = "scip://" + node.fromComponent;
fromDoc.symbols.push_back(makeSymbol(node, "caller"));
}
nlohmann::json docArray = nlohmann::json::array();
for (auto& [lang, stub] : docs) {
docArray.push_back({
{"language", lang},
{"uri", stub.uri},
{"symbols", stub.symbols}
});
}
return {{"schemaVersion", "0.1"}, {"documents", docArray}};
}
private:
static nlohmann::json makeSymbol(const ABIBoundaryNode& node,
const std::string& role) {
return {
{"name", node.name},
{"kind", node.kind},
{"fromComponent", node.fromComponent},
{"toComponent", node.toComponent},
{"role", role},
{"scipSymbol", node.toComponent + "/" + node.name + "."}
};
}
};
} // namespace whetstone