-
Notifications
You must be signed in to change notification settings - Fork 246
/
Copy pathtype.ts
143 lines (127 loc) · 3.78 KB
/
type.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import * as jsii from '@jsii/spec';
import { Assembly } from './assembly';
import { ClassType } from './class';
import { Docs, Documentable } from './docs';
import { EnumType } from './enum';
import { InterfaceType } from './interface';
import { locationInRepository, SourceLocatable, SourceLocation } from './source';
import { TypeSystem } from './type-system';
import { TypeReference } from './type-ref';
export abstract class Type implements Documentable, SourceLocatable {
public constructor(
public readonly system: TypeSystem,
public readonly assembly: Assembly,
public readonly spec: jsii.Type) { }
public toString(): string {
return `${this.kind} ${this.fqn}`;
}
/**
* The fully qualified name of the type (``<assembly>.<namespace>.<name>``)
*/
public get fqn(): string {
return this.spec.fqn;
}
/**
* The namespace of the type (``foo.bar.baz``). When undefined, the type is located at the root of the assembly
* (it's ``fqn`` would be like ``<assembly>.<name>``). If the `namespace` corresponds to an existing type's
* namespace-qualified (e.g: ``<namespace>.<name>``), then the current type is a nested type.
*/
public get namespace(): string | undefined {
return this.spec.namespace;
}
/**
* The simple name of the type (MyClass).
*/
public get name(): string {
return this.spec.name;
}
/**
* The kind of the type.
*/
public get kind(): jsii.TypeKind {
return this.spec.kind;
}
public get docs(): Docs {
return new Docs(this.system, this, this.spec.docs ?? {});
}
/**
* A type reference to this type
*/
public get reference(): TypeReference {
return new TypeReference(this.system, {
fqn: this.fqn,
});
}
/**
* Determines whether this is a Class type or not.
*/
public isClassType(): this is ClassType {
return false;
}
/**
* Determines whether this is a Data Type (that is, an interface with no methods) or not.
*/
public isDataType(): this is InterfaceType {
return false;
}
/**
* Determines whether this is an Enum type or not.
*/
public isEnumType(): this is EnumType {
return false;
}
/**
* Determines whether this is an Interface type or not.
*/
public isInterfaceType(): this is InterfaceType {
return false;
}
/**
* Determines whether this type extends a given base or not.
*
* @param base the candidate base type.
*/
public extends(base: Type): boolean {
if (this === base) {
return true;
}
if ((this.isInterfaceType() || this.isClassType()) && base.isInterfaceType()) {
return this.getInterfaces(true).some(iface => iface === base);
}
if (this.isClassType() && base.isClassType()) {
return this.getAncestors().some(clazz => clazz === base);
}
return false;
}
/**
* Finds all type that:
* - extend this, if this is a ClassType
* - implement this, if this is an InterfaceType (this includes interfaces extending this)
*
* As classes and interfaces are considered to extend themselves, "this" will be part of all return values when called
* on classes and interfaces.
*
* The result will always be empty for types that are neither ClassType nor InterfaceType.
*/
public get allImplementations(): Type[] {
if (this.isClassType() || this.isInterfaceType()) {
return [
...this.system.classes.filter(c => c.extends(this)),
...this.system.interfaces.filter(i => i.extends(this)),
];
}
return [];
}
/**
* Return the location in the module
*/
public get locationInModule(): SourceLocation | undefined {
return this.spec.locationInModule;
}
/**
* Return the location in the repository
*/
public get locationInRepository(): SourceLocation | undefined {
return locationInRepository(this);
}
}