mirror of
https://github.com/photonstorm/phaser
synced 2024-11-21 20:23:19 +00:00
Added in the TypeScript defs generator to the main repo
This commit is contained in:
parent
e902bfe346
commit
4e525492b8
18 changed files with 2514 additions and 915 deletions
1984
package-lock.json
generated
1984
package-lock.json
generated
File diff suppressed because it is too large
Load diff
16
package.json
16
package.json
|
@ -9,6 +9,7 @@
|
|||
"license": "MIT",
|
||||
"licenseUrl": "http://www.opensource.org/licenses/mit-license.php",
|
||||
"main": "./src/phaser.js",
|
||||
"types": "./types/phaser.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://photonstorm@github.com/photonstorm/phaser.git"
|
||||
|
@ -35,7 +36,12 @@
|
|||
"lintfix": "eslint --config .eslintrc.json \"src/**/*.js\" --fix",
|
||||
"sloc": "node-sloc \"./src\" --include-extensions \"js\"",
|
||||
"bundleshaders": "node scripts/bundle-shaders.js",
|
||||
"postinstall": "node scripts/support.js"
|
||||
"postinstall": "node scripts/support.js",
|
||||
"build-tsgen": "cd scripts/tsgen && tsc",
|
||||
"tsgen": "cd scripts/tsgen && jsdoc -c jsdoc-tsd.conf.json",
|
||||
"test-ts": "cd scripts/tsgen/test && tsc > output.txt",
|
||||
"ts": "npm run tsgen && npm run test-ts",
|
||||
"tsdev": "cd scripts/tsgen && tsc && jsdoc -c jsdoc-tsd.conf.json"
|
||||
},
|
||||
"keywords": [
|
||||
"2d",
|
||||
|
@ -53,7 +59,7 @@
|
|||
"clean-webpack-plugin": "^0.1.19",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-plugin-es5": "^1.3.1",
|
||||
"fs-extra": "^6.0.0",
|
||||
"fs-extra": "^6.0.1",
|
||||
"node-sloc": "^0.1.11",
|
||||
"uglifyjs-webpack-plugin": "^1.3.0",
|
||||
"vivid-cli": "^1.1.2",
|
||||
|
@ -62,8 +68,12 @@
|
|||
"webpack-shell-plugin": "^0.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dts-dom": "^3.2.0",
|
||||
"eventemitter3": "^3.1.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"imports-loader": "^0.8.0"
|
||||
"imports-loader": "^0.8.0",
|
||||
"jsdoc": "^3.6.1",
|
||||
"path": "^0.12.7",
|
||||
"typescript": "^3.4.5"
|
||||
}
|
||||
}
|
||||
|
|
507
scripts/tsgen/bin/Parser.js
Normal file
507
scripts/tsgen/bin/Parser.js
Normal file
|
@ -0,0 +1,507 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const dom = require("dts-dom");
|
||||
const regexEndLine = /^(.*)\r\n|\n|\r/gm;
|
||||
class Parser {
|
||||
constructor(docs) {
|
||||
// TODO remove once stable
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
let doclet = docs[i];
|
||||
if (doclet.longname && doclet.longname.indexOf('{') === 0) {
|
||||
doclet.longname = doclet.longname.substr(1);
|
||||
console.log(`Warning: had to fix wrong name for ${doclet.longname} in ${doclet.meta.filename}@${doclet.meta.lineno}`);
|
||||
}
|
||||
if (doclet.memberof && doclet.memberof.indexOf('{') === 0) {
|
||||
doclet.memberof = doclet.memberof.substr(1);
|
||||
console.log(`Warning: had to fix wrong name for ${doclet.longname} in ${doclet.meta.filename}@${doclet.meta.lineno}`);
|
||||
}
|
||||
}
|
||||
//////////////////////////
|
||||
this.topLevel = [];
|
||||
this.objects = {};
|
||||
this.namespaces = {};
|
||||
// parse doclets and create corresponding dom objects
|
||||
this.parseObjects(docs);
|
||||
this.resolveObjects(docs);
|
||||
// removes members inherited from classes
|
||||
// possibly could be avoided if mixins were defined as such before JSDoc parses them and then we could globally remove all inherited (not
|
||||
// overriden) members globally from the parsed DB
|
||||
this.resolveInheritance(docs);
|
||||
this.resolveParents(docs);
|
||||
// add integer alias
|
||||
this.topLevel.push(dom.create.alias('integer', dom.type.number));
|
||||
// add declare module
|
||||
const phaserPkgModuleDOM = dom.create.module('phaser');
|
||||
phaserPkgModuleDOM.members.push(dom.create.exportEquals('Phaser'));
|
||||
this.topLevel.push(phaserPkgModuleDOM);
|
||||
}
|
||||
emit() {
|
||||
let ignored = [];
|
||||
let result = this.topLevel.reduce((out, obj) => {
|
||||
// TODO: remove once stable
|
||||
if (obj.kind === 'property') {
|
||||
ignored.push(obj.name);
|
||||
return out;
|
||||
}
|
||||
//////////////////////////
|
||||
return out + dom.emit(obj);
|
||||
}, '');
|
||||
console.log('ignored top level properties:');
|
||||
console.log(ignored);
|
||||
return result;
|
||||
}
|
||||
parseObjects(docs) {
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
let doclet = docs[i];
|
||||
// if (doclet.kind === 'namespace')
|
||||
// {
|
||||
// console.log('module: ', doclet.name);
|
||||
// }
|
||||
// TODO: Custom temporary rules
|
||||
switch (doclet.longname) {
|
||||
case 'Phaser.GameObjects.Components.Alpha':
|
||||
case 'Phaser.GameObjects.Components.Animation':
|
||||
case 'Phaser.GameObjects.Components.BlendMode':
|
||||
case 'Phaser.GameObjects.Components.ComputedSize':
|
||||
case 'Phaser.GameObjects.Components.Crop':
|
||||
case 'Phaser.GameObjects.Components.Depth':
|
||||
case 'Phaser.GameObjects.Components.Flip':
|
||||
case 'Phaser.GameObjects.Components.GetBounds':
|
||||
case 'Phaser.GameObjects.Components.Mask':
|
||||
case 'Phaser.GameObjects.Components.Origin':
|
||||
case 'Phaser.GameObjects.Components.Pipeline':
|
||||
case 'Phaser.GameObjects.Components.ScaleMode':
|
||||
case 'Phaser.GameObjects.Components.ScrollFactor':
|
||||
case 'Phaser.GameObjects.Components.ScaleFactor':
|
||||
case 'Phaser.GameObjects.Components.Size':
|
||||
case 'Phaser.GameObjects.Components.Texture':
|
||||
case 'Phaser.GameObjects.Components.TextureCrop':
|
||||
case 'Phaser.GameObjects.Components.Tint':
|
||||
case 'Phaser.GameObjects.Components.ToJSON':
|
||||
case 'Phaser.GameObjects.Components.Transform':
|
||||
case 'Phaser.GameObjects.Components.Visible':
|
||||
doclet.kind = 'mixin';
|
||||
break;
|
||||
}
|
||||
if (doclet.longname == 'ModelViewProjection')
|
||||
doclet.kind = 'mixin';
|
||||
if ((doclet.longname.indexOf('Phaser.Physics.Arcade.Components.') == 0
|
||||
|| doclet.longname.indexOf('Phaser.Physics.Impact.Components.') == 0
|
||||
|| doclet.longname.indexOf('Phaser.Physics.Matter.Components.') == 0)
|
||||
&& doclet.longname.indexOf('#') == -1)
|
||||
doclet.kind = 'mixin';
|
||||
/////////////////////////
|
||||
let obj;
|
||||
let container = this.objects;
|
||||
switch (doclet.kind) {
|
||||
case 'namespace':
|
||||
obj = this.createNamespace(doclet);
|
||||
container = this.namespaces;
|
||||
break;
|
||||
case 'class':
|
||||
obj = this.createClass(doclet);
|
||||
break;
|
||||
case 'mixin':
|
||||
obj = this.createInterface(doclet);
|
||||
break;
|
||||
case 'member':
|
||||
if (doclet.isEnum === true) {
|
||||
obj = this.createEnum(doclet);
|
||||
break;
|
||||
}
|
||||
case 'constant':
|
||||
obj = this.createMember(doclet);
|
||||
break;
|
||||
case 'function':
|
||||
obj = this.createFunction(doclet);
|
||||
break;
|
||||
case 'typedef':
|
||||
obj = this.createTypedef(doclet);
|
||||
break;
|
||||
case 'event':
|
||||
obj = this.createEvent(doclet);
|
||||
break;
|
||||
default:
|
||||
console.log('Ignored doclet kind: ' + doclet.kind);
|
||||
break;
|
||||
}
|
||||
if (obj) {
|
||||
if (container[doclet.longname]) {
|
||||
console.log('Warning: ignoring duplicate doc name: ' + doclet.longname);
|
||||
docs.splice(i--, 1);
|
||||
continue;
|
||||
}
|
||||
container[doclet.longname] = obj;
|
||||
if (doclet.description) {
|
||||
let otherDocs = obj.jsDocComment || '';
|
||||
obj.jsDocComment = doclet.description.replace(regexEndLine, '$1\n') + otherDocs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resolveObjects(docs) {
|
||||
let allTypes = new Set();
|
||||
for (let doclet of docs) {
|
||||
let obj = doclet.kind === 'namespace' ? this.namespaces[doclet.longname] : this.objects[doclet.longname];
|
||||
if (!obj) {
|
||||
// TODO
|
||||
console.log(`Warning: Didn't find object for ${doclet.longname}`);
|
||||
continue;
|
||||
}
|
||||
if (!doclet.memberof) {
|
||||
this.topLevel.push(obj);
|
||||
}
|
||||
else {
|
||||
let isNamespaceMember = doclet.kind === 'class' || doclet.kind === 'typedef' || doclet.kind == 'namespace' || doclet.isEnum;
|
||||
let parent = isNamespaceMember ? this.namespaces[doclet.memberof] : (this.objects[doclet.memberof] || this.namespaces[doclet.memberof]);
|
||||
//TODO: this whole section should be removed once stable
|
||||
if (!parent) {
|
||||
console.log(`${doclet.longname} in ${doclet.meta.filename}@${doclet.meta.lineno} has parent '${doclet.memberof}' that is not defined.`);
|
||||
let parts = doclet.memberof.split('.');
|
||||
let newParts = [parts.pop()];
|
||||
while (parts.length > 0 && this.objects[parts.join('.')] == null)
|
||||
newParts.unshift(parts.pop());
|
||||
parent = this.objects[parts.join('.')];
|
||||
if (parent == null) {
|
||||
parent = dom.create.namespace(doclet.memberof);
|
||||
this.namespaces[doclet.memberof] = parent;
|
||||
this.topLevel.push(parent);
|
||||
}
|
||||
else {
|
||||
while (newParts.length > 0) {
|
||||
let oldParent = parent;
|
||||
parent = dom.create.namespace(newParts.shift());
|
||||
parts.push(parent.name);
|
||||
this.namespaces[parts.join('.')] = parent;
|
||||
oldParent.members.push(parent);
|
||||
parent._parent = oldParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////
|
||||
if (parent.members) {
|
||||
parent.members.push(obj);
|
||||
}
|
||||
else {
|
||||
console.log('Cannot find members array for:');
|
||||
console.log(parent);
|
||||
}
|
||||
obj._parent = parent;
|
||||
// class/interface members have methods, not functions
|
||||
if ((parent.kind === 'class' || parent.kind === 'interface')
|
||||
&& obj.kind === 'function')
|
||||
obj.kind = 'method';
|
||||
// namespace members are vars or consts, not properties
|
||||
if (parent.kind === 'namespace' && obj.kind === 'property') {
|
||||
if (doclet.kind == 'constant')
|
||||
obj.kind = 'const';
|
||||
else
|
||||
obj.kind = 'var';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resolveInheritance(docs) {
|
||||
for (let doclet of docs) {
|
||||
let obj = doclet.kind === 'namespace' ? this.namespaces[doclet.longname] : this.objects[doclet.longname];
|
||||
if (!obj) {
|
||||
// TODO
|
||||
console.log(`Didn't find type ${doclet.longname} ???`);
|
||||
continue;
|
||||
}
|
||||
if (!obj._parent)
|
||||
continue;
|
||||
if (doclet.inherited) { // remove inherited members if they aren't from an interface
|
||||
let from = this.objects[doclet.inherits];
|
||||
if (!from || !from._parent)
|
||||
throw `'${doclet.longname}' should inherit from '${doclet.inherits}', which is not defined.`;
|
||||
if (from._parent.kind != 'interface') {
|
||||
obj._parent.members.splice(obj._parent.members.indexOf(obj), 1);
|
||||
obj._parent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resolveParents(docs) {
|
||||
for (let doclet of docs) {
|
||||
let obj = this.objects[doclet.longname];
|
||||
if (!obj || doclet.kind !== 'class')
|
||||
continue;
|
||||
let o = obj;
|
||||
// resolve augments
|
||||
if (doclet.augments && doclet.augments.length) {
|
||||
for (let augment of doclet.augments) {
|
||||
let name = this.prepareTypeName(augment);
|
||||
let wrappingName = name.match(/[^<]+/s)[0]; //gets everything up to a first < (to handle augments with type parameters)
|
||||
let baseType = this.objects[wrappingName];
|
||||
if (!baseType) {
|
||||
console.log(`ERROR: Did not find base type: ${augment} for ${doclet.longname}`);
|
||||
}
|
||||
else {
|
||||
if (baseType.kind == 'class') {
|
||||
o.baseType = dom.create.class(name);
|
||||
}
|
||||
else {
|
||||
o.implements.push(dom.create.interface(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
createNamespace(doclet) {
|
||||
/**
|
||||
namespace: { comment: '',
|
||||
meta:
|
||||
{ filename: 'index.js',
|
||||
lineno: 10,
|
||||
columnno: 0,
|
||||
path: '/Users/rich/Documents/GitHub/phaser/src/tweens',
|
||||
code: {} },
|
||||
kind: 'namespace',
|
||||
name: 'Tweens',
|
||||
memberof: 'Phaser',
|
||||
longname: 'Phaser.Tweens',
|
||||
scope: 'static',
|
||||
___id: 'T000002R034468',
|
||||
___s: true }
|
||||
*/
|
||||
// console.log('namespace:', doclet.longname);
|
||||
let obj = dom.create.namespace(doclet.name);
|
||||
return obj;
|
||||
}
|
||||
createClass(doclet) {
|
||||
let obj = dom.create.class(doclet.name);
|
||||
let params = null;
|
||||
if (doclet.params) {
|
||||
let ctor = dom.create.constructor(null);
|
||||
this.setParams(doclet, ctor);
|
||||
params = ctor.parameters;
|
||||
obj.members.push(ctor);
|
||||
ctor._parent = obj;
|
||||
}
|
||||
this.processGeneric(doclet, obj, params);
|
||||
if (doclet.classdesc)
|
||||
doclet.description = doclet.classdesc.replace(regexEndLine, '$1\n'); // make sure docs will be added
|
||||
return obj;
|
||||
}
|
||||
createInterface(doclet) {
|
||||
return dom.create.interface(doclet.name);
|
||||
}
|
||||
createMember(doclet) {
|
||||
let type = this.parseType(doclet);
|
||||
let obj = dom.create.property(doclet.name, type);
|
||||
this.processGeneric(doclet, obj, null);
|
||||
this.processFlags(doclet, obj);
|
||||
return obj;
|
||||
}
|
||||
createEvent(doclet) {
|
||||
let type = this.parseType(doclet);
|
||||
let obj = dom.create.const(doclet.name, type);
|
||||
this.processFlags(doclet, obj);
|
||||
return obj;
|
||||
}
|
||||
createEnum(doclet) {
|
||||
let obj = dom.create.enum(doclet.name, false);
|
||||
this.processFlags(doclet, obj);
|
||||
return obj;
|
||||
}
|
||||
createFunction(doclet) {
|
||||
let returnType = dom.type.void;
|
||||
if (doclet.returns) {
|
||||
returnType = this.parseType(doclet.returns[0]);
|
||||
}
|
||||
let obj = dom.create.function(doclet.name, null, returnType);
|
||||
this.setParams(doclet, obj);
|
||||
this.processGeneric(doclet, obj, obj.parameters);
|
||||
this.processFlags(doclet, obj);
|
||||
return obj;
|
||||
}
|
||||
createTypedef(doclet) {
|
||||
const typeName = doclet.type.names[0];
|
||||
let type = null;
|
||||
if (doclet.type.names[0] === 'object') {
|
||||
let properties = [];
|
||||
for (let propDoc of doclet.properties) {
|
||||
let prop = this.createMember(propDoc);
|
||||
properties.push(prop);
|
||||
if (propDoc.description)
|
||||
prop.jsDocComment = propDoc.description.replace(regexEndLine, '$1\n');
|
||||
}
|
||||
type = dom.create.objectType(properties);
|
||||
if (doclet.augments && doclet.augments.length) {
|
||||
let intersectionTypes = [];
|
||||
for (let i = 0; i < doclet.augments.length; i++) {
|
||||
intersectionTypes.push(dom.create.namedTypeReference(doclet.augments[i]));
|
||||
}
|
||||
intersectionTypes.push(type);
|
||||
type = dom.create.intersection(intersectionTypes);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (doclet.type.names[0] == "function") {
|
||||
type = dom.create.functionType(null, dom.type.void);
|
||||
this.setParams(doclet, type);
|
||||
}
|
||||
else {
|
||||
type = this.parseType(doclet);
|
||||
}
|
||||
}
|
||||
let alias = dom.create.alias(doclet.name, type);
|
||||
this.processGeneric(doclet, alias, null);
|
||||
return alias;
|
||||
}
|
||||
setParams(doclet, obj) {
|
||||
let parameters = [];
|
||||
if (doclet.params) {
|
||||
let optional = false;
|
||||
obj.jsDocComment = '';
|
||||
for (let paramDoc of doclet.params) {
|
||||
// TODO REMOVE TEMP FIX
|
||||
if (paramDoc.name.indexOf('.') != -1) {
|
||||
console.log(`Warning: ignoring param with '.' for '${doclet.longname}' in ${doclet.meta.filename}@${doclet.meta.lineno}`);
|
||||
let defaultVal = paramDoc.defaultvalue !== undefined ? ` Default ${String(paramDoc.defaultvalue)}.` : '';
|
||||
if (paramDoc.description)
|
||||
obj.jsDocComment += `\n@param ${paramDoc.name} ${paramDoc.description.replace(regexEndLine, '$1\n')}` + defaultVal;
|
||||
else if (defaultVal.length)
|
||||
obj.jsDocComment += `\n@param ${paramDoc.name} ` + defaultVal;
|
||||
continue;
|
||||
}
|
||||
///////////////////////
|
||||
let param = dom.create.parameter(paramDoc.name, this.parseType(paramDoc));
|
||||
parameters.push(param);
|
||||
if (optional && paramDoc.optional != true) {
|
||||
console.log(`Warning: correcting to optional: parameter '${paramDoc.name}' for '${doclet.longname}' in ${doclet.meta.filename}@${doclet.meta.lineno}`);
|
||||
paramDoc.optional = true;
|
||||
}
|
||||
this.processFlags(paramDoc, param);
|
||||
optional = optional || paramDoc.optional === true;
|
||||
let defaultVal = paramDoc.defaultvalue !== undefined ? ` Default ${String(paramDoc.defaultvalue)}.` : '';
|
||||
if (paramDoc.description)
|
||||
obj.jsDocComment += `\n@param ${paramDoc.name} ${paramDoc.description.replace(regexEndLine, '$1\n')}` + defaultVal;
|
||||
else if (defaultVal.length)
|
||||
obj.jsDocComment += `\n@param ${paramDoc.name} ` + defaultVal;
|
||||
}
|
||||
}
|
||||
obj.parameters = parameters;
|
||||
}
|
||||
parseType(typeDoc) {
|
||||
if (!typeDoc || !typeDoc.type) {
|
||||
return dom.type.any;
|
||||
}
|
||||
else {
|
||||
let types = [];
|
||||
for (let name of typeDoc.type.names) {
|
||||
name = this.prepareTypeName(name);
|
||||
let type = dom.create.namedTypeReference(this.processTypeName(name));
|
||||
types.push(type);
|
||||
}
|
||||
if (types.length == 1)
|
||||
return types[0];
|
||||
else
|
||||
return dom.create.union(types);
|
||||
}
|
||||
}
|
||||
prepareTypeName(name) {
|
||||
if (name.indexOf('*') != -1) {
|
||||
name = name.split('*').join('any');
|
||||
}
|
||||
if (name.indexOf('.<') != -1) {
|
||||
name = name.split('.<').join('<');
|
||||
}
|
||||
return name;
|
||||
}
|
||||
processTypeName(name) {
|
||||
if (name === 'float')
|
||||
return 'number';
|
||||
if (name === 'function')
|
||||
return 'Function';
|
||||
if (name === 'array')
|
||||
return 'any[]';
|
||||
if (name.startsWith('Array<')) {
|
||||
let matches = name.match(/^Array<(.*)>$/);
|
||||
if (matches && matches[1]) {
|
||||
return this.processTypeName(matches[1]) + '[]';
|
||||
}
|
||||
}
|
||||
else if (name.startsWith('Object<')) {
|
||||
let matches = name.match(/^Object<(.*)>$/);
|
||||
if (matches && matches[1]) {
|
||||
if (matches[1].indexOf(',') != -1) {
|
||||
let parts = matches[1].split(',');
|
||||
return `{[key: ${this.processTypeName(parts[0])}]: ${this.processTypeName(parts[1])}}`;
|
||||
}
|
||||
else {
|
||||
return `{[key: string]: ${this.processTypeName(matches[1])}}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
processFlags(doclet, obj) {
|
||||
obj.flags = dom.DeclarationFlags.None;
|
||||
if (doclet.variable === true) {
|
||||
obj.flags |= dom.ParameterFlags.Rest;
|
||||
let type = obj.type;
|
||||
if (!type.name.endsWith('[]')) {
|
||||
if (type.name != 'any')
|
||||
console.log(`Warning: rest parameter should be an array type for ${doclet.longname}`);
|
||||
type.name = type.name + '[]'; // Must be an array
|
||||
}
|
||||
}
|
||||
else if (doclet.optional === true) { // Rest implies Optional – no need to flag it as such
|
||||
if (obj['kind'] === 'parameter')
|
||||
obj.flags |= dom.ParameterFlags.Optional;
|
||||
else
|
||||
obj.flags |= dom.DeclarationFlags.Optional;
|
||||
}
|
||||
switch (doclet.access) {
|
||||
case 'protected':
|
||||
obj.flags |= dom.DeclarationFlags.Protected;
|
||||
break;
|
||||
case 'private':
|
||||
obj.flags |= dom.DeclarationFlags.Private;
|
||||
break;
|
||||
}
|
||||
if (doclet.readonly || doclet.kind === 'constant')
|
||||
obj.flags |= dom.DeclarationFlags.ReadOnly;
|
||||
if (doclet.scope === 'static')
|
||||
obj.flags |= dom.DeclarationFlags.Static;
|
||||
}
|
||||
processGeneric(doclet, obj, params) {
|
||||
if (doclet.tags)
|
||||
for (let tag of doclet.tags) {
|
||||
if (tag.originalTitle === 'generic') {
|
||||
let matches = tag.value.match(/(?:(?:{)([^}]+)(?:}))?\s?([^\s]+)(?:\s?-\s?(?:\[)(.+)(?:\]))?/);
|
||||
let typeParam = dom.create.typeParameter(matches[2], matches[1] == null ? null : dom.create.typeParameter(matches[1]));
|
||||
obj.typeParameters.push(typeParam);
|
||||
handleOverrides(matches[3], matches[2]);
|
||||
}
|
||||
else if (tag.originalTitle === 'genericUse') {
|
||||
let matches = tag.value.match(/(?:(?:{)([^}]+)(?:}))(?:\s?-\s?(?:\[)(.+)(?:\]))?/);
|
||||
let overrideType = this.prepareTypeName(matches[1]);
|
||||
handleOverrides(matches[2], this.processTypeName(overrideType));
|
||||
}
|
||||
}
|
||||
function handleOverrides(matchedString, overrideType) {
|
||||
if (matchedString != null) {
|
||||
let overrides = matchedString.split(',');
|
||||
if (params != null) {
|
||||
for (let param of params) {
|
||||
if (overrides.indexOf(param.name) != -1) {
|
||||
param.type = dom.create.namedTypeReference(overrideType);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (overrides.indexOf('$return') != -1) { // has $return, must be a function
|
||||
obj.returnType = dom.create.namedTypeReference(overrideType);
|
||||
}
|
||||
if (overrides.indexOf('$type') != -1) { // has $type, must be a property
|
||||
obj.type = dom.create.namedTypeReference(overrideType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.Parser = Parser;
|
||||
//# sourceMappingURL=Parser.js.map
|
1
scripts/tsgen/bin/Parser.js.map
Normal file
1
scripts/tsgen/bin/Parser.js.map
Normal file
File diff suppressed because one or more lines are too long
25
scripts/tsgen/bin/publish.js
Normal file
25
scripts/tsgen/bin/publish.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs = require("fs-extra");
|
||||
const path = require("path");
|
||||
const Parser_1 = require("./Parser");
|
||||
function publish(data, opts) {
|
||||
// remove undocumented stuff.
|
||||
data({ undocumented: true }).remove();
|
||||
// remove package data
|
||||
data({ kind: 'package' }).remove();
|
||||
// remove header comments
|
||||
data({ copyright: { isString: true } }).remove();
|
||||
// remove private members
|
||||
data({ access: 'private' }).remove();
|
||||
// remove ignored doclets
|
||||
data({ ignore: true }).remove();
|
||||
if (!fs.existsSync(opts.destination)) {
|
||||
fs.mkdirSync(opts.destination);
|
||||
}
|
||||
var out = new Parser_1.Parser(data().get()).emit();
|
||||
fs.writeFileSync(path.join(opts.destination, 'phaser.d.ts'), out);
|
||||
}
|
||||
exports.publish = publish;
|
||||
;
|
||||
//# sourceMappingURL=publish.js.map
|
1
scripts/tsgen/bin/publish.js.map
Normal file
1
scripts/tsgen/bin/publish.js.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":";;AAAA,+BAA+B;AAC/B,6BAA6B;AAC7B,qCAAkC;AAElC,SAAgB,OAAO,CAAC,IAAS,EAAE,IAAS;IACxC,6BAA6B;IAC7B,IAAI,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACtC,sBAAsB;IACtB,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACnC,yBAAyB;IACzB,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACjD,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACrC,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IAEhC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;QAClC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;KAClC;IAED,IAAI,GAAG,GAAG,IAAI,eAAM,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAE1C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,CAAC;AACtE,CAAC;AAnBD,0BAmBC;AAAA,CAAC"}
|
71
scripts/tsgen/jsdoc-plugins/this.js
Normal file
71
scripts/tsgen/jsdoc-plugins/this.js
Normal file
|
@ -0,0 +1,71 @@
|
|||
var logger = require('jsdoc/util/logger');
|
||||
|
||||
exports.handlers = {
|
||||
|
||||
/*
|
||||
From:
|
||||
|
||||
"returns": [
|
||||
{
|
||||
"type": {
|
||||
"names": [
|
||||
"this"
|
||||
],
|
||||
"parsedType": {
|
||||
"type": "NameExpression",
|
||||
"name": "this",
|
||||
"reservedWord": true
|
||||
}
|
||||
},
|
||||
"description": "This Game Object instance."
|
||||
}
|
||||
],
|
||||
|
||||
To:
|
||||
|
||||
"returns": [
|
||||
{
|
||||
"type": {
|
||||
"names": [
|
||||
"Phaser.GameObjects.GameObject"
|
||||
],
|
||||
"parsedType": {
|
||||
"type": "NameExpression",
|
||||
"name": "Phaser.GameObjects.GameObject"
|
||||
}
|
||||
},
|
||||
"description": "This Game Object instance."
|
||||
}
|
||||
],
|
||||
|
||||
*/
|
||||
|
||||
// The processingComplete event is fired after JSDoc updates the parse results to reflect inherited and borrowed symbols.
|
||||
processingComplete: function (e)
|
||||
{
|
||||
var count = 0;
|
||||
|
||||
e.doclets.forEach(function(doclet) {
|
||||
|
||||
if (Array.isArray(doclet.returns))
|
||||
{
|
||||
var entry = doclet.returns[0];
|
||||
|
||||
if (entry.type.names[0] === 'this')
|
||||
{
|
||||
count++;
|
||||
entry.type.names[0] = doclet.memberof;
|
||||
}
|
||||
|
||||
if (entry.type.parsedType && entry.type.parsedType.name === 'this')
|
||||
{
|
||||
entry.type.parsedType.name = doclet.memberof;
|
||||
entry.type.parsedType.reservedWord = false;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// logger.warn('converted ' + count);
|
||||
}
|
||||
};
|
11
scripts/tsgen/jsdoc-plugins/typedef.js
Normal file
11
scripts/tsgen/jsdoc-plugins/typedef.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
exports.handlers = {
|
||||
beforeParse: function(e) {
|
||||
|
||||
// replace {?[type]} with {?any}
|
||||
e.source = e.source.replace(/{\?\[type\]}/g, '{any}');
|
||||
|
||||
// replace {[type]} with {any}
|
||||
e.source = e.source.replace(/{\[type\]}/g, '{any}');
|
||||
|
||||
}
|
||||
};
|
33
scripts/tsgen/jsdoc-tsd.conf.json
Normal file
33
scripts/tsgen/jsdoc-tsd.conf.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"tags": {
|
||||
"allowUnknownTags": true
|
||||
},
|
||||
"source": {
|
||||
"include": [
|
||||
"../../src/",
|
||||
"../../plugins/fbinstant"
|
||||
],
|
||||
"exclude": [
|
||||
"../../src/phaser-arcade-physics.js",
|
||||
"../../src/phaser-core.js",
|
||||
"../../src/physics/matter-js/poly-decomp/",
|
||||
"../../src/physics/matter-js/lib",
|
||||
"../../src/polyfills"
|
||||
],
|
||||
"includePattern": ".+\\.js?$",
|
||||
"excludePattern": "(^|\\/|\\\\)_"
|
||||
},
|
||||
"plugins": ["./jsdoc-plugins/typedef"],
|
||||
"opts": {
|
||||
"debug": true,
|
||||
"template": "./bin/",
|
||||
"encoding": "utf8",
|
||||
"destination": "../../types/",
|
||||
"outputSourceFiles": false,
|
||||
"outputSourcePath": true,
|
||||
"recurse": true,
|
||||
"private": false,
|
||||
"lenient": true,
|
||||
"sourceType": "script"
|
||||
}
|
||||
}
|
591
scripts/tsgen/src/Parser.ts
Normal file
591
scripts/tsgen/src/Parser.ts
Normal file
|
@ -0,0 +1,591 @@
|
|||
import * as dom from 'dts-dom';
|
||||
|
||||
const regexEndLine = /^(.*)\r\n|\n|\r/gm;
|
||||
|
||||
export class Parser {
|
||||
|
||||
topLevel: dom.TopLevelDeclaration[];
|
||||
objects: { [key: string]: dom.DeclarationBase };
|
||||
namespaces: { [key: string]: dom.NamespaceDeclaration };
|
||||
|
||||
constructor(docs: any[]) {
|
||||
|
||||
// TODO remove once stable
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
let doclet = docs[i];
|
||||
|
||||
if (doclet.longname && doclet.longname.indexOf('{') === 0) {
|
||||
doclet.longname = doclet.longname.substr(1);
|
||||
console.log(`Warning: had to fix wrong name for ${doclet.longname} in ${doclet.meta.filename}@${doclet.meta.lineno}`);
|
||||
}
|
||||
if (doclet.memberof && doclet.memberof.indexOf('{') === 0) {
|
||||
doclet.memberof = doclet.memberof.substr(1);
|
||||
console.log(`Warning: had to fix wrong name for ${doclet.longname} in ${doclet.meta.filename}@${doclet.meta.lineno}`);
|
||||
}
|
||||
}
|
||||
//////////////////////////
|
||||
|
||||
this.topLevel = [];
|
||||
this.objects = {};
|
||||
this.namespaces = {};
|
||||
|
||||
// parse doclets and create corresponding dom objects
|
||||
this.parseObjects(docs);
|
||||
|
||||
this.resolveObjects(docs);
|
||||
|
||||
// removes members inherited from classes
|
||||
// possibly could be avoided if mixins were defined as such before JSDoc parses them and then we could globally remove all inherited (not
|
||||
// overriden) members globally from the parsed DB
|
||||
this.resolveInheritance(docs);
|
||||
|
||||
this.resolveParents(docs);
|
||||
|
||||
// add integer alias
|
||||
this.topLevel.push(dom.create.alias('integer', dom.type.number));
|
||||
|
||||
// add declare module
|
||||
const phaserPkgModuleDOM = dom.create.module('phaser');
|
||||
phaserPkgModuleDOM.members.push(dom.create.exportEquals('Phaser'));
|
||||
this.topLevel.push(phaserPkgModuleDOM);
|
||||
}
|
||||
|
||||
emit() {
|
||||
let ignored = [];
|
||||
let result = this.topLevel.reduce((out: string, obj: dom.TopLevelDeclaration) => {
|
||||
// TODO: remove once stable
|
||||
if (<string>obj.kind === 'property') {
|
||||
ignored.push((<any>obj).name);
|
||||
return out;
|
||||
}
|
||||
//////////////////////////
|
||||
return out + dom.emit(obj);
|
||||
}, '');
|
||||
|
||||
console.log('ignored top level properties:');
|
||||
console.log(ignored);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private parseObjects(docs: any[]) {
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
|
||||
let doclet = docs[i];
|
||||
|
||||
// if (doclet.kind === 'namespace')
|
||||
// {
|
||||
// console.log('module: ', doclet.name);
|
||||
// }
|
||||
|
||||
// TODO: Custom temporary rules
|
||||
switch (doclet.longname) {
|
||||
case 'Phaser.GameObjects.Components.Alpha':
|
||||
case 'Phaser.GameObjects.Components.Animation':
|
||||
case 'Phaser.GameObjects.Components.BlendMode':
|
||||
case 'Phaser.GameObjects.Components.ComputedSize':
|
||||
case 'Phaser.GameObjects.Components.Crop':
|
||||
case 'Phaser.GameObjects.Components.Depth':
|
||||
case 'Phaser.GameObjects.Components.Flip':
|
||||
case 'Phaser.GameObjects.Components.GetBounds':
|
||||
case 'Phaser.GameObjects.Components.Mask':
|
||||
case 'Phaser.GameObjects.Components.Origin':
|
||||
case 'Phaser.GameObjects.Components.Pipeline':
|
||||
case 'Phaser.GameObjects.Components.ScaleMode':
|
||||
case 'Phaser.GameObjects.Components.ScrollFactor':
|
||||
case 'Phaser.GameObjects.Components.ScaleFactor':
|
||||
case 'Phaser.GameObjects.Components.Size':
|
||||
case 'Phaser.GameObjects.Components.Texture':
|
||||
case 'Phaser.GameObjects.Components.TextureCrop':
|
||||
case 'Phaser.GameObjects.Components.Tint':
|
||||
case 'Phaser.GameObjects.Components.ToJSON':
|
||||
case 'Phaser.GameObjects.Components.Transform':
|
||||
case 'Phaser.GameObjects.Components.Visible':
|
||||
doclet.kind = 'mixin';
|
||||
break;
|
||||
}
|
||||
if (doclet.longname == 'ModelViewProjection') doclet.kind = 'mixin';
|
||||
if ((doclet.longname.indexOf('Phaser.Physics.Arcade.Components.') == 0
|
||||
|| doclet.longname.indexOf('Phaser.Physics.Impact.Components.') == 0
|
||||
|| doclet.longname.indexOf('Phaser.Physics.Matter.Components.') == 0)
|
||||
&& doclet.longname.indexOf('#') == -1)
|
||||
doclet.kind = 'mixin';
|
||||
/////////////////////////
|
||||
|
||||
let obj: dom.DeclarationBase;
|
||||
let container = this.objects;
|
||||
|
||||
switch (doclet.kind) {
|
||||
case 'namespace':
|
||||
obj = this.createNamespace(doclet);
|
||||
container = this.namespaces;
|
||||
break;
|
||||
case 'class':
|
||||
obj = this.createClass(doclet);
|
||||
break;
|
||||
case 'mixin':
|
||||
obj = this.createInterface(doclet);
|
||||
break;
|
||||
case 'member':
|
||||
if (doclet.isEnum === true) {
|
||||
obj = this.createEnum(doclet);
|
||||
break;
|
||||
}
|
||||
case 'constant':
|
||||
obj = this.createMember(doclet);
|
||||
break;
|
||||
case 'function':
|
||||
obj = this.createFunction(doclet);
|
||||
break;
|
||||
case 'typedef':
|
||||
obj = this.createTypedef(doclet);
|
||||
break;
|
||||
case 'event':
|
||||
obj = this.createEvent(doclet);
|
||||
break;
|
||||
default:
|
||||
console.log('Ignored doclet kind: ' + doclet.kind);
|
||||
break;
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
if (container[doclet.longname]) {
|
||||
console.log('Warning: ignoring duplicate doc name: ' + doclet.longname);
|
||||
docs.splice(i--, 1);
|
||||
continue;
|
||||
}
|
||||
container[doclet.longname] = obj;
|
||||
if (doclet.description) {
|
||||
let otherDocs = obj.jsDocComment || '';
|
||||
obj.jsDocComment = doclet.description.replace(regexEndLine, '$1\n') + otherDocs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private resolveObjects(docs: any[]) {
|
||||
let allTypes = new Set<string>();
|
||||
for (let doclet of docs) {
|
||||
let obj = doclet.kind === 'namespace' ? this.namespaces[doclet.longname] : this.objects[doclet.longname];
|
||||
|
||||
if (!obj) {
|
||||
|
||||
// TODO
|
||||
console.log(`Warning: Didn't find object for ${doclet.longname}`);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!doclet.memberof) {
|
||||
this.topLevel.push(obj as dom.TopLevelDeclaration);
|
||||
} else {
|
||||
let isNamespaceMember = doclet.kind === 'class' || doclet.kind === 'typedef' || doclet.kind == 'namespace' || doclet.isEnum;
|
||||
let parent = isNamespaceMember ? this.namespaces[doclet.memberof] : (this.objects[doclet.memberof] || this.namespaces[doclet.memberof]);
|
||||
|
||||
//TODO: this whole section should be removed once stable
|
||||
if (!parent) {
|
||||
console.log(`${doclet.longname} in ${doclet.meta.filename}@${doclet.meta.lineno} has parent '${doclet.memberof}' that is not defined.`);
|
||||
let parts: string[] = doclet.memberof.split('.');
|
||||
let newParts = [parts.pop()];
|
||||
while (parts.length > 0 && this.objects[parts.join('.')] == null) newParts.unshift(parts.pop());
|
||||
parent = this.objects[parts.join('.')] as dom.NamespaceDeclaration;
|
||||
if (parent == null) {
|
||||
parent = dom.create.namespace(doclet.memberof);
|
||||
this.namespaces[doclet.memberof] = <dom.NamespaceDeclaration>parent;
|
||||
this.topLevel.push(<dom.NamespaceDeclaration>parent);
|
||||
} else {
|
||||
while (newParts.length > 0) {
|
||||
let oldParent = <dom.NamespaceDeclaration>parent;
|
||||
parent = dom.create.namespace(newParts.shift());
|
||||
parts.push((<dom.NamespaceDeclaration>parent).name);
|
||||
this.namespaces[parts.join('.')] = <dom.NamespaceDeclaration>parent;
|
||||
oldParent.members.push(<dom.NamespaceDeclaration>parent);
|
||||
(<any>parent)._parent = oldParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
if ((<any>parent).members) {
|
||||
(<any>parent).members.push(obj);
|
||||
} else {
|
||||
console.log('Cannot find members array for:');
|
||||
console.log(parent);
|
||||
}
|
||||
|
||||
(<any>obj)._parent = parent;
|
||||
|
||||
// class/interface members have methods, not functions
|
||||
if (((parent as any).kind === 'class' || (parent as any).kind === 'interface')
|
||||
&& (obj as any).kind === 'function')
|
||||
(obj as any).kind = 'method';
|
||||
// namespace members are vars or consts, not properties
|
||||
if ((parent as any).kind === 'namespace' && (obj as any).kind === 'property') {
|
||||
if (doclet.kind == 'constant') (obj as any).kind = 'const';
|
||||
else (obj as any).kind = 'var';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private resolveInheritance(docs: any[]) {
|
||||
for (let doclet of docs) {
|
||||
let obj = doclet.kind === 'namespace' ? this.namespaces[doclet.longname] : this.objects[doclet.longname];
|
||||
if (!obj) {
|
||||
|
||||
// TODO
|
||||
console.log(`Didn't find type ${doclet.longname} ???`);
|
||||
|
||||
continue;
|
||||
}
|
||||
if (!(<any>obj)._parent) continue;
|
||||
|
||||
if (doclet.inherited) {// remove inherited members if they aren't from an interface
|
||||
let from = this.objects[doclet.inherits];
|
||||
if (!from || !(<any>from)._parent)
|
||||
throw `'${doclet.longname}' should inherit from '${doclet.inherits}', which is not defined.`;
|
||||
|
||||
if ((<any>from)._parent.kind != 'interface') {
|
||||
(<any>obj)._parent.members.splice((<any>obj)._parent.members.indexOf(obj), 1);
|
||||
(<any>obj)._parent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private resolveParents(docs: any[]) {
|
||||
for (let doclet of docs) {
|
||||
let obj = this.objects[doclet.longname];
|
||||
if (!obj || doclet.kind !== 'class') continue;
|
||||
|
||||
let o = obj as dom.ClassDeclaration;
|
||||
|
||||
// resolve augments
|
||||
if (doclet.augments && doclet.augments.length) {
|
||||
for (let augment of doclet.augments) {
|
||||
let name: string = this.prepareTypeName(augment);
|
||||
|
||||
let wrappingName = name.match(/[^<]+/s)[0];//gets everything up to a first < (to handle augments with type parameters)
|
||||
|
||||
let baseType = this.objects[wrappingName] as dom.ClassDeclaration | dom.InterfaceDeclaration;
|
||||
|
||||
if (!baseType) {
|
||||
console.log(`ERROR: Did not find base type: ${augment} for ${doclet.longname}`);
|
||||
} else {
|
||||
if (baseType.kind == 'class') {
|
||||
o.baseType = dom.create.class(name);
|
||||
} else {
|
||||
o.implements.push(dom.create.interface(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private createNamespace(doclet: any): dom.NamespaceDeclaration {
|
||||
|
||||
/**
|
||||
namespace: { comment: '',
|
||||
meta:
|
||||
{ filename: 'index.js',
|
||||
lineno: 10,
|
||||
columnno: 0,
|
||||
path: '/Users/rich/Documents/GitHub/phaser/src/tweens',
|
||||
code: {} },
|
||||
kind: 'namespace',
|
||||
name: 'Tweens',
|
||||
memberof: 'Phaser',
|
||||
longname: 'Phaser.Tweens',
|
||||
scope: 'static',
|
||||
___id: 'T000002R034468',
|
||||
___s: true }
|
||||
*/
|
||||
|
||||
// console.log('namespace:', doclet.longname);
|
||||
|
||||
let obj = dom.create.namespace(doclet.name);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private createClass(doclet: any): dom.ClassDeclaration {
|
||||
let obj = dom.create.class(doclet.name);
|
||||
|
||||
let params = null;
|
||||
if (doclet.params) {
|
||||
let ctor = dom.create.constructor(null);
|
||||
this.setParams(doclet, ctor);
|
||||
params = ctor.parameters;
|
||||
|
||||
obj.members.push(ctor);
|
||||
(<any>ctor)._parent = obj;
|
||||
}
|
||||
|
||||
this.processGeneric(doclet, obj, params);
|
||||
|
||||
if (doclet.classdesc)
|
||||
doclet.description = doclet.classdesc.replace(regexEndLine, '$1\n'); // make sure docs will be added
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private createInterface(doclet: any): dom.InterfaceDeclaration {
|
||||
return dom.create.interface(doclet.name);
|
||||
}
|
||||
|
||||
private createMember(doclet: any): dom.PropertyDeclaration {
|
||||
let type = this.parseType(doclet);
|
||||
|
||||
let obj = dom.create.property(doclet.name, type);
|
||||
|
||||
this.processGeneric(doclet, obj, null);
|
||||
|
||||
this.processFlags(doclet, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private createEvent(doclet: any): dom.ConstDeclaration {
|
||||
|
||||
let type = this.parseType(doclet);
|
||||
|
||||
let obj = dom.create.const(doclet.name, type);
|
||||
|
||||
this.processFlags(doclet, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private createEnum(doclet: any): dom.EnumDeclaration {
|
||||
let obj = dom.create.enum(doclet.name, false);
|
||||
|
||||
this.processFlags(doclet, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private createFunction(doclet: any): dom.FunctionDeclaration {
|
||||
let returnType: dom.Type = dom.type.void;
|
||||
|
||||
if (doclet.returns) {
|
||||
returnType = this.parseType(doclet.returns[0]);
|
||||
}
|
||||
|
||||
let obj = dom.create.function(doclet.name, null, returnType);
|
||||
this.setParams(doclet, obj);
|
||||
|
||||
this.processGeneric(doclet, obj, obj.parameters);
|
||||
|
||||
this.processFlags(doclet, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private createTypedef(doclet: any): dom.TypeAliasDeclaration {
|
||||
const typeName = doclet.type.names[0];
|
||||
let type = null;
|
||||
|
||||
if (doclet.type.names[0] === 'object') {
|
||||
let properties = [];
|
||||
|
||||
for (let propDoc of doclet.properties) {
|
||||
let prop = this.createMember(propDoc);
|
||||
properties.push(prop);
|
||||
if (propDoc.description)
|
||||
prop.jsDocComment = propDoc.description.replace(regexEndLine, '$1\n');
|
||||
}
|
||||
|
||||
type = dom.create.objectType(properties);
|
||||
|
||||
if (doclet.augments && doclet.augments.length) {
|
||||
let intersectionTypes = [];
|
||||
for (let i = 0; i < doclet.augments.length; i++) {
|
||||
intersectionTypes.push(dom.create.namedTypeReference(doclet.augments[i]));
|
||||
}
|
||||
intersectionTypes.push(type);
|
||||
type = dom.create.intersection(intersectionTypes);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (doclet.type.names[0] == "function") {
|
||||
type = dom.create.functionType(null, dom.type.void);
|
||||
this.setParams(doclet, type);
|
||||
} else {
|
||||
type = this.parseType(doclet);
|
||||
}
|
||||
}
|
||||
|
||||
let alias = dom.create.alias(doclet.name, type);
|
||||
|
||||
this.processGeneric(doclet, alias, null);
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
private setParams(doclet: any, obj: dom.FunctionDeclaration | dom.ConstructorDeclaration): void {
|
||||
let parameters: dom.Parameter[] = [];
|
||||
|
||||
if (doclet.params) {
|
||||
|
||||
let optional = false;
|
||||
|
||||
obj.jsDocComment = '';
|
||||
|
||||
for (let paramDoc of doclet.params) {
|
||||
|
||||
// TODO REMOVE TEMP FIX
|
||||
if (paramDoc.name.indexOf('.') != -1) {
|
||||
console.log(`Warning: ignoring param with '.' for '${doclet.longname}' in ${doclet.meta.filename}@${doclet.meta.lineno}`);
|
||||
|
||||
let defaultVal = paramDoc.defaultvalue !== undefined ? ` Default ${String(paramDoc.defaultvalue)}.` : '';
|
||||
if (paramDoc.description)
|
||||
obj.jsDocComment += `\n@param ${paramDoc.name} ${paramDoc.description.replace(regexEndLine, '$1\n')}` + defaultVal;
|
||||
else if (defaultVal.length)
|
||||
obj.jsDocComment += `\n@param ${paramDoc.name} ` + defaultVal;
|
||||
continue;
|
||||
}
|
||||
///////////////////////
|
||||
|
||||
let param = dom.create.parameter(paramDoc.name, this.parseType(paramDoc));
|
||||
parameters.push(param);
|
||||
|
||||
if (optional && paramDoc.optional != true) {
|
||||
console.log(`Warning: correcting to optional: parameter '${paramDoc.name}' for '${doclet.longname}' in ${doclet.meta.filename}@${doclet.meta.lineno}`);
|
||||
paramDoc.optional = true;
|
||||
}
|
||||
|
||||
this.processFlags(paramDoc, param);
|
||||
|
||||
optional = optional || paramDoc.optional === true;
|
||||
|
||||
let defaultVal = paramDoc.defaultvalue !== undefined ? ` Default ${String(paramDoc.defaultvalue)}.` : '';
|
||||
|
||||
if (paramDoc.description)
|
||||
obj.jsDocComment += `\n@param ${paramDoc.name} ${paramDoc.description.replace(regexEndLine, '$1\n')}` + defaultVal;
|
||||
else if (defaultVal.length)
|
||||
obj.jsDocComment += `\n@param ${paramDoc.name} ` + defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
obj.parameters = parameters;
|
||||
}
|
||||
|
||||
private parseType(typeDoc: any): dom.Type {
|
||||
if (!typeDoc || !typeDoc.type) {
|
||||
return dom.type.any;
|
||||
} else {
|
||||
let types = [];
|
||||
for (let name of typeDoc.type.names) {
|
||||
|
||||
name = this.prepareTypeName(name);
|
||||
|
||||
let type = dom.create.namedTypeReference(this.processTypeName(name));
|
||||
|
||||
types.push(type);
|
||||
}
|
||||
if (types.length == 1) return types[0];
|
||||
else return dom.create.union(types);
|
||||
}
|
||||
}
|
||||
|
||||
private prepareTypeName(name: string): string {
|
||||
if (name.indexOf('*') != -1) {
|
||||
name = (<string>name).split('*').join('any');
|
||||
}
|
||||
if (name.indexOf('.<') != -1) {
|
||||
name = (<string>name).split('.<').join('<');
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private processTypeName(name: string): string {
|
||||
if (name === 'float') return 'number';
|
||||
if (name === 'function') return 'Function';
|
||||
if (name === 'array') return 'any[]';
|
||||
|
||||
if (name.startsWith('Array<')) {
|
||||
let matches = name.match(/^Array<(.*)>$/);
|
||||
|
||||
if (matches && matches[1]) {
|
||||
return this.processTypeName(matches[1]) + '[]';
|
||||
}
|
||||
} else if (name.startsWith('Object<')) {
|
||||
let matches = name.match(/^Object<(.*)>$/);
|
||||
|
||||
if (matches && matches[1]) {
|
||||
if (matches[1].indexOf(',') != -1) {
|
||||
let parts = matches[1].split(',');
|
||||
return `{[key: ${this.processTypeName(parts[0])}]: ${this.processTypeName(parts[1])}}`;
|
||||
} else {
|
||||
return `{[key: string]: ${this.processTypeName(matches[1])}}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
private processFlags(doclet: any, obj: dom.DeclarationBase | dom.Parameter) {
|
||||
obj.flags = dom.DeclarationFlags.None;
|
||||
if (doclet.variable === true) {
|
||||
obj.flags |= dom.ParameterFlags.Rest;
|
||||
let type: any = (<dom.Parameter>obj).type;
|
||||
if (!type.name.endsWith('[]')) {
|
||||
if (type.name != 'any')
|
||||
console.log(`Warning: rest parameter should be an array type for ${doclet.longname}`);
|
||||
type.name = type.name + '[]'; // Must be an array
|
||||
}
|
||||
} else if (doclet.optional === true) {// Rest implies Optional – no need to flag it as such
|
||||
if (obj['kind'] === 'parameter') obj.flags |= dom.ParameterFlags.Optional;
|
||||
else obj.flags |= dom.DeclarationFlags.Optional;
|
||||
}
|
||||
switch (doclet.access) {
|
||||
case 'protected':
|
||||
obj.flags |= dom.DeclarationFlags.Protected;
|
||||
break;
|
||||
case 'private':
|
||||
obj.flags |= dom.DeclarationFlags.Private;
|
||||
break;
|
||||
}
|
||||
if (doclet.readonly || doclet.kind === 'constant') obj.flags |= dom.DeclarationFlags.ReadOnly;
|
||||
if (doclet.scope === 'static') obj.flags |= dom.DeclarationFlags.Static;
|
||||
}
|
||||
|
||||
private processGeneric(doclet: any, obj: dom.ClassDeclaration | dom.FunctionDeclaration | dom.PropertyDeclaration | dom.TypeAliasDeclaration, params: dom.Parameter[]) {
|
||||
if (doclet.tags)
|
||||
for (let tag of doclet.tags) {
|
||||
if (tag.originalTitle === 'generic') {
|
||||
let matches = (<string>tag.value).match(/(?:(?:{)([^}]+)(?:}))?\s?([^\s]+)(?:\s?-\s?(?:\[)(.+)(?:\]))?/);
|
||||
let typeParam = dom.create.typeParameter(matches[2], matches[1] == null ? null : dom.create.typeParameter(matches[1]));
|
||||
(<dom.ClassDeclaration | dom.FunctionDeclaration | dom.TypeAliasDeclaration>obj).typeParameters.push(typeParam);
|
||||
handleOverrides(matches[3], matches[2]);
|
||||
} else if (tag.originalTitle === 'genericUse') {
|
||||
let matches = (<string>tag.value).match(/(?:(?:{)([^}]+)(?:}))(?:\s?-\s?(?:\[)(.+)(?:\]))?/);
|
||||
let overrideType: string = this.prepareTypeName(matches[1]);
|
||||
|
||||
handleOverrides(matches[2], this.processTypeName(overrideType));
|
||||
}
|
||||
}
|
||||
|
||||
function handleOverrides(matchedString: string, overrideType: string) {
|
||||
if (matchedString != null) {
|
||||
let overrides = matchedString.split(',');
|
||||
if (params != null) {
|
||||
for (let param of params) {
|
||||
if (overrides.indexOf(param.name) != -1) {
|
||||
param.type = dom.create.namedTypeReference(overrideType);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (overrides.indexOf('$return') != -1) {// has $return, must be a function
|
||||
(<dom.FunctionDeclaration>obj).returnType = dom.create.namedTypeReference(overrideType);
|
||||
}
|
||||
if (overrides.indexOf('$type') != -1) {// has $type, must be a property
|
||||
(<dom.PropertyDeclaration>obj).type = dom.create.namedTypeReference(overrideType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
24
scripts/tsgen/src/publish.ts
Normal file
24
scripts/tsgen/src/publish.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import { Parser } from './Parser';
|
||||
|
||||
export function publish(data: any, opts: any) {
|
||||
// remove undocumented stuff.
|
||||
data({ undocumented: true }).remove();
|
||||
// remove package data
|
||||
data({ kind: 'package' }).remove();
|
||||
// remove header comments
|
||||
data({ copyright: { isString: true } }).remove();
|
||||
// remove private members
|
||||
data({ access: 'private' }).remove();
|
||||
// remove ignored doclets
|
||||
data({ ignore: true }).remove();
|
||||
|
||||
if (!fs.existsSync(opts.destination)) {
|
||||
fs.mkdirSync(opts.destination);
|
||||
}
|
||||
|
||||
var out = new Parser(data().get()).emit();
|
||||
|
||||
fs.writeFileSync(path.join(opts.destination, 'phaser.d.ts'), out);
|
||||
};
|
63
scripts/tsgen/test/bin/game.js
Normal file
63
scripts/tsgen/test/bin/game.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var MyScene = /** @class */ (function (_super) {
|
||||
__extends(MyScene, _super);
|
||||
function MyScene() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
MyScene.prototype.preload = function () {
|
||||
this.load.atlas('cards', 'assets/atlas/cards.png', 'assets/atlas/cards.json');
|
||||
};
|
||||
MyScene.prototype.create = function () {
|
||||
var sprite = this.add.sprite(400, 300, 'cards', 'clubs3');
|
||||
sprite.setInteractive();
|
||||
this.input.on('pointerdown', function () {
|
||||
sprite.setFrame('hearts4');
|
||||
});
|
||||
};
|
||||
return MyScene;
|
||||
}(Phaser.Scene));
|
||||
var config = {
|
||||
type: Phaser.AUTO,
|
||||
parent: 'phaser-example',
|
||||
width: 800,
|
||||
height: 600,
|
||||
scene: MyScene
|
||||
};
|
||||
var game = new Phaser.Game(config);
|
||||
var scene = new Phaser.Scene("");
|
||||
var blitter = new Phaser.GameObjects.Blitter(scene, 10, 10);
|
||||
var conf = {
|
||||
type: Phaser.AUTO,
|
||||
width: 100,
|
||||
height: 100,
|
||||
zoom: 1,
|
||||
resolution: 1
|
||||
};
|
||||
var tex = null;
|
||||
tex.source[0].setFilter(Phaser.Textures.FilterMode.LINEAR);
|
||||
tex.setFilter(Phaser.Textures.FilterMode.LINEAR);
|
||||
tex.setFilter(Phaser.Textures.NEAREST);
|
||||
var sprite = new Phaser.GameObjects.Sprite(scene, 0, 0, "test");
|
||||
var MyVec = /** @class */ (function (_super) {
|
||||
__extends(MyVec, _super);
|
||||
function MyVec() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
MyVec.prototype.extra = function () {
|
||||
};
|
||||
return MyVec;
|
||||
}(Phaser.Geom.Rectangle));
|
||||
var p = new MyVec();
|
||||
sprite.getBounds(p).extra();
|
||||
var container = scene.add.container(0, 0);
|
||||
container.getWorldTransformMatrix();
|
||||
//# sourceMappingURL=game.js.map
|
1
scripts/tsgen/test/bin/game.js.map
Normal file
1
scripts/tsgen/test/bin/game.js.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"game.js","sourceRoot":"","sources":["../src/game.ts","../src/game2.ts"],"names":[],"mappings":";;;;;;;;;;AAAA;IAAsB,2BAAY;IAAlC;;IAoBA,CAAC;IAlBU,yBAAO,GAAd;QAEI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,CAAC,CAAC;IAClF,CAAC;IAEM,wBAAM,GAAb;QAEI,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QAE1D,MAAM,CAAC,cAAc,EAAE,CAAC;QAExB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,aAAa,EAAE;YAEzB,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAE/B,CAAC,CAAC,CAAC;IACP,CAAC;IAEL,cAAC;AAAD,CAAC,AApBD,CAAsB,MAAM,CAAC,KAAK,GAoBjC;AAED,IAAI,MAAM,GAAG;IACT,IAAI,EAAE,MAAM,CAAC,IAAI;IACjB,MAAM,EAAE,gBAAgB;IACxB,KAAK,EAAE,GAAG;IACV,MAAM,EAAE,GAAG;IACX,KAAK,EAAE,OAAO;CACjB,CAAC;AAEF,IAAI,IAAI,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AC7BnC,IAAI,KAAK,GAAgB,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAE9C,IAAI,OAAO,GAAG,IAAI,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAE5D,IAAI,IAAI,GAAc;IAClB,IAAI,EAAC,MAAM,CAAC,IAAI;IAChB,KAAK,EAAE,GAAG;IACV,MAAM,EAAE,GAAG;IACX,IAAI,EAAE,CAAC;IACP,UAAU,EAAE,CAAC;CAChB,CAAA;AAED,IAAI,GAAG,GAAgC,IAAI,CAAC;AAE5C,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAE3D,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACjD,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAEvC,IAAI,MAAM,GAAG,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;AAEhE;IAAoB,yBAAqB;IAAzC;;IAMA,CAAC;IAJU,qBAAK,GAAZ;IAEA,CAAC;IAEL,YAAC;AAAD,CAAC,AAND,CAAoB,MAAM,CAAC,IAAI,CAAC,SAAS,GAMxC;AACD,IAAI,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC;AAEpB,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;AAE5B,IAAI,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1C,SAAS,CAAC,uBAAuB,EAAE,CAAC"}
|
0
scripts/tsgen/test/output.txt
Normal file
0
scripts/tsgen/test/output.txt
Normal file
31
scripts/tsgen/test/src/game.ts
Normal file
31
scripts/tsgen/test/src/game.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
class MyScene extends Phaser.Scene {
|
||||
|
||||
public preload ()
|
||||
{
|
||||
this.load.atlas('cards', 'assets/atlas/cards.png', 'assets/atlas/cards.json');
|
||||
}
|
||||
|
||||
public create ()
|
||||
{
|
||||
let sprite = this.add.sprite(400, 300, 'cards', 'clubs3');
|
||||
|
||||
sprite.setInteractive();
|
||||
|
||||
this.input.on('pointerdown', function () {
|
||||
|
||||
sprite.setFrame('hearts4');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let config = {
|
||||
type: Phaser.AUTO,
|
||||
parent: 'phaser-example',
|
||||
width: 800,
|
||||
height: 600,
|
||||
scene: MyScene
|
||||
};
|
||||
|
||||
let game = new Phaser.Game(config);
|
35
scripts/tsgen/test/src/game2.ts
Normal file
35
scripts/tsgen/test/src/game2.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
|
||||
let scene:Phaser.Scene = new Phaser.Scene("");
|
||||
|
||||
let blitter = new Phaser.GameObjects.Blitter(scene, 10, 10);
|
||||
|
||||
let conf:GameConfig = {
|
||||
type:Phaser.AUTO,
|
||||
width: 100,
|
||||
height: 100,
|
||||
zoom: 1,
|
||||
resolution: 1
|
||||
}
|
||||
|
||||
let tex:Phaser.Textures.Texture = <any>null;
|
||||
|
||||
tex.source[0].setFilter(Phaser.Textures.FilterMode.LINEAR);
|
||||
|
||||
tex.setFilter(Phaser.Textures.FilterMode.LINEAR);
|
||||
tex.setFilter(Phaser.Textures.NEAREST);
|
||||
|
||||
let sprite = new Phaser.GameObjects.Sprite(scene, 0, 0, "test");
|
||||
|
||||
class MyVec extends Phaser.Geom.Rectangle {
|
||||
|
||||
public extra() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
let p = new MyVec();
|
||||
|
||||
sprite.getBounds(p).extra();
|
||||
|
||||
let container = scene.add.container(0, 0);
|
||||
container.getWorldTransformMatrix();
|
19
scripts/tsgen/test/tsconfig.json
Normal file
19
scripts/tsgen/test/tsconfig.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "system",
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"noImplicitThis": true,
|
||||
"noImplicitReturns": true,
|
||||
"preserveConstEnums": true,
|
||||
"outFile": "./bin/game.js",
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": [
|
||||
"src/*",
|
||||
"../../../types/phaser.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
16
scripts/tsgen/tsconfig.json
Normal file
16
scripts/tsgen/tsconfig.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"version": "0.0.1",
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"declaration": false,
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": true,
|
||||
"outDir": "./bin/"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"./node_modules/@types/**/*.d.ts"
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue