Skip to content

Commit

Permalink
Parse types.
Browse files Browse the repository at this point in the history
  • Loading branch information
jjrv committed Mar 23, 2016
1 parent 90e5b77 commit 22a6306
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 10 deletions.
4 changes: 3 additions & 1 deletion src/ClassSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import * as ts from 'typescript';
import * as readts from './readts';

export class ClassSpec {
constructor(name: string, doc: string) {
constructor(name: string, symbol: ts.Symbol, doc: string) {
this.name = name;
this.symbol = symbol;
if(doc) this.doc = doc;
}

Expand All @@ -29,6 +30,7 @@ export class ClassSpec {
}

name: string;
symbol: ts.Symbol;
construct: readts.FunctionSpec;
methodList: readts.FunctionSpec[];
propertyList: readts.IdentifierSpec[];
Expand Down
5 changes: 3 additions & 2 deletions src/IdentifierSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
// Released under the MIT license, see LICENSE.

import * as ts from 'typescript';
import * as readts from './readts';

/** Property, function / method parameter or variable. */

export class IdentifierSpec {
constructor(name: string, type: string, doc: string) {
constructor(name: string, type: readts.TypeSpec, doc: string) {
this.name = name;
this.type = type;
if(doc) this.doc = doc;
Expand All @@ -15,7 +16,7 @@ export class IdentifierSpec {
/** Identifier name. */
name: string;
/** Type in TypeScript syntax. */
type: string;
type: readts.TypeSpec;
/** Interface members and function / method parameters may be optional. */
optional: boolean;
/** JSDoc comment. */
Expand Down
35 changes: 30 additions & 5 deletions src/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export class Parser {

this.program = ts.createProgram(config.fileNames, config.options);
this.checker = this.program.getTypeChecker();
this.moduleList = [];
this.symbolTbl = {};

for(var source of this.program.getSourceFiles()) {
// Skip contents of default library.
Expand All @@ -37,10 +39,30 @@ export class Parser {
return(this.moduleList);
}

private formatType(type: ts.Type) {
typeToString(type: ts.Type) {
return(this.checker.typeToString(type));
}

private addSymbol(name: string, data: any) {
if(!this.symbolTbl[name]) this.symbolTbl[name] = [];

this.symbolTbl[name].push(data);
}

getSymbol(symbol: ts.Symbol) {
for(var match of this.symbolTbl[symbol.getName()] || []) {
if(symbol == match.symbol) return(match);
}

return(null);
}

private formatType(type: ts.Type) {
var spec = new readts.TypeSpec(type, this);

return(spec);
}

private parseModule(node: ts.Node) {
var spec = new readts.ModuleSpec();

Expand Down Expand Up @@ -100,7 +122,9 @@ export class Parser {
}

private parseClass(spec: SymbolSpec) {
var classSpec = new readts.ClassSpec(spec.name, spec.doc);
var classSpec = new readts.ClassSpec(spec.name, spec.symbol, spec.doc);

this.addSymbol(spec.name, classSpec);

for(var signature of spec.type.getConstructSignatures()) {
classSpec.addConstructor(this.parseSignature(signature));
Expand Down Expand Up @@ -167,7 +191,8 @@ export class Parser {
);
}

program: ts.Program;
checker: ts.TypeChecker;
moduleList: readts.ModuleSpec[] = [];
private program: ts.Program;
private checker: ts.TypeChecker;
private moduleList: readts.ModuleSpec[];
private symbolTbl: { [name: string]: any[] };
}
4 changes: 2 additions & 2 deletions src/SignatureSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as ts from 'typescript';
import * as readts from './readts';

export class SignatureSpec {
constructor(returnType: string, doc: string) {
constructor(returnType: readts.TypeSpec, doc: string) {
this.returnType = returnType;
if(doc) this.doc = doc;
}
Expand All @@ -17,7 +17,7 @@ export class SignatureSpec {
/** List of parameters. */
paramList: readts.IdentifierSpec[] = [];
/** Return type in TypeScript syntax. */
returnType: string;
returnType: readts.TypeSpec;
/** JSDoc comment. */
doc: string;
}
68 changes: 68 additions & 0 deletions src/TypeSpec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// This file is part of readts, copyright (c) 2016 BusFaster Ltd.
// Released under the MIT license, see LICENSE.

import * as ts from 'typescript';
import * as readts from './readts';

export interface FormatHooks {
[name: string]: (spec: TypeSpec, hooks: FormatHooks) => string;

class?: (spec: TypeSpec, hooks: FormatHooks) => string;
array?: (spec: TypeSpec, hooks: FormatHooks) => string;
union?: (spec: TypeSpec, hooks: FormatHooks) => string;
}

export class TypeSpec {
constructor(type: ts.Type, parser: readts.Parser) {
var tf = ts.TypeFlags;

// console.log(Object.keys(tf).map((name: string) => type.flags & tf[name] ? name : null).filter((name) => !!name).join(' | '));

if(type.flags & ((tf as any).Intrinsic | tf.ThisType | tf.Anonymous | tf.StringLiteral)) {
this.name = parser.typeToString(type);
} else if(type.flags & tf.Reference) {
this.parseReference(type as ts.TypeReference, parser);
} else if (type.flags & (tf.Class | tf.Interface | tf.Enum | tf.TypeParameter)) {
this.parseClass(type, parser);
} else if (type.flags & tf.Tuple) {
} else if (type.flags & tf.UnionOrIntersection) {
this.parseUnion(type as ts.UnionOrIntersectionType, parser);
}
}

parseClass(type: ts.Type, parser: readts.Parser) {
var spec = parser.getSymbol(type.symbol);

if(spec) this.class = spec;
else this.name = parser.typeToString(type);
}

parseReference(type: ts.TypeReference, parser: readts.Parser) {
if(type.target.symbol.getName() == 'Array' && type.typeArguments) {
this.arrayOf = new TypeSpec(type.typeArguments[0], parser);
} else this.parseClass(type, parser);
}

parseUnion(type: ts.UnionOrIntersectionType, parser: readts.Parser) {
this.unionOf = type.types.map((type: ts.Type) => new TypeSpec(type, parser));
}

format(hooks?: FormatHooks, needParens?: boolean): string {
if(this.name) return(this.name);
if(this.class) return(hooks && hooks.class ? hooks.class(this, hooks) : this.class.name);
if(this.arrayOf) return(hooks && hooks.array ? hooks.array(this, hooks) : this.arrayOf.format(hooks, true) + '[]');

var output: string;

if(this.unionOf) output = hooks && hooks.union ? hooks.union(this, hooks) : this.unionOf.map((spec: TypeSpec) => spec.format(hooks, true)).join(' | ');

if(needParens) output = '(' + output + ')';

return(output);
}

name: string;
class: readts.ClassSpec;
unionOf: TypeSpec[];
arrayOf: TypeSpec;
}
1 change: 1 addition & 0 deletions src/readts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export {SignatureSpec} from './SignatureSpec';
export {FunctionSpec} from './FunctionSpec';
export {ClassSpec} from './ClassSpec';
export {ModuleSpec} from './ModuleSpec';
export {TypeSpec, FormatHooks} from './TypeSpec';
export {Parser} from './Parser';

0 comments on commit 22a6306

Please sign in to comment.