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 }