153 lines
4.7 KiB
TypeScript
153 lines
4.7 KiB
TypeScript
|
module ts {
|
||
|
interface Map<T> {
|
||
|
[index: string]: T;
|
||
|
}
|
||
|
|
||
|
interface Equals<T> {
|
||
|
equals(other: T): boolean;
|
||
|
}
|
||
|
|
||
|
class Symbol {
|
||
|
}
|
||
|
|
||
|
class Type extends Symbol {
|
||
|
equals(that: Type): boolean {
|
||
|
if (this === that) return true;
|
||
|
if (!(this.isObjectType() && that.isObjectType())) return false;
|
||
|
var propCount = that.getPropertyCount();
|
||
|
if (propCount !== this.getPropertyCount()) return false;
|
||
|
var sigCount = that.getSignatureCount();
|
||
|
if (sigCount !== this.getSignatureCount()) return false;
|
||
|
if (propCount) {
|
||
|
for (var i = 0; i < propCount; i++) {
|
||
|
var thisProp = this.getProperty(i);
|
||
|
var thatProp = that.getPropertyByName(thisProp.name);
|
||
|
if (!(thatProp && thisProp.flags === thatProp.flags && thisProp.type.equals(thatProp.type))) return false;
|
||
|
}
|
||
|
}
|
||
|
if (sigCount) {
|
||
|
if (!setEquals(this.getSignatures(), that.getSignatures())) return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
getProperties(): Property[] {
|
||
|
return [];
|
||
|
}
|
||
|
getProperty(index: number): Property {
|
||
|
return undefined;
|
||
|
}
|
||
|
getPropertyByName(name: string): Property {
|
||
|
return undefined;
|
||
|
}
|
||
|
getPropertyCount(): number {
|
||
|
return 0;
|
||
|
}
|
||
|
getSignature(index: number): Signature {
|
||
|
return undefined;
|
||
|
}
|
||
|
getSignatureCount(): number {
|
||
|
return 0;
|
||
|
}
|
||
|
getSignatures(): Signature[] {
|
||
|
return [];
|
||
|
}
|
||
|
isPrimitive(): boolean {
|
||
|
return false;
|
||
|
}
|
||
|
isObjectType(): boolean {
|
||
|
return false;
|
||
|
}
|
||
|
isTypeParameter(): boolean {
|
||
|
return false;
|
||
|
}
|
||
|
isSubTypeOf(type: Type) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class Property extends Symbol {
|
||
|
constructor(public name: string, public type: Type, public flags: PropertyFlags) {
|
||
|
super();
|
||
|
}
|
||
|
equals(other: Property): boolean {
|
||
|
return this.name === other.name &&
|
||
|
this.flags === other.flags &&
|
||
|
this.type.equals(other.type);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
enum PropertyFlags {
|
||
|
Optional = 1,
|
||
|
Private = 2
|
||
|
}
|
||
|
|
||
|
class Signature extends Symbol {
|
||
|
constructor(public typeParameters: TypeParameter[], public parameters: Parameter[], public returnType: Type) {
|
||
|
super();
|
||
|
}
|
||
|
equalsNoReturn(other: Signature): boolean {
|
||
|
return this.parameters.length === other.parameters.length &&
|
||
|
this.typeParameters.length === other.typeParameters.length &&
|
||
|
arrayEquals(this.parameters, other.parameters) &&
|
||
|
arrayEquals(this.typeParameters, other.typeParameters);
|
||
|
}
|
||
|
equals(other: Signature): boolean {
|
||
|
return this.equalsNoReturn(other) &&
|
||
|
this.returnType.equals(other.returnType);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class Parameter extends Symbol {
|
||
|
constructor(public name: string, public type: Type, public flags: ParameterFlags) {
|
||
|
super();
|
||
|
}
|
||
|
equals(other: Parameter) {
|
||
|
return this.name === other.name &&
|
||
|
this.flags === other.flags &&
|
||
|
this.type.equals(other.type);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
enum ParameterFlags {
|
||
|
Optional = 1,
|
||
|
Rest = 2
|
||
|
}
|
||
|
|
||
|
|
||
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||
|
|
||
|
function getProperty<T>(map: Map<T>, key: string): T {
|
||
|
if (!hasOwnProperty.call(map, key)) return undefined;
|
||
|
return map[key];
|
||
|
}
|
||
|
|
||
|
function hasProperty<T>(map: Map<T>, key: string): boolean {
|
||
|
return hasOwnProperty.call(map, key);
|
||
|
}
|
||
|
|
||
|
function arrayContains<T extends Equals<T>>(a: T[], item: T): boolean {
|
||
|
var len = a.length;
|
||
|
for (var i = 0; i < len; i++) {
|
||
|
if (item.equals(a[i])) return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
function arrayEquals<T extends Equals<T>>(a: T[], b: T[]): boolean {
|
||
|
var len = a.length;
|
||
|
if (b.length !== len) return false;
|
||
|
for (var i = 0; i < len; i++) {
|
||
|
if (!a[i].equals(b[i])) return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
function setEquals<T extends Equals<T>>(a: T[], b: T[]): boolean {
|
||
|
var len = a.length;
|
||
|
if (b.length !== len) return false;
|
||
|
for (var i = 0; i < len; i++) {
|
||
|
if (!arrayContains(b, a[i])) return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
}
|