Parser throws on tuple `@type` tags and `= {}` initializers, and silently drops unresolvable types
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 68/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- typescript
- 領域
- tooling
調査の方向性
src/parsers/script-parser.ts の extractAttributes() から始め、parseAttributes() を経由して到達するこの処理で、test/utils.ts に記載されている方法で playcanvas 型を読み込んだ状態で 3 つのスニペットを再現します。隣接する ParsingError パスを追跡し、タプル型、空のオブジェクト初期化子、解決できない @type 参照について回帰テストを追加します。これらのケースで処理が中断したり暗黙的に消えたりせず、有効な属性が引き続き解析されれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Found while investigating a forum report about the Interface Attribute Arrays docs example (docs fix: playcanvas/developer-site#1200). Interface arrays themselves work correctly — these are three separate robustness problems I hit while narrowing it down.
All three reproduce on main (fa36853, v1.11.0) through parseAttributes(), with the playcanvas types loaded as in test/utils.ts. Each snippet below is a complete script file.
1. TypeError when @type is a tuple
import { Script } from 'playcanvas';
class GameLogic extends Script {
static scriptName = 'gameLogic';
/**
* @attribute
* @type {[number]}
*/
values;
}
export { GameLogic };
TypeError: Cannot read properties of undefined (reading 'declarations')
at ScriptParser.extractAttributes
at JSDocParser.parseAttributes
src/parsers/script-parser.ts:497-498:
const symbol = type.aliasSymbol || type.symbol;
const typeNode = (symbol?.valueDeclaration || symbol.declarations?.[0]) as InternalNode;
A tuple type has no symbol, so symbol?.valueDeclaration is undefined and the second term dereferences undefined. symbol?.declarations?.[0] would fall through to the if (!typeNode) continue guard on the next line. Same for @type {[number, number]}.
2. TypeError when an attribute is initialized with an empty object literal
import { Script } from 'playcanvas';
class GameLogic extends Script {
static scriptName = 'gameLogic';
/**
* @attribute
*/
data = {};
}
export { GameLogic };
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
at Array.from (<anonymous>)
at ScriptParser.extractAttributes
at JSDocParser.parseAttributes
src/parsers/script-parser.ts:553-560:
const members: readonly ts.Node[] =
typeNode.members ??
typeNode.properties ??
Array.from(type.symbol.members as unknown as Iterable<[string, ts.Symbol]>).map(
(entry) => entry[1].declarations[0]
) ??
[];
For = {} both typeNode.members and typeNode.properties are nullish and type.symbol.members is undefined, so Array.from throws. Note the trailing ?? [] can never catch this, since the throw happens while evaluating the operand. data = { x: 1 } is fine — only the empty literal hits it.
This also fires for a member of an /** @interface */ class, e.g. data = {}; inside class Enemy.
Why 1 and 2 matter
Both throw out of extractAttributes, so the consumer gets no attributes and no diagnostics for the whole file instead of one error on the offending member. A half-written type annotation is a normal intermediate state while typing in the Editor's code editor, so these are easy to hit. Reporting a ParsingError for the member (as the neighbouring paths do) would keep the rest of the script parsing.
3. An unresolvable @type is dropped silently
import { Script } from 'playcanvas';
class GameLogic extends Script {
static scriptName = 'gameLogic';
/**
* @attribute
* @type {Enemy[]}
*/
enemies;
}
export { GameLogic };
With Enemy undefined (not declared, not imported, or a typo), parseAttributes() returns no attribute and no error; getAttributes() doesn't list the member either. Non-array @type {Enemy} behaves the same, as does @type {{}}.
The type resolves to TypeScript's error type, which has no symbol, so the if (!typeNode) continue at src/parsers/script-parser.ts:500 skips the member before any of the reporting paths below it run. An error type is detectable and could be reported with the existing "…" is not a valid attribute type message.
This is the one that makes a typo'd or missing Interface import hard to diagnose: the attribute just never appears in the Editor, with nothing in the editor's problem list to explain why.
- 主要言語
- TypeScript
- スター
- 1
- フォーク
- 3
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
playcanvas/attribute-parser のほかの issue
-
難易度 3/5 半日 初心者へのやさしさ 62/100
-
Dependency Dashboardオープン
難易度 4/5 3〜5日 初心者へのやさしさ 15/100
playcanvas/attribute-parser の issue をすべて見る
似ている issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 65/100
521xueweihan/HelloGitHub#4025 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
voidzero-dev/void#478 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 69/100
Small-tailqwq/dsh-deep-whale#207 ·
メンテナーはふだん 1 日以内に返信
-
The inspector never shows the instances field, so scaling out is unreachable対応中かも @Mrkewl が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
xevrion/breakscale#96 ·
メンテナーはふだん 4 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
Flux159/mcp-server-kubernetes#384 ·