cocos-ts-plugin
v0.1.11
Published
TypeScript Language Service plugin that resolves `this.xxx` inside cocos2d-x / cocos2d-html5 cc.Class.extend({...}) literals — providing Go to Definition and hover info that tsserver alone can't compute.
Maintainers
Readme
cocos-ts-plugin
A TypeScript Language Service plugin that gives VS Code / any tsserver-based editor working Go-to-Definition and hover info for this.xxx inside cocos2d-x / cocos2d-html5 cc.Class.extend({...}) class literals.
Why
cocos2d-html5 defines classes through a cc.Class.extend(props) pattern. A typical class looks like:
let FlyingObject = cc.Node.extend({
delay: 0,
sourceNode: null,
resetFlyStats: function (sourceNode) {
this.sourceNode = sourceNode; // ← tsserver shows `any`, can't jump
this.callHelper(); // ← tsserver shows `any`, can't jump
},
callHelper: function () {}
});Out of the box, tsserver infers this inside the literal as any — Go-to-Definition fails and hover only shows any. Adding a .d.ts with ThisType<T> works in isolation, but breaks on real cocos2d-html5 source because of self-referential JSDoc (@param {cc.Node} inside the literal that defines cc.Node) and JS files that re-assign cc.Node as a plain object. tsserver gives up and falls back to any.
This plugin sidesteps the whole type-inference problem by hooking the Language Service directly: when you query something inside an X.extend({...}) literal, it walks the AST and resolves this.<member> against the literal's own properties.
Features
- Go to Definition:
Cmd/Ctrl-clickonthis.xxxjumps toxxx:in the same literal, and falls through to parent-class literals on cache miss (sothis.stopAllActions()inside acc.Node.extend({...})subclass jumps toCCNode.jswherecc.Node = cc.Class.extend({...})defines it). Also resolves:- dotted-namespace static accesses like
sp.SkeletonAnimation.createWithJsonFileorccui.Widget.TOUCH_ENDED, by indexing top-levela.b.c = ...assignments. Object-literal RHS values are flattened too, socc.Node = { addChild: function(){...} }style auto-binding stubs work. - chained accesses like
this.m_layout.setBackGroundColor(...)whenm_layout: ccui.Layout(orccui.layoutwith the project's lowercase type-hint convention) appears as a property in the extend literal. The receiver's class is inferred from the field's initializer and walked through its own extend chain. this.xxxinside classical-prototype methods (Foo.prototype.bar = function () { this.xxx /* here */ }). The plugin indexes<Class>.prototype.<m> = ...member assignments and<Class>.prototype = <Other>.prototype | new Other() | Object.create(Other.prototype)parent links, then walks the chain.
- dotted-namespace static accesses like
- Hover: shows
(method) xxx: (n: any) => numberor(property) xxx: 0with JSDoc, using the same resolution paths as definition. - Find All References: from either a
xxx:declaration or athis.xxxcall site, lists all matching property declarations andthis.xxxaccesses inside*.extend({...})literals across the project
All three augment tsserver's native answers only when those are empty/any-typed, so normal IntelliSense for non-cocos code is untouched.
Current limitations
- Find References is name-matched. It returns all extend-literal members named
xxxacross the project, regardless of whether they belong to the same class hierarchy. False positives are possible if unrelated classes share a method name.
Install
npm install --save-dev cocos-ts-pluginThen in your jsconfig.json (or tsconfig.json):
{
"compilerOptions": {
"plugins": [
{ "name": "cocos-ts-plugin" }
]
}
}VS Code setup
VS Code's bundled TypeScript does not load plugins from jsconfig.json automatically. Two ways to enable it:
Option A — Use the project's TypeScript (recommended)
npm install --save-dev typescriptThen Cmd+Shift+P → TypeScript: Select TypeScript Version → pick the workspace version.
Option B — Whitelist the plugin path globally
In .vscode/settings.json:
{
"typescript.tsserver.pluginPaths": [
"./node_modules/cocos-ts-plugin"
]
}After either option, Cmd+Shift+P → TypeScript: Restart TS Server.
Verify it loaded
Cmd+Shift+P → TypeScript: Open TS Server Log (you may need to set "typescript.tsserver.log": "verbose" first and restart). Grep for cocos-ts-plugin — you should see [cocos-ts-plugin] plugin loaded.
How it works
The plugin proxies three Language Service methods:
| Method | Behavior |
|---|---|
| getDefinitionAndBoundSpan | If tsserver returns no definitions, parse the source, locate the enclosing <X>.extend({...}) literal, and return the matching xxx: property as the definition. Walks the cached extend index up the parent chain on miss. Falls back to a cached expando index (a.b.c = … assignments) for dotted-namespace lookups. |
| getDefinitionAtPosition | Same. |
| getQuickInfoAtPosition | If tsserver returns any or nothing, build hover info from the property's value (function signature for function(){} initializers, inferred type otherwise) and emit its JSDoc. Walks the parent chain and expando index in the same way. |
| findReferences / getReferencesAtPosition | Scan every source file's <X>.extend({...}) literals and collect (a) properties named xxx, (b) this.xxx accesses inside such literals. Merged with and deduplicated against tsserver's native results. |
| getCompletionsAtPosition | After a ., enumerate members from the relevant index (current extend literal + parent chain for this.; resolved class for this.<field>. via type-hint convention; matching expando keys for dotted namespaces). Merged with tsserver's native results — when a name collides with a tsserver "warning" (low-confidence) entry, ours replaces it. |
The proxy never intercepts when tsserver already has a real answer, so it composes safely with @types packages, ThisType<T> hints, and any other type augmentation you might add.
Build from source
git clone https://github.com/williezou/cocos-ts-plugin.git
cd cocos-ts-plugin
npm install
npm run buildOutput lands in dist/.
Roadmap
- [x] Walk parent-class chain across files (
X = cc.Node.extend({...})→ resolvethis.getPositiontoCCNode.js) - [ ] Scope find-references to one class hierarchy (build the extend graph; today it's name-only)
- [ ] Auto-completion provider (
this.<TAB>lists literal members) - [ ] Handle
_super.xxx - [ ] Optional configuration: which extend-style method names to detect (
extend,create, …)
License
MIT
