Skip to content

Support for multidimensional arrays #491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"minimatch": "^3.0.0",
"progress": "^2.0.0",
"shelljs": "^0.7.0",
"typedoc-default-themes": "^0.4.2",
"typedoc-default-themes": "^0.4.4",
"typescript": "2.3.2"
},
"devDependencies": {
Expand Down
4 changes: 3 additions & 1 deletion src/lib/converter/plugins/TypePlugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Reflection, ReflectionKind, Decorator, DeclarationReflection, DeclarationHierarchy} from '../../models/reflections/index';
import {Type, ReferenceType, TupleType, UnionType, IntersectionType} from '../../models/types/index';
import {Type, ReferenceType, TupleType, UnionType, IntersectionType, ArrayType} from '../../models/types/index';
import {Component, ConverterComponent} from '../components';
import {Converter} from '../converter';
import {Context} from '../context';
Expand Down Expand Up @@ -113,6 +113,8 @@ export class TypePlugin extends ConverterComponent {
for (let index = 0, count = unionOrIntersectionType.types.length; index < count; index++) {
resolveType(reflection, unionOrIntersectionType.types[index]);
}
} else if (type instanceof ArrayType) {
resolveType(reflection, type.elementType);
}
}
}
Expand Down
42 changes: 32 additions & 10 deletions src/lib/converter/types/array.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
import * as ts from 'typescript';

import {Type, IntrinsicType} from '../../models/index';
import {Component, ConverterTypeComponent, TypeNodeConverter} from '../components';
import {Type, ArrayType} from '../../models/index';
import {Component, ConverterTypeComponent, TypeConverter} from '../components';
import {Context} from '../context';

