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