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