Skip to content
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
325 changes: 315 additions & 10 deletions mjbase/src/mjbase/renamer/shadow_token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ void appendRepairAction(ShadowSlotError error, std::string& text)
break;
case ShadowSlotError::AmbiguousMember:
text += "; supply the raw descriptor to disambiguate the overload "
"(descriptor token grammar lands later; pass the raw descriptor for now)";
"(descriptor slots accept embedded class handles; "
"three-part member handles are future work)";
break;
case ShadowSlotError::MissingSidecar:
text += "; generate a shadow sidecar first (MCP shadow_generate, or `mjt shadow -i <jar>`)";
Expand Down Expand Up @@ -303,16 +304,13 @@ ShadowSlotResult resolveShadowSlot(const ShadowAliasTable& table,
const std::string& input,
const ShadowSlotQuery& query)
{
if (query.position != ShadowSlotPosition::Name) {
// 未接线分支占位:descriptor / jasm body 标识槽文法未接,fail-loud
// 防意外提前使用;后续扩展在本收口内替换本分支,不开新入口。
return failure(ShadowSlotError::MalformedHandle,
std::string(query.position == ShadowSlotPosition::Descriptor
? "descriptor"
: "jasm-body") +
" slot does not accept shadow references yet (planned); "
"pass the raw form for now");
if (query.position == ShadowSlotPosition::Descriptor) {
return resolveShadowDescriptor(table, input);
}
if (query.position == ShadowSlotPosition::JasmBody) {
return resolveShadowJasmBody(table, input);
}
// 其余位置:Name(缺省);无未接线分支。

const auto parts = parseShadowRef(input);
switch (parts.form) {
Expand Down Expand Up @@ -350,6 +348,313 @@ ShadowSlotResult resolveShadowSlot(const ShadowAliasTable& table,
return failure(ShadowSlotError::MalformedHandle, "unreachable reference form");
}


ShadowSlotResult resolveShadowDescriptor(const ShadowAliasTable& table,
const std::string& input)
{
ShadowSlotResult result;
std::string out;
std::size_t cursor = 0;
ca::usize expansions = 0;

// 单遍词法走查 + 轻量描述符文法校验(垃圾入 fail-loud,不静默替换)。
// 返回 true = 校验与展开完成(result.raw 就绪);false = 已填 Malformed
// 类失败。
const auto emitTypeSegment = [&]() -> bool {
// 前置 '[' 已由调用方消费;此处 input[cursor] ∈ {基类型, 'L', 'V'?}。
const char c = input[cursor];
if (c == 'L') {
++cursor;
const auto nameBegin = cursor;
while (cursor < input.size() && input[cursor] != ';') {
// 泛型签名标记:fail-loud(Sig 属性 v2 另批)。
if (input[cursor] == '<' || input[cursor] == '>') {
result = failure(ShadowSlotError::MalformedHandle,
"generic signature marker '" + std::string(1, input[cursor]) +
"' inside descriptor " + quoted(input) +
" is not accepted by the descriptor slot (planned); "
"pass the erased descriptor");
return false;
}
++cursor;
}
if (cursor >= input.size()) {
result = failure(ShadowSlotError::MalformedHandle,
"unterminated object type segment in descriptor " +
quoted(input));
return false;
}
const auto content = input.substr(nameBegin, cursor - nameBegin);
++cursor; // ';'
const auto parts = parseShadowRef(content);
switch (parts.form) {
case ShadowRefForm::Raw:
out += 'L';
out += content;
out += ';';
break;
case ShadowRefForm::EscapedLiteral:
// 字面请求:剥 $ 后的段按普通类名输出(与 Name 槽剥皮语义一致)。
out += 'L';
out += parts.literal;
out += ';';
break;
case ShadowRefForm::ClassRef: {
ShadowSlotResult entryResult;
const auto entry =
resolveShadowHandleEntry(table, std::string(content), entryResult);
if (!entry.has_value()) {
result = std::move(entryResult);
return false;
}
out += 'L';
out += entry->rawName;
out += ';';
++expansions;
break;
}
case ShadowRefForm::MemberRef:
result = failure(ShadowSlotError::MalformedHandle,
"member reference " + quoted(content) +
" cannot appear in a type position of descriptor " +
quoted(input));
return false;
case ShadowRefForm::Malformed:
result = failure(ShadowSlotError::MalformedHandle,
"malformed reference " + quoted(content) +
" inside descriptor " + quoted(input));
return false;
}
return true;
}
// 基类型(含 V 的调用方约束在外面)。
static constexpr std::string_view kPrimitives = "BCDFIJSZ";
if (kPrimitives.find(c) == std::string_view::npos) {
result = failure(ShadowSlotError::MalformedHandle,
"byte " + std::string(1, c) + " at offset " +
std::to_string(cursor) + " does not fit a descriptor: " +
quoted(input));
return false;
}
out += c;
++cursor;
return true;
};

const auto parseFieldType = [&]() -> bool {
while (cursor < input.size() && input[cursor] == '[') {
out += '[';
++cursor;
}
return emitTypeSegment();
};

bool ok = false;
if (cursor < input.size() && input[cursor] == '(') {
// 方法描述符:( 参数类型* ) 返回类型(V 或字段类型)。
out += '(';
++cursor;
while (cursor < input.size() && input[cursor] != ')') {
if (!parseFieldType()) return result;
}
if (cursor >= input.size()) {
result = failure(ShadowSlotError::MalformedHandle,
"unterminated parameter list in descriptor " + quoted(input));
return result;
}
out += ')';
++cursor;
if (cursor < input.size() && input[cursor] == 'V') {
out += 'V';
++cursor;
}
else {
ok = parseFieldType();
if (!ok) return result;
}
}
else {
ok = parseFieldType();
if (!ok) return result;
}
if (cursor != input.size()) {
result = failure(ShadowSlotError::MalformedHandle,
"trailing bytes after descriptor " + quoted(input) + " at offset " +
std::to_string(cursor));
return result;
}
result.error = ShadowSlotError::None;
result.raw = std::move(out);
result.fromHandle = expansions > 0;
return result;
}


ShadowSlotResult resolveShadowJasmBody(const ShadowAliasTable& table,
const std::string& input)
{
ShadowSlotResult result;
if (input.empty()) {
result.raw = input;
result.error = ShadowSlotError::None;
return result;
}

// ── 尾随描述符切分 ──
std::string refPart;
std::string descPart; // 括号内(方法)或尾 token(字段);空 = 无
std::string separator; // 引用部与描述符之间的原样分隔(" (" / " ")
bool hasDesc = false;
if (input.back() == ')') {
const auto paren = input.rfind(" (");
if (paren == std::string::npos || paren + 2 >= input.size() - 1) {
return failure(ShadowSlotError::MalformedHandle,
"operand '" + brief(input) +
"' ends with ')' but has no ' (desc)' group");
}
refPart = input.substr(0, paren);
descPart = input.substr(paren + 2, input.size() - paren - 3);
separator = " (";
hasDesc = true;
}
else {
const auto space = input.rfind(' ');
if (space != std::string::npos && space + 1 < input.size()) {
refPart = input.substr(0, space);
descPart = input.substr(space + 1);
separator = " ";
hasDesc = true;
}
else {
refPart = input;
}
}

// ── 引用部解析 ──
// 产物:resolvedRef(替换后引用部);expansions 计数。
// 分派序:整体 parseShadowRef(ClassRef/MemberRef/EscapedLiteral 直达);
// Malformed 且带 '${' 前缀 → 复合拆分(首个 '}' 前 = owner handle,余部
// ".name");其余 Raw(owner.name 复合或纯裸名零漂移直通)。
std::string resolvedRef;
ca::usize expansions = 0;

// name 段:裸名直通;嵌套 MemberRef handle 展开并核验与 raw owner 自洽。
// 失败时已填 result,返回 false。
const auto resolveNamePart = [&](const std::string& namePart,
const std::string& rawOwner,
std::string& out) -> bool {
if (namePart.rfind("${", 0) != 0) {
out = namePart;
return true;
}
if (parseShadowRef(namePart).form != ShadowRefForm::MemberRef) {
result = failure(ShadowSlotError::MalformedHandle,
"malformed member handle in jasm operand: " +
quoted(namePart));
return false;
}
ShadowSlotResult entryResult;
const auto entry = resolveShadowHandleEntry(table, namePart, entryResult);
if (!entry.has_value()) {
result = std::move(entryResult);
return false;
}
if (entry->owner != rawOwner) {
result = failure(ShadowSlotError::MalformedHandle,
"member handle owner " + brief(entry->owner) +
" conflicts with operand owner " + brief(rawOwner));
return false;
}
out = entry->rawName;
++expansions;
return true;
};

const auto parts = parseShadowRef(refPart);
if (parts.form == ShadowRefForm::ClassRef) {
ShadowSlotResult entryResult;
const auto entry = resolveShadowHandleEntry(table, refPart, entryResult);
if (!entry.has_value()) return entryResult;
resolvedRef = entry->rawName;
++expansions;
}
else if (parts.form == ShadowRefForm::MemberRef) {
// 整体成员句柄:展开为 rawOwner.rawName 复合。
ShadowSlotResult entryResult;
const auto entry = resolveShadowHandleEntry(table, refPart, entryResult);
if (!entry.has_value()) return entryResult;
resolvedRef = std::string(entry->owner) + "." + std::string(entry->rawName);
++expansions;
}
else if (parts.form == ShadowRefForm::EscapedLiteral) {
resolvedRef = parts.literal;
}
else if (parts.form == ShadowRefForm::Malformed && refPart.rfind("${", 0) == 0) {
// 复合拆分:首个 '}' 前为 owner handle(须 ClassRef 形状);表查询
// 错误原样直传——unknown-handle 不得被复合语境吞成 malformed。
const auto close = refPart.find('}');
if (close == std::string::npos) {
return failure(ShadowSlotError::MalformedHandle,
"malformed reference " + quoted(refPart) +
" in jasm operand (no closing brace)");
}
const auto handlePart = refPart.substr(0, close + 1);
const auto rest = refPart.substr(close + 1);
if (rest.empty() || rest[0] != '.') {
return failure(ShadowSlotError::MalformedHandle,
"malformed reference " + quoted(refPart) +
" in jasm operand (expected .name after handle)");
}
if (parseShadowRef(handlePart).form != ShadowRefForm::ClassRef) {
return failure(ShadowSlotError::MalformedHandle,
"malformed owner handle " + quoted(handlePart) +
" in jasm operand");
}
ShadowSlotResult ownerResult;
const auto ownerEntry =
resolveShadowHandleEntry(table, handlePart, ownerResult);
if (!ownerEntry.has_value()) return ownerResult;
const std::string rawOwner(ownerEntry->rawName);
std::string resolvedName;
if (!resolveNamePart(rest.substr(1), rawOwner, resolvedName)) return result;
resolvedRef = rawOwner + "." + resolvedName;
++expansions;
}
else if (parts.form == ShadowRefForm::Malformed) {
return failure(ShadowSlotError::MalformedHandle,
"malformed reference " + quoted(refPart) + " in jasm operand");
}
else {
// Raw:复合 owner.name(name 可嵌 MemberRef handle)或纯裸名。
const auto dot = refPart.find('.');
if (dot == std::string::npos) {
resolvedRef = refPart; // 类操作数裸名:零漂移直通
}
else {
const auto ownerPart = refPart.substr(0, dot);
const auto namePart = refPart.substr(dot + 1);
std::string resolvedName;
if (!resolveNamePart(namePart, ownerPart, resolvedName)) return result;
resolvedRef = ownerPart + "." + resolvedName;
}
}

// ── 描述符部展开 ──
std::string resolvedDesc;
if (hasDesc) {
const auto descResult = resolveShadowDescriptor(table, descPart);
if (descResult.error != ShadowSlotError::None) return descResult;
resolvedDesc = descResult.raw;
if (descResult.fromHandle) ++expansions;
}

result.error = ShadowSlotError::None;
result.raw = resolvedRef + separator + (hasDesc ? resolvedDesc : "") +
(separator == " (" ? ")" : "");
result.fromHandle = expansions > 0;
return result;
}

std::string shadowRefHandleOf(const ShadowAliasTable& table, const ShadowAliasEntry& entry)
{
const std::string token(entry.token8);
Expand Down
Loading
Loading