@Component({name: 'type:array'})
export class ArrayConverter extends ConverterTypeComponent implements TypeNodeConverter<ts.Type, ts.ArrayTypeNode> {
export class ArrayConverter extends ConverterTypeComponent implements TypeConverter<ts.TypeReference, ts.ArrayTypeNode> {
/**
* Test whether this converter can handle the given TypeScript node.
*/
supportsNode(context: Context, node: ts.ArrayTypeNode): boolean {
return node.kind === ts.SyntaxKind.ArrayType;
}

/**
* Test whether this converter can handle the given TypeScript type.
*/
supportsType(context: Context, type: ts.TypeReference): boolean {
// Is there a better way to detect the {"type":"reference","name":"Array","typeArguments":{...}} types that are in fact arrays?
return !!(type.flags & ts.TypeFlags.Object) && !!type.symbol && type.symbol.name === 'Array' && !type.symbol.parent && !!type.typeArguments && type.typeArguments.length === 1;
}

/**
* Convert the given array type node to its type reflection.
*
Expand All @@ -27,14 +35,28 @@ export class ArrayConverter extends ConverterTypeComponent implements TypeNodeCo
* @returns The type reflection representing the given array type node.
*/
convertNode(context: Context, node: ts.ArrayTypeNode): Type {
let result = this.owner.convertType(context, node.elementType);
const result = this.owner.convertType(context, node.elementType);

if (result) {
result.isArray = true;
} else {
result = new IntrinsicType('Array');
}
return new ArrayType(result);
}

/**
* Convert the given type reference to its type reflection.
*
* This is a type based converter, see [[convertTypeReference]] for the node equivalent.
*
* ```
* class SomeClass { }
* let someValue: SomeClass;
* ```
*
* @param context The context object describing the current state the converter is in.
* @param type The type reference that should be converted.
* @returns The type reflection representing the given type reference.
*/
convertType(context: Context, type: ts.TypeReference): Type {
const result = this.owner.convertType(context, null, type.typeArguments[0]);

return result;
return new ArrayType(result);
}
}
8 changes: 0 additions & 8 deletions src/lib/models/types/abstract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
* Instances of this class are also used to represent the type `void`.
*/
export abstract class Type {
/**
* Is this an array type?
*/
isArray = false;

/**
* The type name identifier.
Expand Down Expand Up @@ -38,10 +34,6 @@ export abstract class Type {
let result: any = {};
result.type = this.type;

if (this.isArray) {
result.isArray = this.isArray;
}

return result;
}

Expand Down
75 changes: 75 additions & 0 deletions src/lib/models/types/array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {Type, UnionType, IntersectionType} from './index';

/**
* Represents an array type.
*
* ~~~
* let value: string[];
* ~~~
*/
export class ArrayType extends Type {

/**
* The type of the array elements.
*/
elementType: Type;

/**
* The type name identifier.
*/
readonly type: string = 'array';

/**
* Create a new TupleType instance.
*
* @param elementType The type of the array's elements.
*/
constructor(elementType: Type) {
super();
this.elementType = elementType;
}

/**
* Clone this type.
*
* @return A clone of this type.
*/
clone(): Type {
return new ArrayType(this.elementType);
}

/**
* Test whether this type equals the given type.
*
* @param type The type that should be checked for equality.
* @returns TRUE if the given type equals this type, FALSE otherwise.
*/
equals(type: Type): boolean {
if (!(type instanceof ArrayType)) {
return false;
}
return type.elementType.equals(this.elementType);
}

/**
* Return a raw object representation of this type.
*/
toObject(): any {
const result: any = super.toObject();
result.elementType = this.elementType.toObject();

return result;
}

/**
* Return a string representation of this type.
*/
toString() {
const elementTypeStr = this.elementType.toString();
if (this.elementType instanceof UnionType || this.elementType instanceof IntersectionType) {
return '(' + elementTypeStr + ')[]';
} else {
return elementTypeStr + '[]';
}
}
}
1 change: 1 addition & 0 deletions src/lib/models/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export {Type} from './abstract';
export {ArrayType} from './array';
export {IntrinsicType} from './intrinsic';
export {IntersectionType} from './intersection';
export {ReferenceType} from './reference';
Expand Down
7 changes: 1 addition & 6 deletions src/lib/models/types/intersection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ export class IntersectionType extends Type {
* @return A clone of this type.
*/
clone(): Type {
const clone = new IntersectionType(this.types);
clone.isArray = this.isArray;
return clone;
return new IntersectionType(this.types);
}

/**
Expand All @@ -49,9 +47,6 @@ export class IntersectionType extends Type {
if (!(type instanceof IntersectionType)) {
return false;
}
if (type.isArray !== this.isArray) {
return false;
}
return Type.isTypeListSimiliar(type.types, this.types);
}

Expand Down
7 changes: 2 additions & 5 deletions src/lib/models/types/intrinsic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ export class IntrinsicType extends Type {
* @return A clone of this type.
*/
clone(): Type {
const clone = new IntrinsicType(this.name);
clone.isArray = this.isArray;
return clone;
return new IntrinsicType(this.name);
}

/**
Expand All @@ -47,7 +45,6 @@ export class IntrinsicType extends Type {
*/
equals(type: IntrinsicType): boolean {
return type instanceof IntrinsicType &&
type.isArray === this.isArray &&
type.name === this.name;
}

Expand All @@ -64,6 +61,6 @@ export class IntrinsicType extends Type {
* Return a string representation of this type.
*/
toString() {
return this.name + (this.isArray ? '[]' : '');
return this.name;
}
}
5 changes: 1 addition & 4 deletions src/lib/models/types/reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ export class ReferenceType extends Type {
*/
clone(): Type {
const clone = new ReferenceType(this.name, this.symbolID, this.reflection);
clone.isArray = this.isArray;
clone.typeArguments = this.typeArguments;
return clone;
}
Expand All @@ -86,7 +85,6 @@ export class ReferenceType extends Type {
*/
equals(type: ReferenceType): boolean {
return type instanceof ReferenceType &&
type.isArray === this.isArray &&
(type.symbolID === this.symbolID || type.reflection === this.reflection);
}

Expand Down Expand Up @@ -114,14 +112,13 @@ export class ReferenceType extends Type {
*/
toString() {
const name = this.reflection ? this.reflection.name : this.name;
const arraySuffix = this.isArray ? '[]' : '';
let typeArgs = '';
if (this.typeArguments) {
typeArgs += '<';
typeArgs += this.typeArguments.map(arg => arg.toString()).join(', ');
typeArgs += '>';
}

return name + typeArgs + arraySuffix;
return name + typeArgs;
}
}
4 changes: 1 addition & 3 deletions src/lib/models/types/reflection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ export class ReflectionType extends Type {
* @return A clone of this type.
*/
clone(): Type {
const clone = new ReflectionType(this.declaration);
clone.isArray = this.isArray;
return clone;
return new ReflectionType(this.declaration);
}

/**
Expand Down
5 changes: 1 addition & 4 deletions src/lib/models/types/string-literal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ export class StringLiteralType extends Type {
* @return A clone of this type.
*/
clone(): Type {
const clone = new StringLiteralType(this.value);
clone.isArray = this.isArray;
return clone;
return new StringLiteralType(this.value);
}

/**
Expand All @@ -47,7 +45,6 @@ export class StringLiteralType extends Type {
*/
equals(type: StringLiteralType): boolean {
return type instanceof StringLiteralType &&
type.isArray === this.isArray &&
type.value === this.value;
}

Expand Down
7 changes: 1 addition & 6 deletions src/lib/models/types/tuple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ export class TupleType extends Type {
* @return A clone of this type.
*/
clone(): Type {
const clone = new TupleType(this.elements);
clone.isArray = this.isArray;
return clone;
return new TupleType(this.elements);
}

/**
Expand All @@ -49,9 +47,6 @@ export class TupleType extends Type {
if (!(type instanceof TupleType)) {
return false;
}
if (type.isArray !== this.isArray) {
return false;
}
return Type.isTypeListEqual(type.elements, this.elements);
}

Expand Down
9 changes: 2 additions & 7 deletions src/lib/models/types/type-parameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export class TypeParameterType extends Type {
*/
clone(): Type {
const clone = new TypeParameterType();
clone.isArray = this.isArray;
clone.name = this.name;
clone.constraint = this.constraint;
return clone;
Expand All @@ -44,17 +43,13 @@ export class TypeParameterType extends Type {
return false;
}

let constraintEquals: boolean;
if (this.constraint && type.constraint) {
constraintEquals = type.constraint.equals(this.constraint);
return type.constraint.equals(this.constraint);
} else if (!this.constraint && !type.constraint) {
constraintEquals = true;
return true;
} else {
return false;
}

return constraintEquals &&
type.isArray === this.isArray;
}

/**
Expand Down
7 changes: 1 addition & 6 deletions src/lib/models/types/union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ export class UnionType extends Type {
* @return A clone of this type.
*/
clone(): Type {
const clone = new UnionType(this.types);
clone.isArray = this.isArray;
return clone;
return new UnionType(this.types);
}

/**
Expand All @@ -49,9 +47,6 @@ export class UnionType extends Type {
if (!(type instanceof UnionType)) {
return false;
}
if (type.isArray !== this.isArray) {
return false;
}
return Type.isTypeListSimiliar(type.types, this.types);
}

Expand Down
5 changes: 1 addition & 4 deletions src/lib/models/types/unknown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ export class UnknownType extends Type {
* @return A clone of this type.
*/
clone(): Type {
const clone = new UnknownType(this.name);
clone.isArray = this.isArray;
return clone;
return new UnknownType(this.name);
}

/**
Expand All @@ -43,7 +41,6 @@ export class UnknownType extends Type {
*/
equals(type: UnknownType): boolean {
return type instanceof UnknownType &&
type.isArray === this.isArray &&
type.name === this.name;
}

Expand Down
Loading