Skip to content

自动加载的单例可能会导致插件部分功能崩溃(具体表现为Godot内置类的文档无法被打开,显示出现错误) #983

@QAQ-QAQbit

Description

@QAQ-QAQbit

Godot version

4.6.0

VS Code version

1.109.5

Godot Tools VS Code extension version

2.6.1

System information

Windos 11 25h2

Issue description

我并没有能力修复好这个bug,因此这个bug的修复全部来自GitHub Copilot
报错:TypeError: Cannot read properties of undefined (reading 'body')
表现:在打开Godot内置类的文档时,终端会输出错误信息,同时会出现无法打开的提示:Image

由GitHub Copilot总结的流程和修复思路:
1.读取 project.godot 的 [autoload] 段;
2.对每个值执行 URI 到文件的映射;
3.通过 LSP 请求 “native symbol” 数据,得到一个包含 children(属性、方法等)的对象;
4.把这个对象传给渲染函数 LP 和 n,生成 HTML。
当条目是 UID 格式时,扩展先在磁盘上找 .gd.uid 文件并映射到实际脚本路径;
但在某些情况下这个查找失败(比如尚未保存、缓存尚未更新、或者类本身就是引擎内置类),它就把 undefined 继续传给 LP。
LP 在遍历 r.children 时立刻假设 n(_) 返回的是合法对象,直接访问了 y.body,于是出现:TypeError: Cannot read properties of undefined (reading 'body')

修复思路:
1.在渲染子项前检查 y 是否为真。
2.在打开文档前确保 o(symbol info)不为 undefined,否则生成一个提示页面。

补丁代码(由GitHub Copilot给出,本地运行后成功修复了bug):
在插件的extension.js文件中
@@

  •    if(r.children)for(let _ of r.children){let y=n(_);switch(_.kind){case Rn.SymbolKind.Property:case Rn.SymbolKind.Variable:m+=nt("li",y.index),f+=nt("li",y.body,{id:_.name});break;case Rn.SymbolKind.Constant:a+=nt("li",y.body,{id:_.name});break;case Rn.SymbolKind.Event:c+=nt("li",y.body,{id:_.name});break;case Rn.SymbolKind.Method:case Rn.SymbolKind.Function:u+=nt("li",y.index),l+=nt("li",y.body,{id:_.name});break;default:g+=nt("li",y.body,{id:_.name});break}}
    
  •    if(r.children)for(let _ of r.children){
    
  •        let y = n(_);
    
  •        if(!y) continue;                    // <— skip invalid entries
    
  •        switch(_.kind){
    
  •        case Rn.SymbolKind.Property:case Rn.SymbolKind.Variable:
    
  •            m+=nt("li",y.index),f+=nt("li",y.body,{id:_.name});break;
    
  •        case Rn.SymbolKind.Constant:
    
  •            a+=nt("li",y.body,{id:_.name});break;
    
  •        case Rn.SymbolKind.Event:
    
  •            c+=nt("li",y.body,{id:_.name});break;
    
  •        case Rn.SymbolKind.Method:case Rn.SymbolKind.Function:
    
  •            u+=nt("li",y.index),l+=nt("li",y.body,{id:_.name});break;
    
  •        default:
    
  •            g+=nt("li",y.body,{id:_.name});break
    
  •        }
    
  •    }
    

@@

  •    this.htmlDb.has(i)||this.htmlDb.set(i,o0(t.webview,o,s));
    
  •    if(!o) {
    
  •        // symbol lookup failed – avoid crash by showing placeholder
    
  •        this.htmlDb.has(i)||
    
  •            this.htmlDb.set(i,
    
  •                `<html><body><p>No documentation available for ${i}</p></body></html>`);
    
  •    } else {
    
  •        this.htmlDb.has(i)||this.htmlDb.set(i,o0(t.webview,o,s));
    
  •    }
    

Steps to reproduce

我不太清楚具体要怎么复现,但是知道它和自动加载的单例有关,在我让GitHub Copilot修复这个bug时,它给出了可能的复现步骤,仅供参考:
创建一个新的 Godot 项目。
1.在 Project → Project Settings → Autoload 中添加一个单例,勾选 Use UID(或者添加后手动改为 *uid://…)。
2.在 VS Code 中打开该项目,并确保安装/启用 geequlim.godot-tools(2.6.1 或类似版本)。
3.尝试在编辑器中打开该单例类的文档(例如 Ctrl+点击脚本名),或简单地触发扩展的类浏览。
4.查看“输出”面板的 “Godot Tools” 部分,会看到如上 TypeError 并出现弹窗 “由于意外错误,无法打开编辑器”。

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions