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 int line; 244 bool isTemplate; 245 TemplateParameterDeclaration[] templateArgs; 246 247 override @property string kindCaption() const { return "Declaration"; } 248 abstract @property Declaration dup(); 249 abstract @property DeclarationKind kind(); 250 @property inout(Declaration) parentDeclaration() inout { return cast(inout(Declaration))parent; } 251 @property Module module_() { 252 Entity e = parent; 253 while(e){ 254 if( auto m = cast(Module)e ) return m; 255 e = e.parent; 256 } 257 assert(false, "Declaration without module?"); 258 } 259 @property const(Module) module_() const { 260 Rebindable!(const(Entity)) e = parent; 261 while(e){ 262 if( auto m = cast(const(Module))e ) return m; 263 e = e.parent; 264 } 265 assert(false, "Declaration without module?"); 266 } 267 268 @property string templateArgsString() const { 269 if (!isTemplate) return null; 270 return format("(%s)", (cast(string[])templateArgs.map!(a => a.name).array).join(", ")); 271 } 272 273 this(Entity parent, string name){ super(parent, name); } 274 275 abstract override void iterateChildren(bool delegate(Entity) del); 276 277 protected void copyFrom(Declaration src) 278 { 279 this.docGroup = src.docGroup; 280 this.inheritingDecl = src.inheritingDecl; 281 this.protection = src.protection; 282 this.line = src.line; 283 this.templateArgs = src.templateArgs; 284 } 285 } 286 287 class TypedDeclaration : Declaration { 288 Type type; 289 290 this(Entity parent, string name){ super(parent, name); } 291 292 override @property string kindCaption() const { return "Typed declaration"; } 293 294 abstract override @property DeclarationKind kind() const; 295 296 abstract override void iterateChildren(bool delegate(Entity) del); 297 298 protected override void copyFrom(Declaration src) 299 { 300 super.copyFrom(src); 301 if (auto tsrc = cast(TypedDeclaration)src) 302 this.type = tsrc.type; 303 } 304 } 305 306 final class VariableDeclaration : TypedDeclaration { 307 Value initializer; 308 309 override @property string kindCaption() const { return "Variable"; } 310 override @property VariableDeclaration dup() { auto ret = new VariableDeclaration(parent, name); ret.copyFrom(this); ret.initializer = initializer; return ret; } 311 override @property DeclarationKind kind() const { return DeclarationKind.Variable; } 312 313 this(Entity parent, string name){ super(parent, name); } 314 315 override void iterateChildren(bool delegate(Entity) del) {} 316 } 317 318 final class FunctionDeclaration : TypedDeclaration { 319 Type returnType; 320 VariableDeclaration[] parameters; 321 string[] attributes; 322 323 override @property string kindCaption() const { return "Function"; } 324 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; } 325 override @property DeclarationKind kind() const { return DeclarationKind.Function; } 326 327 this(Entity parent, string name){ super(parent, name); } 328 329 bool hasAttribute(string att) const { foreach( a; attributes ) if( a == att ) return true; return false; } 330 331 override void iterateChildren(bool delegate(Entity) del) 332 { 333 foreach( p; parameters ) del(p); 334 } 335 } 336 337 class CompositeTypeDeclaration : Declaration { 338 Declaration[] members; 339 340 override @property string kindCaption() const { return "Composite type"; } 341 override abstract @property DeclarationKind kind() const; 342 343 this(Entity parent, string name){ super(parent, name); } 344 345 override void iterateChildren(bool delegate(Entity) del) 346 { 347 foreach( m; members ) if( !del(m) ) return; 348 } 349 } 350 351 final class StructDeclaration : CompositeTypeDeclaration { 352 override @property string kindCaption() const { return "Struct"; } 353 override @property StructDeclaration dup() { auto ret = new StructDeclaration(parent, name); ret.copyFrom(this); ret.members = members; return ret; } 354 override @property DeclarationKind kind() const { return DeclarationKind.Struct; } 355 356 this(Entity parent, string name){ super(parent, name); } 357 } 358 359 final class UnionDeclaration : CompositeTypeDeclaration { 360 override @property string kindCaption() const { return "Union"; } 361 override @property UnionDeclaration dup() { auto ret = new UnionDeclaration(parent, name); ret.copyFrom(this); ret.members = members; return ret; } 362 override @property DeclarationKind kind() const { return DeclarationKind.Union; } 363 364 this(Entity parent, string name){ super(parent, name); } 365 } 366 367 final class InterfaceDeclaration : CompositeTypeDeclaration { 368 Type[] derivedInterfaces; 369 370 override @property string kindCaption() const { return "Interface"; } 371 override @property InterfaceDeclaration dup() { auto ret = new InterfaceDeclaration(parent, name); ret.copyFrom(this); ret.members = members; ret.derivedInterfaces = derivedInterfaces.dup; return ret; } 372 override @property DeclarationKind kind() const { return DeclarationKind.Interface; } 373 374 this(Entity parent, string name){ super(parent, name); } 375 } 376 377 final class ClassDeclaration : CompositeTypeDeclaration { 378 Type baseClass; 379 Type[] derivedInterfaces; 380 381 override @property string kindCaption() const { return "Class"; } 382 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; } 383 override @property DeclarationKind kind() const { return DeclarationKind.Class; } 384 385 this(Entity parent, string name){ super(parent, name); } 386 } 387 388 final class EnumDeclaration : CompositeTypeDeclaration { 389 Type baseType; 390 391 override @property string kindCaption() const { return "Enum"; } 392 override @property EnumDeclaration dup() { auto ret = new EnumDeclaration(parent, name); ret.copyFrom(this); ret.members = members; ret.baseType = baseType; return ret; } 393 override @property DeclarationKind kind() const { return DeclarationKind.Enum; } 394 395 this(Entity parent, string name){ super(parent, name); } 396 } 397 398 final class EnumMemberDeclaration : Declaration { 399 Value value; 400 401 override @property string kindCaption() const { return "Enum member"; } 402 override @property EnumMemberDeclaration dup() { auto ret = new EnumMemberDeclaration(parent, name); ret.copyFrom(this); ret.value = value; return ret; } 403 override @property DeclarationKind kind() const { return DeclarationKind.EnumMember; } 404 @property Type type() { if( !value ) return null; return value.type; } 405 406 this(Entity parent, string name){ super(parent, name); } 407 408 override void iterateChildren(bool delegate(Entity) del) {} 409 } 410 411 final class AliasDeclaration : Declaration { 412 string[] attributes; 413 Declaration targetDecl; 414 Type targetType; 415 416 override @property string kindCaption() const { return "Alias"; } 417 override @property AliasDeclaration dup() { auto ret = new AliasDeclaration(parent, name); ret.copyFrom(this); ret.targetDecl = targetDecl; ret.targetType = targetType; return ret; } 418 override @property DeclarationKind kind() const { return DeclarationKind.Alias; } 419 @property Type type() { return targetType; } 420 421 this(Entity parent, string name){ super(parent, name); } 422 423 override void iterateChildren(bool delegate(Entity) del) {} 424 } 425 426 final class TemplateDeclaration : Declaration { 427 Declaration[] members; 428 429 override @property string kindCaption() const { return "Template"; } 430 override @property TemplateDeclaration dup() { auto ret = new TemplateDeclaration(parent, name); ret.copyFrom(this); ret.members = members.dup; return ret; } 431 override @property DeclarationKind kind() const { return DeclarationKind.Template; } 432 433 this(Entity parent, string name){ super(parent, name); isTemplate = true; } 434 435 override void iterateChildren(bool delegate(Entity) del) 436 { 437 foreach( m; members ) del(m); 438 } 439 } 440 441 final class TemplateParameterDeclaration : TypedDeclaration { 442 override @property string kindCaption() const { return "Template parameter"; } 443 override @property TemplateParameterDeclaration dup() { auto ret = new TemplateParameterDeclaration(parent, name); ret.copyFrom(this); ret.type = type; return ret; } 444 override @property DeclarationKind kind() const { return DeclarationKind.TemplateParameter; } 445 446 this(Entity parent, string name){ super(parent, name); type = new Type(this); } 447 448 override void iterateChildren(bool delegate(Entity) del) {} 449 } 450 451 final class Value { 452 Type type; 453 string valueString; 454 } 455 456 enum TypeKind { 457 Primitive, 458 Pointer, 459 Array, 460 StaticArray, 461 AssociativeArray, 462 Function, 463 Delegate 464 } 465 466 final class Type { 467 TypeKind kind; 468 string[] attributes; 469 string[] modifiers; 470 string templateArgs; 471 string text; // original text as in DMDs JSON output 472 // Primitive 473 string typeName; 474 Declaration typeDecl; 475 // P, A, SA, AA 476 Type elementType; 477 // SA 478 string arrayLength; 479 // AA 480 Type keyType; 481 // Function/Delegate 482 Type returnType; 483 Type[] parameterTypes; 484 string[] _parameterNames; 485 Value[] _parameterDefaultValues; 486 487 this() {} 488 this(Declaration decl) { kind = TypeKind.Primitive; text = decl.nestedName; typeName = text; typeDecl = decl; } 489 490 override equals_t opEquals(Object other_) 491 { 492 auto other = cast(Type)other_; 493 if( !other ) return false; 494 if( kind != other.kind ) return false; 495 if( attributes != other.attributes ) return false; // TODO use set comparison instead 496 if( modifiers != other.modifiers ) return false; // TODO: use set comparison instead 497 498 final switch( kind ){ 499 case TypeKind.Primitive: return typeName == other.typeName && typeDecl == other.typeDecl; 500 case TypeKind.Pointer: 501 case TypeKind.Array: return elementType == other.elementType; 502 case TypeKind.StaticArray: return elementType == other.elementType && arrayLength == other.arrayLength; 503 case TypeKind.AssociativeArray: return elementType == other.elementType && keyType == other.keyType; 504 case TypeKind.Function: 505 case TypeKind.Delegate: 506 if( returnType != other.returnType ) return false; 507 if( parameterTypes.length != other.parameterTypes.length ) return false; 508 foreach( i, p; parameterTypes ) 509 if( p != other.parameterTypes[i] ) 510 return false; 511 } 512 return true; 513 } 514 }