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