1 /**
2 	Contains definitions of the syntax tree elements.
3 
4 	Copyright: © 2012 RejectedSoftware e.K.
5 	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
6 	Authors: Sönke Ludwig
7 */
8 module ddox.entities;
9 
10 import ddox.ddoc;
11 import std.algorithm : countUntil, joiner, map;
12 import std.range;
13 import std.string;
14 import std.typecons;
15 
16 
17 class Entity {
18 	Entity parent;
19 	string name;
20 	DocGroup docGroup;
21 
22 	this(Entity parent, string name)
23 	{
24 		this.parent = parent;
25 		this.name = name;
26 	}
27 
28 	@property string qualifiedName()
29 	const {
30 		string s = name;
31 		Rebindable!(const(Entity)) e = parent;
32 		while( e && e.parent ){
33 			s = e.name ~ "." ~ s;
34 			e = e.parent;
35 		}
36 		return s;
37 	}
38 
39 	@property string moduleName()
40 	const {
41 		Rebindable!(const(Entity)) e = this;
42 		while( e && !cast(Module)e ) e = e.parent;
43 		if( e ) return e.qualifiedName;
44 		return null;
45 	}
46 
47 	@property string nestedName()
48 	const {
49 		string s = name;
50 		Rebindable!(const(Entity)) e = parent;
51 		while( e && e.parent ){
52 			if( cast(Module)e ) break;
53 			s = e.name ~ "." ~ s;
54 			e = e.parent;
55 		}
56 		return s;
57 	}
58 
59 	@property string kindCaption() const { return "Entity"; }
60 
61 	bool isAncestorOf(in Entity node)
62 	const {
63 		auto n = rebindable(node);
64 		while( n ){
65 			if( n.parent is this ) return true;
66 			n = n.parent;
67 		}
68 		return false;
69 	}
70 
71 	abstract void iterateChildren(bool delegate(Entity) del);
72 
73 	final T findChild(T = Entity)(string name)
74 	{
75 		T ret;
76 		iterateChildren((ch){ if( ch.name == name ){ ret = cast(T)ch; return ret is null; } return true; });
77 		return ret;
78 	}
79 
80 	final T[] findChildren(T = Entity)(string name)
81 	{
82 		T[] ret;
83 		iterateChildren((ch){ if( ch.name == name ){ auto t = cast(T)ch; if( t ) ret ~= t; } return true; });
84 		return ret;
85 	}
86 
87 	final T lookup(T = Entity)(string qualified_name, bool recurse = true)
88 	{
89 		auto parts = split(qualified_name, ".");
90 		Entity e = this;
91 		foreach( i, p; parts ){
92 			if( i+1 < parts.length ){
93 				e = e.findChild(p);
94 				if( !e ) break;
95 			} else {
96 				auto r = e.findChild!T(p);
97 				if( r ) return r;
98 			}
99 		}
100 		static if (is(T == Declaration)) {
101 			if (auto decl = cast(Declaration)this) {
102 				auto idx = decl.templateArgs.countUntil!(p => p.name == qualified_name);
103 				if (idx >= 0) return decl.templateArgs[idx];
104 			}
105 		}
106 		if( recurse && parent ) return parent.lookup!T(qualified_name);
107 		return null;
108 	}
109 
110 	final T[] lookupAll(T = Entity)(string qualified_name)
111 	{
112 		auto parts = split(qualified_name, ".");
113 		Entity e = this;
114 		foreach( i, p; parts ){
115 			if( i+1 < parts.length ) e = e.findChild(p);
116 			else return e.findChildren!T(p);
117 			if( !e ) return null;
118 		}
119 		return null;
120 	}
121 
122 	final Entity lookdown(string qualified_name, bool stop_at_module_level = false)
123 	{
124 		auto parts = split(qualified_name, ".");
125 		Entity e = this;
126 		foreach( p; parts ){
127 			e = e.findChild(p);
128 			if( !e ){
129 				if( stop_at_module_level && cast(Module)this ) return null;
130 				Entity ret;
131 				iterateChildren((ch){
132 					if( auto res = (cast()ch).lookdown(qualified_name) ){
133 						ret = res;
134 						return false;
135 					}
136 					return true; 
137 				});
138 				return ret;
139 			}
140 		}
141 		return e;
142 	}
143 
144 	void visit(T)(void delegate(T) del)
145 	{
146 		if( auto t = cast(T)this ) del(t);
147 		iterateChildren((ch){ ch.visit!T(del); return true; });
148 	}
149 }
150 
151 final class DocGroup {
152 	Entity[] members;
153 	string text;
154 	DdocComment comment;
155 
156 	this(Entity entity, string text)
157 	{
158 		this.members = [entity];
159 		this.text = text;
160 		this.comment = new DdocComment(text);
161 	}
162 
163 	this(Entity entity, string text, DdocComment comment)
164 	{
165 		this.members = [entity];
166 		this.text = text;
167 		this.comment = comment;
168 	}
169 }
170 
171 final class Package : Entity {
172 	Package[] packages;
173 	Module[] modules;
174 
175 	this(Entity parent, string name){ super(parent, name); }
176 
177 	override @property string kindCaption() const { return "Package"; }
178 
179 	Module createModule(string name)
180 	{
181 		assert(findChild!Module(name) is null, "Module already present");
182 		auto mod = new Module(this, name);
183 		modules ~= mod;
184 		return mod;
185 	}
186 
187 	Package getOrAddPackage(string name)
188 	{
189 		foreach( p; packages )
190 			if( p.name == name )
191 				return p;
192 		auto pack = new Package(this, name);
193 		pack.docGroup = new DocGroup(pack, null);
194 		packages ~= pack;
195 		return pack;
196 	}
197 
198 	override void iterateChildren(bool delegate(Entity) del)
199 	{
200 		foreach( p; packages ) if( !del(p) ) return;
201 		foreach( m; modules ) if( !del(m) ) return;
202 	}
203 }
204 
205 final class Module : Entity{
206 	Declaration[] members;
207 	string file;
208 
209 	this(Entity parent, string name){ super(parent, name); }
210 
211 	override @property string kindCaption() const { return "Module"; }
212 
213 	override void iterateChildren(bool delegate(Entity) del)
214 	{
215 		foreach( m; members ) if( !del(m) ) return;
216 	}
217 }
218 
219 enum DeclarationKind {
220 	Variable,
221 	Function,
222 	Struct,
223 	Union,
224 	Class,
225 	Interface,
226 	Enum,
227 	EnumMember,
228 	Alias,
229 	Template,
230 	TemplateParameter
231 }
232 
233 enum Protection {
234 	Private,
235 	Package,
236 	Protected,
237 	Public
238 }
239 
240 class Declaration : Entity {
241 	Declaration inheritingDecl;
242 	Protection protection = Protection.Public;
243 	string[] attributes;
244 	int line;
245 	bool isTemplate;
246 	TemplateParameterDeclaration[] templateArgs;
247 	string templateConstraint;
248 
249 	override @property string kindCaption() const { return "Declaration"; }
250 	abstract @property Declaration dup();
251 	abstract @property DeclarationKind kind();
252 	@property inout(Declaration) parentDeclaration() inout { return cast(inout(Declaration))parent; }
253 	@property Module module_() {
254 		Entity e = parent;
255 		while(e){
256 			if( auto m = cast(Module)e ) return m;
257 			e = e.parent;
258 		}
259 		assert(false, "Declaration without module?");
260 	}
261 	@property const(Module) module_() const {
262 		Rebindable!(const(Entity)) e = parent;
263 		while(e){
264 			if( auto m = cast(const(Module))e ) return m;
265 			e = e.parent;
266 		}
267 		assert(false, "Declaration without module?");
268 	}
269 
270 	@property string templateArgsString() const {
271 		if (!isTemplate) return null;
272 		return format("(%s)", (cast(string[])templateArgs.map!(a => a.name).array).join(", "));
273 	}
274 
275 	this(Entity parent, string name){ super(parent, name); }
276 
277 	abstract override void iterateChildren(bool delegate(Entity) del);
278 
279 	protected void copyFrom(Declaration src)
280 	{
281 		this.docGroup = src.docGroup;
282 		this.inheritingDecl = src.inheritingDecl;
283 		this.protection = src.protection;
284 		this.line = src.line;
285 		this.templateArgs = src.templateArgs;
286 	}
287 }
288 
289 class TypedDeclaration : Declaration {
290 	Type type;
291 
292 	this(Entity parent, string name){ super(parent, name); }
293 
294 	override @property string kindCaption() const { return "Typed declaration"; }
295 
296 	abstract override @property DeclarationKind kind() const;
297 
298 	abstract override void iterateChildren(bool delegate(Entity) del);
299 
300 	protected override void copyFrom(Declaration src)
301 	{
302 		super.copyFrom(src);
303 		if (auto tsrc = cast(TypedDeclaration)src)
304 			this.type = tsrc.type;
305 	}
306 }
307 
308 final class VariableDeclaration : TypedDeclaration {
309 	Value initializer;
310 
311 	override @property string kindCaption() const { return "Variable"; }
312 	override @property VariableDeclaration dup() { auto ret = new VariableDeclaration(parent, name); ret.copyFrom(this); ret.initializer = initializer; return ret; }
313 	override @property DeclarationKind kind() const { return DeclarationKind.Variable; }
314 
315 	this(Entity parent, string name){ super(parent, name); }
316 
317 	override void iterateChildren(bool delegate(Entity) del) {}
318 }
319 
320 final class FunctionDeclaration : TypedDeclaration {
321 	Type returnType;
322 	VariableDeclaration[] parameters;
323 
324 	override @property string kindCaption() const { return "Function"; }
325 	override @property FunctionDeclaration dup() { auto ret = new FunctionDeclaration(parent, name); ret.copyFrom(this); ret.returnType = returnType; ret.parameters = parameters.dup; ret.attributes = attributes; return ret; }
326 	override @property DeclarationKind kind() const { return DeclarationKind.Function; }
327 
328 	this(Entity parent, string name){ super(parent, name); }
329 
330 	bool hasAttribute(string att) const { foreach( a; attributes ) if( a == att ) return true; return false; }
331 
332 	override void iterateChildren(bool delegate(Entity) del)
333 	{
334 		foreach( p; parameters ) del(p);
335 	}
336 }
337 
338 class CompositeTypeDeclaration : Declaration {
339 	Declaration[] members;
340 
341 	override @property string kindCaption() const { return "Composite type"; }
342 	override abstract @property DeclarationKind kind() const;
343  
344 	this(Entity parent, string name){ super(parent, name); }
345 
346 	override void iterateChildren(bool delegate(Entity) del)
347 	{
348 		foreach( m; members ) if( !del(m) ) return;
349 	}
350 }
351 
352 final class StructDeclaration : CompositeTypeDeclaration {
353 	override @property string kindCaption() const { return "Struct"; }
354 	override @property StructDeclaration dup() { auto ret = new StructDeclaration(parent, name); ret.copyFrom(this); ret.members = members; return ret; }
355 	override @property DeclarationKind kind() const { return DeclarationKind.Struct; }
356 
357 	this(Entity parent, string name){ super(parent, name); }
358 }
359 
360 final class UnionDeclaration : CompositeTypeDeclaration {
361 	override @property string kindCaption() const { return "Union"; }
362 	override @property UnionDeclaration dup() { auto ret = new UnionDeclaration(parent, name); ret.copyFrom(this); ret.members = members; return ret; }
363 	override @property DeclarationKind kind() const { return DeclarationKind.Union; }
364 
365 	this(Entity parent, string name){ super(parent, name); }
366 }
367 
368 final class InterfaceDeclaration : CompositeTypeDeclaration {
369 	Type[] derivedInterfaces;
370 
371 	override @property string kindCaption() const { return "Interface"; }
372 	override @property InterfaceDeclaration dup() { auto ret = new InterfaceDeclaration(parent, name); ret.copyFrom(this); ret.members = members; ret.derivedInterfaces = derivedInterfaces.dup; return ret; }
373 	override @property DeclarationKind kind() const { return DeclarationKind.Interface; }
374 
375 	this(Entity parent, string name){ super(parent, name); }
376 }
377 
378 final class ClassDeclaration : CompositeTypeDeclaration {
379 	Type baseClass;
380 	Type[] derivedInterfaces;
381 
382 	override @property string kindCaption() const { return "Class"; }
383 	override @property ClassDeclaration dup() { auto ret = new ClassDeclaration(parent, name); ret.copyFrom(this); ret.members = members; ret.baseClass = baseClass; ret.derivedInterfaces = derivedInterfaces.dup; return ret; }
384 	override @property DeclarationKind kind() const { return DeclarationKind.Class; }
385 
386 	this(Entity parent, string name){ super(parent, name); }
387 }
388 
389 final class EnumDeclaration : CompositeTypeDeclaration {
390 	Type baseType;
391 
392 	override @property string kindCaption() const { return "Enum"; }
393 	override @property EnumDeclaration dup() { auto ret = new EnumDeclaration(parent, name); ret.copyFrom(this); ret.members = members; ret.baseType = baseType; return ret; }
394 	override @property DeclarationKind kind() const { return DeclarationKind.Enum; }
395 
396 	this(Entity parent, string name){ super(parent, name); }
397 }
398 
399 final class EnumMemberDeclaration : Declaration {
400 	Value value;
401 
402 	override @property string kindCaption() const { return "Enum member"; }
403 	override @property EnumMemberDeclaration dup() { auto ret = new EnumMemberDeclaration(parent, name); ret.copyFrom(this); ret.value = value; return ret; }
404 	override @property DeclarationKind kind() const { return DeclarationKind.EnumMember; }
405 	@property Type type() { if( !value ) return null; return value.type; }
406 
407 	this(Entity parent, string name){ super(parent, name); }
408 
409 	override void iterateChildren(bool delegate(Entity) del) {}
410 }
411 
412 final class AliasDeclaration : Declaration {
413 	Declaration targetDecl;
414 	Type targetType;
415 	string targetString;
416 
417 	override @property string kindCaption() const { return "Alias"; }
418 	override @property AliasDeclaration dup() { auto ret = new AliasDeclaration(parent, name); ret.copyFrom(this); ret.targetDecl = targetDecl; ret.targetType = targetType; return ret; }
419 	override @property DeclarationKind kind() const { return DeclarationKind.Alias; }
420 	@property Type type() { return targetType; }
421 
422 	this(Entity parent, string name){ super(parent, name); }
423 
424 	override void iterateChildren(bool delegate(Entity) del) {}
425 }
426 
427 final class TemplateDeclaration : Declaration {
428 	Declaration[] members;
429 
430 	override @property string kindCaption() const { return "Template"; }
431 	override @property TemplateDeclaration dup() { auto ret = new TemplateDeclaration(parent, name); ret.copyFrom(this); ret.members = members.dup; return ret; }
432 	override @property DeclarationKind kind() const { return DeclarationKind.Template; }
433 
434 	this(Entity parent, string name){ super(parent, name); isTemplate = true; }
435 
436 	override void iterateChildren(bool delegate(Entity) del)
437 	{
438 		foreach( m; members ) del(m);
439 	}
440 }
441 
442 final class TemplateParameterDeclaration : TypedDeclaration {
443 	override @property string kindCaption() const { return "Template parameter"; }
444 	override @property TemplateParameterDeclaration dup() { auto ret = new TemplateParameterDeclaration(parent, name); ret.copyFrom(this); ret.type = type; return ret; }
445 	override @property DeclarationKind kind() const { return DeclarationKind.TemplateParameter; }
446 
447 	this(Entity parent, string name){ super(parent, name); type = new Type(this); }
448 
449 	override void iterateChildren(bool delegate(Entity) del) {}
450 }
451 
452 final class Value {
453 	Type type;
454 	string valueString;
455 
456 	this() {}
457 	this(Type type, string value_string) { this.type = type; this.valueString = value_string; }
458 }
459 
460 enum TypeKind {
461 	Primitive,
462 	Pointer,
463 	Array,
464 	StaticArray,
465 	AssociativeArray,
466 	Function,
467 	Delegate
468 }
469 
470 final class Type {
471 	TypeKind kind;
472 	string[] attributes;
473 	string[] modifiers;
474 	string templateArgs;
475 	string text; // original text as in DMDs JSON output
476 	// Primitive
477 	string typeName;
478 	Declaration typeDecl;
479 	// P, A, SA, AA
480 	Type elementType;
481 	// SA
482 	string arrayLength;
483 	// AA
484 	Type keyType;
485 	// Function/Delegate
486 	Type returnType;
487 	Type[] parameterTypes;
488 	string[] _parameterNames;
489 	Value[] _parameterDefaultValues;
490 
491 	this() {}
492 	this(Declaration decl) { kind = TypeKind.Primitive; text = decl.nestedName; typeName = text; typeDecl = decl; }
493 
494 	static Type makePointer(Type base_type) { auto ret = new Type; ret.kind = TypeKind.Pointer; ret.elementType = base_type; return ret; }
495 	static Type makeArray(Type base_type) { auto ret = new Type; ret.kind = TypeKind.Array; ret.elementType = base_type; return ret; }
496 	static Type makeStaticArray(Type base_type, string length) { auto ret = new Type; ret.kind = TypeKind.StaticArray; ret.elementType = base_type; ret.arrayLength = length; return ret; }
497 	static Type makeAssociativeArray(Type value_type, Type key_type) { auto ret = new Type; ret.kind = TypeKind.AssociativeArray; ret.keyType = key_type; ret.elementType = value_type; return ret; }
498 	static Type makeFunction(Type return_type, Type[] parameter_types) { auto ret = new Type; ret.kind = TypeKind.Function; ret.returnType = return_type; ret.parameterTypes = parameter_types; return ret; }
499 	static Type makeDelegate(Type return_type, Type[] parameter_types) { auto ret = new Type; ret.kind = TypeKind.Delegate; ret.returnType = return_type; ret.parameterTypes = parameter_types; return ret; }
500 
501 	override equals_t opEquals(Object other_)
502 	{
503 		auto other = cast(Type)other_;
504 		if( !other ) return false;
505 		if( kind != other.kind ) return false;
506 		if( attributes != other.attributes ) return false; // TODO use set comparison instead
507 		if( modifiers != other.modifiers ) return false; // TODO: use set comparison instead
508 
509 		final switch( kind ){
510 			case TypeKind.Primitive: return typeName == other.typeName && typeDecl == other.typeDecl;
511 			case TypeKind.Pointer: 
512 			case TypeKind.Array: return elementType == other.elementType;
513 			case TypeKind.StaticArray: return elementType == other.elementType && arrayLength == other.arrayLength;
514 			case TypeKind.AssociativeArray: return elementType == other.elementType && keyType == other.keyType;
515 			case TypeKind.Function:
516 			case TypeKind.Delegate:
517 				if( returnType != other.returnType ) return false;
518 				if( parameterTypes.length != other.parameterTypes.length ) return false;
519 				foreach( i, p; parameterTypes )
520 					if( p != other.parameterTypes[i] )
521 						return false;
522 		}
523 		return true;
524 	}
525 }