hako_check: QuickFix (--fix-dry-run) expand to HC002 include→using, HC016 unused alias removal, HC014 entrypoint stub proposal; keep unified diff output
This commit is contained in:
@ -252,13 +252,59 @@ static box HakoAnalyzerBox {
|
||||
// ---- QuickFix (text scope, MVP: HC003 using quoted) ----
|
||||
_fix_text_quick(text) {
|
||||
if text == null { return null }
|
||||
// Only HC003: using 非引用→引用化
|
||||
// QuickFix (text scope):
|
||||
// - HC002 include → using
|
||||
// - HC003 using 非引用 → 引用化
|
||||
// - HC016 未使用 alias の削除(using ... as Alias)
|
||||
// - HC014 missing entrypoint の空スタブ提案
|
||||
local lines = me._split_lines(text)
|
||||
local changed = 0
|
||||
local out = new ArrayBox()
|
||||
// 事前: alias 宣言の収集(行番号と別名)
|
||||
local alias_lines = new ArrayBox() // of Map {idx, alias}
|
||||
local i = 0
|
||||
while i < lines.size() {
|
||||
local ln = lines.get(i)
|
||||
// HC002: include → using(相対→modulesの推測はしない;文字列そのまま移行)
|
||||
{
|
||||
local ltrim = me._ltrim(ln)
|
||||
if ltrim.indexOf("include \"") == 0 {
|
||||
// preserve indentation and trailing content (;等)
|
||||
local head_len = ln.indexOf("include \"")
|
||||
if head_len < 0 { head_len = 0 }
|
||||
local head = ln.substring(0, head_len)
|
||||
local rest = ln.substring(head_len)
|
||||
// rest begins with include "
|
||||
local after = rest.substring(8) // length("include ") = 8
|
||||
local newline = head + "using " + after
|
||||
if newline != ln { changed = 1; out.push(newline) } else { out.push(ln) }
|
||||
i = i + 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// HC016 用: using ... as Alias の抽出
|
||||
{
|
||||
local ltrim2 = me._ltrim(ln)
|
||||
if ltrim2.indexOf("using ") == 0 && ltrim2.indexOf(" as ") > 0 {
|
||||
// パターン: using "X" as Alias もしくは using X as Alias
|
||||
local aspos = ltrim2.indexOf(" as ")
|
||||
local tail = ltrim2.substring(aspos + 4)
|
||||
// Alias の終端は空白/セミコロン/行末
|
||||
local j = 0; local alias = ""
|
||||
while j < tail.length() {
|
||||
local ch = tail.substring(j,j+1)
|
||||
if ch == " " || ch == "\t" || ch == ";" { break }
|
||||
alias = alias + ch
|
||||
j = j + 1
|
||||
}
|
||||
if alias != "" {
|
||||
local ent = new MapBox(); ent.set("idx", i); ent.set("alias", alias); alias_lines.push(ent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HC003: using 非引用 → 引用化
|
||||
local ltrim = me._ltrim(ln)
|
||||
if ltrim.indexOf("using ") == 0 && ltrim.indexOf('using "') != 0 {
|
||||
// rewrite: using X ... -> using "X" ...(X は最初の空白/セミコロン/"as" まで)
|
||||
@ -289,11 +335,67 @@ static box HakoAnalyzerBox {
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
// HC016: 未使用 alias の削除(安全に、完全一致のみ削除)
|
||||
if alias_lines.size() > 0 {
|
||||
// 再結合した out を基にテキストを作り、使用有無チェック
|
||||
local cur_text = ""; local k=0; while k<out.size() { cur_text = cur_text + out.get(k); if k<out.size()-1 { cur_text = cur_text + "\n" } k=k+1 }
|
||||
// 逆順に処理して行番号のズレを回避
|
||||
local ai = alias_lines.size() - 1
|
||||
while ai >= 0 {
|
||||
local ent = alias_lines.get(ai)
|
||||
local idx = ent.get("idx")
|
||||
local alias = ent.get("alias")
|
||||
if me._alias_unused(cur_text, alias) == 1 {
|
||||
// remove that line from out if matches using ... as alias
|
||||
// ただし out の該当行が using でない場合はスキップ
|
||||
if idx >= 0 && idx < out.size() {
|
||||
local l = me._ltrim(out.get(idx))
|
||||
if l.indexOf("using ") == 0 && l.indexOf(" as ") > 0 && l.indexOf(" " + alias) > 0 {
|
||||
// delete
|
||||
out.set(idx, null)
|
||||
changed = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
ai = ai - 1
|
||||
}
|
||||
// null を除去
|
||||
local out2 = new ArrayBox(); local z=0; while z<out.size() { if out.get(z)!=null { out2.push(out.get(z)) } z=z+1 }
|
||||
out = out2
|
||||
}
|
||||
|
||||
// HC014: missing entrypoint → 空スタブ提案
|
||||
local joined = ""; local jj=0; while jj<out.size() { joined = joined + out.get(jj); if jj<out.size()-1 { joined = joined + "\n" } jj=jj+1 }
|
||||
if me._has_entrypoint(joined) == 0 {
|
||||
// append stub
|
||||
local stub = "\nstatic box Main { method main(args) { return 0 } }"
|
||||
joined = joined + stub
|
||||
changed = 1
|
||||
// split again for diff
|
||||
out = me._split_lines(joined)
|
||||
}
|
||||
|
||||
if changed == 0 { return text }
|
||||
// Join with \n
|
||||
local j = 0; local buf = ""; while j < out.size() { buf = buf + out.get(j); if j < out.size()-1 { buf = buf + "\n" } j = j + 1 }
|
||||
return buf
|
||||
}
|
||||
_alias_unused(text, alias) {
|
||||
if text == null || alias == null { return 0 }
|
||||
// 使用判定は保守的に: 'Alias.' / 'Alias(' / 'Alias ' / 'Alias::' のいずれかが存在すれば使用中とみなす
|
||||
local pats = new ArrayBox(); pats.push(alias+"."); pats.push(alias+"("); pats.push(alias+" "); pats.push(alias+"::")
|
||||
local i = 0; while i < pats.size() {
|
||||
if text.indexOf(pats.get(i)) >= 0 { return 0 }
|
||||
i = i + 1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
_has_entrypoint(text) {
|
||||
if text == null { return 1 }
|
||||
// Rough check: presence of 'method main(' is considered as entrypoint
|
||||
if text.indexOf("method main(") >= 0 { return 1 }
|
||||
return 0
|
||||
}
|
||||
_print_unified_diff(path, before, after) {
|
||||
if before == null || after == null || before == after { return 0 }
|
||||
// Minimal unified diff for whole file replacement(MVP)
|
||||
|
||||
Reference in New Issue
Block a user