1 // Copyright Brian Schott (Hackerpilot) 2014. 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 6 module symbol_finder; 7 8 import std.stdio : File; 9 import dparse.lexer; 10 import dparse.parser; 11 import dparse.ast; 12 import std.stdio; 13 import std.file:isFile; 14 15 void findDeclarationOf(File output, string symbolName, string[] fileNames) 16 { 17 import std.array : uninitializedArray, array; 18 import std.conv : to; 19 LexerConfig config; 20 StringCache cache = StringCache(StringCache.defaultBucketCount); 21 auto visitor = new FinderVisitor(output, symbolName); 22 foreach (fileName; fileNames) 23 { 24 File f = File(fileName); 25 assert (isFile(fileName)); 26 if (f.size == 0) continue; 27 auto bytes = uninitializedArray!(ubyte[])(to!size_t(f.size)); 28 f.rawRead(bytes); 29 auto tokens = getTokensForParser(bytes, config, &cache); 30 Module m = parseModule(tokens.array, fileName, null, &doNothing); 31 visitor.fileName = fileName; 32 visitor.visit(m); 33 } 34 } 35 36 private: 37 38 void doNothing(string, size_t, size_t, string, bool) {} 39 40 class FinderVisitor : ASTVisitor 41 { 42 this(File output, string symbolName) 43 { 44 this.output = output; 45 this.symbolName = symbolName; 46 } 47 48 mixin generateVisit!FunctionDeclaration; 49 mixin generateVisit!ClassDeclaration; 50 mixin generateVisit!InterfaceDeclaration; 51 mixin generateVisit!StructDeclaration; 52 mixin generateVisit!UnionDeclaration; 53 mixin generateVisit!TemplateDeclaration; 54 55 override void visit(const EnumDeclaration dec) 56 { 57 if (dec.name.text == symbolName) 58 output.writefln("%s(%d:%d)", fileName, dec.name.line, dec.name.column); 59 } 60 61 override void visit(const AnonymousEnumMember member) 62 { 63 if (member.name.text == symbolName) 64 output.writefln("%s(%d:%d)", fileName, member.name.line, member.name.column); 65 } 66 67 override void visit(const EnumMember member) 68 { 69 if (member.name.text == symbolName) 70 output.writefln("%s(%d:%d)", fileName, member.name.line, member.name.column); 71 } 72 73 override void visit(const AliasDeclaration dec) 74 { 75 if (dec.identifierList !is null) 76 { 77 foreach (ident; dec.identifierList.identifiers) 78 { 79 if (ident.text == symbolName) 80 output.writefln("%s(%d:%d)", fileName, ident.line, ident.column); 81 } 82 } 83 foreach (initializer; dec.initializers) 84 { 85 if (initializer.name.text == symbolName) 86 output.writefln("%s(%d:%d)", fileName, initializer.name.line, 87 initializer.name.column); 88 } 89 } 90 91 override void visit(const Declarator dec) 92 { 93 if (dec.name.text == symbolName) 94 output.writefln("%s(%d:%d)", fileName, dec.name.line, dec.name.column); 95 } 96 97 override void visit(const AutoDeclaration ad) 98 { 99 foreach (id; ad.identifiers) 100 { 101 if (id.text == symbolName) 102 output.writefln("%s(%d:%d)", fileName, id.line, id.column); 103 } 104 } 105 106 override void visit(const FunctionBody) {} 107 108 mixin template generateVisit(T) 109 { 110 override void visit(const T t) 111 { 112 if (t.name.text == symbolName) 113 output.writefln("%s(%d:%d)", fileName, t.name.line, t.name.column); 114 t.accept(this); 115 } 116 } 117 118 alias visit = ASTVisitor.visit; 119 120 File output; 121 string symbolName; 122 string fileName; 123 }