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 }