1 module dlangide.tools.d.dparser;
2 
3 version(USE_LIBDPARSE):
4 
5 import dlangui.core.logger;
6 
7 import std.d.lexer;
8 import std.d.parser;
9 import std.d.ast;
10 import std.algorithm;
11 import std..string;
12 import std.path;
13 import std.file;
14 import std.conv;
15 
16 string importDeclToModuleName(const IdentifierChain chain) {
17     char[] buf;
18     foreach(token; chain.identifiers) {
19         if (buf.length)
20             buf ~= '.';
21         buf ~= token.text;
22     }
23     return buf.dup;
24 }
25 
26 class DParsedModule {
27     protected string _moduleName;
28     protected string _moduleFile;
29     protected StringCache* _cache;
30     protected Module _ast;
31     protected string[] _imports;
32     protected const(Token)[] _tokens;
33     protected LexerConfig _lexerConfig;
34     protected ubyte[] _sourceCode;
35 
36     @property string filename() { return _moduleFile; }
37     /// module name, e.g. "std.stdio"
38     @property string moduleName() { return _moduleName; }
39 
40     this(StringCache* cache, string filename) {
41         _cache = cache;
42         _moduleFile = filename;
43     }
44 
45     static void msgFunction(string fn, size_t line, size_t col, string msg, bool isError) {
46         debug(DParseErrors) Log.d("parser error: ", fn, "(", line, ":", col, ") : ", isError ? "Error: ": "Warning: ", msg);
47     }
48 
49     static class ImportListIterator : ASTVisitor {
50         string[] _imports;
51         @property string[] imports() {
52             return _imports;
53         }
54         private void addImport(string m) {
55             foreach(imp; _imports)
56                 if (imp.equal(m))
57                     return;
58             _imports ~= m;
59         }
60 
61         alias visit = ASTVisitor.visit;
62         //override void visit(const Module module_) { 
63         //    super.visit(module_); 
64         //}
65         override void visit(const ImportDeclaration importDeclaration) { 
66             foreach(imp; importDeclaration.singleImports) {
67                 addImport(importDeclToModuleName(imp.identifierChain));
68             }
69         }
70 
71         void run(Module ast) {
72             _imports.length = 0;
73             visit(ast);
74         }
75     }
76     private ImportListIterator _importIterator;
77     void scanImports() {
78         if (!_importIterator)
79             _importIterator = new ImportListIterator();
80         _importIterator.run(_ast);
81         _imports = _importIterator.imports;
82     }
83 
84 
85 
86     private IdentPositionIterator _identPositionIterator;
87     IdentDefinitionLookupResult findTokenNode(const(Token)* tokenToFindPositionFor, const(Token)* tokenToFindReferencesFor) {
88         if (!_identPositionIterator)
89             _identPositionIterator = new IdentPositionIterator();
90         auto foundNode = _identPositionIterator.run(this, _ast, tokenToFindPositionFor, tokenToFindReferencesFor);
91         return foundNode;
92     }
93 
94 
95     void findDeclaration(int bytePosition, DParsedModule[string] scanned) {
96         const(Token) * token = findIdentTokenByBytePosition(bytePosition);
97         if (!token)
98             return;
99 
100         Log.d("Identifier token found by position: ", token.text);
101         IdentDefinitionLookupResult res = findTokenNode(token, token);
102         if (!res.found)
103             return;
104         Log.d("Found in node:");
105         res.found.dump();
106     }
107 
108     const(Token) * findIdentTokenByBytePosition(int bytePosition) {
109         const(Token) * res = null;
110         for(int i = 0; i < _tokens.length; i++) {
111             auto t = &_tokens[i];
112             if (t.index >= bytePosition) {
113                 if (res && *res == tok!"identifier")
114                     return res; // return this or previous identifier token
115                 if (t.index == bytePosition && (*t) == tok!"identifier")
116                     return t; // return next identifier token
117             }
118             res = t;
119         }
120         return res;
121     }
122 
123     void parse(ubyte[] sourceCode) {
124         _sourceCode = sourceCode;
125         _tokens = getTokensForParser(sourceCode, _lexerConfig, _cache);
126         uint errorCount;
127         uint warningCount;
128         _ast = parseModule(_tokens, _moduleFile, null, &msgFunction, &errorCount, &warningCount);
129         _moduleName = _ast.moduleDeclaration ? importDeclToModuleName(_ast.moduleDeclaration.moduleName) : null;
130         scanImports();
131     }
132 
133     private void addImport(string m) {
134         foreach(imp; _imports)
135             if (imp.equal(m))
136                 return;
137         _imports ~= m;
138     }
139 
140     @property string[] imports() {
141         return _imports;
142     }
143 }
144 
145 /// D source code parsing service
146 class DParsingService {
147 
148     protected static __gshared DParsingService _instance;
149     /// singleton
150     static @property DParsingService instance() {
151         if (!_instance) {
152             _instance = new DParsingService();
153         }
154         return _instance;
155     }
156     /// destroy singleton
157     static void shutdown() {
158         destroy(_instance);
159         _instance = null;
160     }
161 
162     protected StringCache _cache;
163     protected string[] _importPaths;
164     protected DParsedModule[] _modules;
165     protected DParsedModule[string] _moduleByName;
166     protected DParsedModule[string] _moduleByFile;
167     protected bool[string] _notFoundModules;
168     protected DParsedModule _currentModule; // current module
169 
170     this() {
171         _cache = StringCache(16);
172     }
173 
174     void scanDeps(DParsedModule m, ref DParsedModule[string]scanned) {
175         foreach(imp; m.imports) {
176             if (imp !in scanned) {
177                 DParsedModule impModule = getOrParseModule(imp);
178                 scanned[imp] = impModule;
179                 if (impModule)
180                     scanDeps(impModule, scanned);
181             }
182         }
183     }
184 
185     DParsedModule scan(ubyte[] sourceCode, string filename, ref DParsedModule[string] scanned) {
186         Log.d("scanning ", filename);
187         destroy(_notFoundModules);
188         DParsedModule res = new DParsedModule(&_cache, filename);
189         res.parse(sourceCode);
190         _currentModule = res;
191         Log.d("moduleName: ", res.moduleName, " imports: ", res.imports);
192         Log.d("deps:");
193         scanned[res.moduleName] = res;
194         scanDeps(res, scanned);
195         foreach(key, value; scanned) {
196             Log.d("     module ", key, " : ", value ? value.filename : "NOT FOUND");
197         }
198         return res;
199     }
200 
201     DParsedModule findDeclaration(ubyte[] sourceCode, string filename, int bytePosition) {
202         DParsedModule[string] scanned;
203         DParsedModule m = scan(sourceCode, filename, scanned);
204         m.findDeclaration(bytePosition, scanned);
205         return m;
206     }
207 
208     /// converts some.module.name to some/module/name.d
209     string moduleNameToPackagePath(string moduleName) {
210         string[] pathSegments = moduleName.split(".");
211         string normalized = buildNormalizedPath(pathSegments);
212         return normalized ~ ".d";
213     }
214 
215     string findModuleFile(string moduleName) {
216         string packagePath = moduleNameToPackagePath(moduleName);
217         foreach(ip; _importPaths) {
218             //Log.d("packagePath: ", packagePath, " importPath: ", ip);
219             string path = buildNormalizedPath(ip, packagePath);
220             if (path.exists && path.isFile) {
221                 //Log.d("found ", path);
222                 return path;
223             }
224             string pathImports = path ~ "i";
225             if (pathImports.exists && pathImports.isFile) {
226                 //Log.d("found ", pathImports);
227                 return pathImports;
228             }
229         }
230         return null;
231     }
232 
233     DParsedModule getOrParseModule(string moduleName) {
234         if (_currentModule) {
235             if (moduleName.equal(_currentModule.moduleName))
236                 return _currentModule; // module being scanned
237         }
238         if (auto m = moduleName in _moduleByName) {
239             return *m;
240         }
241         if (moduleName in _notFoundModules) {
242             Log.d("module is in not found: ", moduleName);
243             return null; // already listed as not found
244         }
245         string filename = findModuleFile(moduleName);
246         if (!filename) {
247             Log.d("module not found: ", moduleName);
248             _notFoundModules[moduleName] = true;
249             return null;
250         }
251         try {
252             DParsedModule res = new DParsedModule(&_cache, filename);
253             ubyte[] sourceCode = cast(ubyte[])read(filename);
254             res.parse(sourceCode);
255             _moduleByName[moduleName] = res;
256             _moduleByFile[filename] = res;
257             return res;
258         } catch (Exception e) {
259             Log.d("exception while parsing: ", moduleName, " : ", e);
260             _notFoundModules[moduleName] = true;
261             return null;
262         }
263     }
264 
265     void addImportPaths(in string[] paths) {
266         Log.d("addImportPaths: ", paths);
267         foreach(p; paths) {
268             string ap = absolutePath(buildNormalizedPath(p));
269             bool found = false;
270             foreach(ip; _importPaths)
271                 if (ip.equal(ap)) {
272                     found = true;
273                     break;
274                 }
275             if (!found)
276                 _importPaths ~= ap;
277         }
278     }
279 }
280 
281 
282 static class ImportInfo {
283     string moduleName;
284     const ImportDeclaration decl;
285     this(const ImportDeclaration decl, string moduleName) {
286         this.decl = decl;
287         this.moduleName = moduleName;
288     }
289 }
290 enum DeclarationType {
291     none,
292     classVariableDeclaration,
293     structVariableDeclaration,
294     variableDeclaration,
295     classDeclaration, // class declaration
296     structDeclaration, // struct declaration
297     classFunctionDeclaration, // function inside class
298     structFunctionDeclaration, // function inside struct
299     functionDeclaration, // just function
300     functionParameter, // function parameter
301     functionTemplateTypeParameter,
302     classTemplateTypeParameter,
303     structTemplateTypeParameter,
304     templateTypeParameter,
305 }
306 static class IdentContext {
307     DParsedModule mod;
308     Token token;
309     ImportInfo[] imports;
310     const(ASTNode)[] stack;
311     ASTNode declarationNode;
312     ASTNode baseDeclarationNode;
313     DeclarationType declarationType = DeclarationType.none;
314     this(DParsedModule mod, const Token token, ImportInfo[] imports, const(ASTNode)[] stack) {
315         this.mod = mod;
316         this.token = token;
317         this.imports = imports;
318         this.stack = stack;
319         initDeclarationType();
320     }
321     /// returns true if context ident token is the same as t
322     bool sametok(const Token t) {
323         return t.text.ptr is token.text.ptr;
324     }
325     /// casts top object on stack with specified offset to specified type and returns result
326     T match(T)(int offset = 0) {
327         if (offset < 0 || offset >= stack.length)
328             return null;
329         return cast(T)stack[$ - 1 - offset];
330     }
331     /// returns true if top object on stack is T1 and second is T2
332     bool match(T1, T2)() {
333         if (stack.length < 2)
334             return false;
335         return cast(T1)stack[$ - 1] !is null && cast(T2)stack[$ - 2] !is null;
336     }
337     /// returns true if top object on stack is T1 and second is T2
338     bool match(T1, T2, T3)() {
339         if (stack.length < 3)
340             return false;
341         return cast(T1)stack[$ - 1] !is null && cast(T2)stack[$ - 2] !is null && cast(T3)stack[$ - 3] !is null;
342     }
343     bool initDeclarationType() {
344         if (match!(Declarator, VariableDeclaration) && sametok(match!Declarator.name)) {
345             if (match!StructBody(2) && match!ClassDeclaration(3)) {
346                 declarationType = DeclarationType.classVariableDeclaration;
347                 declarationNode = match!VariableDeclaration(1);
348                 baseDeclarationNode = match!ClassDeclaration(3);
349             } else if (match!StructBody(2) && match!StructDeclaration(3)) {
350                 declarationType = DeclarationType.structVariableDeclaration;
351                 declarationNode = match!VariableDeclaration(1);
352                 baseDeclarationNode = match!StructDeclaration(3);
353             } else {
354                 declarationType = DeclarationType.variableDeclaration;
355                 declarationNode = match!VariableDeclaration(1);
356             }
357             return true;
358         } else if (match!ClassDeclaration && sametok(match!ClassDeclaration.name)) {
359             declarationType = DeclarationType.classDeclaration;
360             declarationNode = match!ClassDeclaration;
361             return true;
362         } else if (match!StructDeclaration && sametok(match!StructDeclaration.name)) {
363             declarationType = DeclarationType.structDeclaration;
364             declarationNode = match!StructDeclaration;
365             return true;
366         } else if (match!FunctionDeclaration && sametok(match!FunctionDeclaration.name)) {
367             if (match!StructBody(1) && match!ClassDeclaration(2)) {
368                 declarationType = DeclarationType.classFunctionDeclaration;
369                 declarationNode = match!FunctionDeclaration;
370                 baseDeclarationNode = match!ClassDeclaration(2);
371             } else if (match!StructBody(1) && match!StructDeclaration(2)) {
372                 declarationType = DeclarationType.structFunctionDeclaration;
373                 declarationNode = match!FunctionDeclaration;
374                 baseDeclarationNode = match!StructDeclaration(2);
375             } else {
376                 declarationType = DeclarationType.functionDeclaration;
377                 declarationNode = match!FunctionDeclaration;
378             }
379             return true;
380         } else if (match!Parameter && sametok(match!Parameter.name) && match!Parameters(1)) {
381             if (match!FunctionDeclaration(2)) {
382                 declarationType = DeclarationType.functionParameter;
383                 declarationNode = match!Parameter;
384                 baseDeclarationNode = match!FunctionDeclaration(2);
385                 return true;
386             }
387         } else if (match!TemplateTypeParameter && sametok(match!TemplateTypeParameter.identifier) && match!TemplateParameter(1) && match!TemplateParameterList(2) && match!TemplateParameters(3)) {
388             if (match!FunctionDeclaration(4)) {
389                 declarationType = DeclarationType.functionTemplateTypeParameter;
390                 declarationNode = match!TemplateTypeParameter;
391                 baseDeclarationNode = match!FunctionDeclaration(4);
392                 return true;
393             } else if (match!ClassDeclaration(4)) {
394                 declarationType = DeclarationType.classTemplateTypeParameter;
395                 declarationNode = match!TemplateTypeParameter;
396                 baseDeclarationNode = match!ClassDeclaration(4);
397                 return true;
398             } else if (match!StructDeclaration(4)) {
399                 declarationType = DeclarationType.structTemplateTypeParameter;
400                 declarationNode = match!TemplateTypeParameter;
401                 baseDeclarationNode = match!StructDeclaration(4);
402                 return true;
403             }
404             declarationType = DeclarationType.templateTypeParameter;
405             declarationNode = match!TemplateTypeParameter;
406             return true;
407         }
408         return false;
409     }
410     void dump() {
411         Log.d("module: ", mod.moduleName, 
412               "\n\ttoken: ", token.text, "    [", token.line, ":", token.column, "-", token.index, "]   declType: ", declarationType, 
413               " declNode: ", declarationNode, " baseDeclNode: ", baseDeclarationNode, 
414               "\n\timports: ", imports, "\n\tcontext: ", stack);
415     }   
416 }
417 
418 static class IdentDefinitionLookupResult {
419     DParsedModule mod;
420     const(Token) tokenToFind;
421     const(Token) tokenToFindReferences;
422     IdentContext found;
423     IdentContext[] references;
424     this(DParsedModule mod, const(Token) * tokenToFind, const(Token) * tokenToFindReferences, IdentContext found, IdentContext[] references) {
425         this.mod = mod;
426         this.tokenToFind = *tokenToFind;
427         this.tokenToFindReferences = *tokenToFindReferences;
428         this.found = found;
429         this.references = references;
430     }
431 }
432 
433 static class IdentPositionIterator : ASTVisitor {
434 
435     private const(Token) * _tokenToFind;
436     private const(Token) * _tokenToFindReferences;
437     private ImportInfo[] _scopedImportList;
438     private const(ASTNode)[] _stack;
439     private IdentContext _found;
440     private IdentContext[] _references;
441     private DParsedModule _mod;
442 
443 
444     private void addImport(const ImportDeclaration decl, string m) {
445         foreach(imp; _scopedImportList)
446             if (imp.moduleName.equal(m))
447                 return;
448         _scopedImportList ~= new ImportInfo(decl, m);
449     }
450 
451     private void push(const ASTNode node) {
452         _stack ~= node;
453     }
454 
455     private const(ASTNode)pop() {
456         assert(_stack.length > 0);
457         auto res = _stack[$ - 1];
458         _stack.length--;
459         return res;
460     }
461 
462     IdentDefinitionLookupResult run(DParsedModule mod, Module ast, const(Token) * tokenToFind, const(Token) * tokenToFindReferences) {
463         _mod = mod;
464         _stack.length = 0;
465         _references.length = 0;
466         _found = null;
467         _tokenToFind = tokenToFind;
468         _tokenToFindReferences = tokenToFindReferences;
469         visit(ast);
470         if (_references.length > 0) {
471             Log.d("References to the same ident found: ");
472             foreach(r; _references)
473                 r.dump();
474         }
475         return new IdentDefinitionLookupResult(_mod, _tokenToFind, _tokenToFindReferences, _found, _references);
476     }
477 
478     //alias visit = ASTVisitor.visit;
479     static string def(string param) {
480         return "push(" ~ param ~ "); super.visit(" ~ param ~ "); pop();";
481     }
482     /// for objects which contain token not covered by visit()
483     static string deftoken(string param, string tokenField) {
484         return "push(" ~ param ~ "); visit(" ~ param ~ '.' ~ tokenField ~ "); super.visit(" ~ param ~ "); pop();";
485     }
486     /// for objects which can affect scope - save imports list, and restore after visiting
487     static string defblock(string param) {
488         return "size_t importPos = _scopedImportList.length; push(" ~ param ~ "); super.visit(" ~ param ~ "); pop(); _scopedImportList.length = importPos;";
489     }
490 
491     @property private const(ASTNode)[] copyStack() {
492         const(ASTNode)[] res;
493         foreach(n; _stack)
494             res ~= n;
495         return res;
496     }
497 
498     @property private ImportInfo[] copyImports() {
499         ImportInfo[]res;
500         foreach(imp; _scopedImportList)
501             res ~= imp;
502         return res;
503     }
504 
505     override void visit(const Token t) {
506         if (_tokenToFind && t.index == _tokenToFind.index) {
507             _found = new IdentContext(_mod, t, copyImports, copyStack);
508         } else if (_tokenToFindReferences && t.text.ptr is _tokenToFindReferences.text.ptr) {
509             _references ~= new IdentContext(_mod, t, copyImports, copyStack);
510         }
511     }
512 
513     override void visit(const ExpressionNode n) { 
514         //mixin(def("n")); 
515         super.visit(n);
516     }
517     override void visit(const AddExpression addExpression) { mixin(def("addExpression")); }
518     override void visit(const AliasDeclaration aliasDeclaration) {  mixin(def("aliasDeclaration")); }
519     override void visit(const AliasInitializer aliasInitializer) { mixin(def("aliasInitializer")); }
520     override void visit(const AliasThisDeclaration aliasThisDeclaration) { mixin(def("aliasThisDeclaration")); }
521     override void visit(const AlignAttribute alignAttribute) { mixin(def("alignAttribute")); }
522     override void visit(const AndAndExpression andAndExpression) { mixin(def("andAndExpression")); }
523     override void visit(const AndExpression andExpression) { mixin(def("andExpression")); }
524     override void visit(const AnonymousEnumDeclaration anonymousEnumDeclaration) { mixin(def("anonymousEnumDeclaration")); }
525     override void visit(const AnonymousEnumMember anonymousEnumMember) { mixin(def("anonymousEnumMember")); }
526     override void visit(const ArgumentList argumentList) { mixin(def("argumentList")); }
527     override void visit(const Arguments arguments) { mixin(def("arguments")); }
528     override void visit(const ArrayInitializer arrayInitializer) { mixin(def("arrayInitializer")); }
529     override void visit(const ArrayLiteral arrayLiteral) { mixin(def("arrayLiteral")); }
530     override void visit(const ArrayMemberInitialization arrayMemberInitialization) { mixin(def("arrayMemberInitialization")); }
531     override void visit(const AsmAddExp asmAddExp) { mixin(def("asmAddExp")); }
532     override void visit(const AsmAndExp asmAndExp) { mixin(def("asmAndExp")); }
533     override void visit(const AsmBrExp asmBrExp) { mixin(def("asmBrExp")); }
534     override void visit(const AsmEqualExp asmEqualExp) { mixin(def("asmEqualExp")); }
535     override void visit(const AsmExp asmExp) { mixin(def("asmExp")); }
536     override void visit(const AsmInstruction asmInstruction) { mixin(def("asmInstruction")); }
537     override void visit(const AsmLogAndExp asmLogAndExp) { mixin(def("asmLogAndExp")); }
538     override void visit(const AsmLogOrExp asmLogOrExp) { mixin(def("asmLogOrExp")); }
539     override void visit(const AsmMulExp asmMulExp) { mixin(def("asmMulExp")); }
540     override void visit(const AsmOrExp asmOrExp) { mixin(def("asmOrExp")); }
541     override void visit(const AsmPrimaryExp asmPrimaryExp) { mixin(def("asmPrimaryExp")); }
542     override void visit(const AsmRelExp asmRelExp) { mixin(def("asmRelExp")); }
543     override void visit(const AsmShiftExp asmShiftExp) { mixin(def("asmShiftExp")); }
544     override void visit(const AsmStatement asmStatement) { mixin(def("asmStatement")); }
545     override void visit(const AsmTypePrefix asmTypePrefix) { mixin(def("asmTypePrefix")); }
546     override void visit(const AsmUnaExp asmUnaExp) { mixin(def("asmUnaExp")); }
547     override void visit(const AsmXorExp asmXorExp) { mixin(def("asmXorExp")); }
548     override void visit(const AssertExpression assertExpression) { mixin(def("assertExpression")); }
549     override void visit(const AssignExpression assignExpression) { mixin(def("assignExpression")); }
550     override void visit(const AssocArrayLiteral assocArrayLiteral) { mixin(def("assocArrayLiteral")); }
551     override void visit(const AtAttribute atAttribute) { 
552         mixin(deftoken("atAttribute", "identifier")); 
553     }
554     override void visit(const Attribute attribute) { 
555         mixin(deftoken("attribute", "attribute")); 
556     }
557     override void visit(const AttributeDeclaration attributeDeclaration) { mixin(def("attributeDeclaration")); }
558     override void visit(const AutoDeclaration autoDeclaration) { mixin(def("autoDeclaration")); }
559     override void visit(const BlockStatement blockStatement) { 
560         mixin(defblock("blockStatement"));
561     }
562     override void visit(const BodyStatement bodyStatement) { mixin(def("bodyStatement")); }
563     override void visit(const BreakStatement breakStatement) { mixin(def("breakStatement")); }
564     override void visit(const BaseClass baseClass) { mixin(def("baseClass")); }
565     override void visit(const BaseClassList baseClassList) { mixin(def("baseClassList")); }
566     override void visit(const CaseRangeStatement caseRangeStatement) { mixin(def("caseRangeStatement")); }
567     override void visit(const CaseStatement caseStatement) { mixin(def("caseStatement")); }
568     override void visit(const CastExpression castExpression) { mixin(def("castExpression")); }
569     override void visit(const CastQualifier castQualifier) { mixin(def("castQualifier")); }
570     override void visit(const Catch catch_) { mixin(def("catch_")); }
571     override void visit(const Catches catches) { mixin(def("catches")); }
572     override void visit(const ClassDeclaration classDeclaration) { 
573         mixin(deftoken("classDeclaration", "name")); 
574     }
575     override void visit(const CmpExpression cmpExpression) { mixin(def("cmpExpression")); }
576     override void visit(const CompileCondition compileCondition) { mixin(def("compileCondition")); }
577     override void visit(const ConditionalDeclaration conditionalDeclaration) { 
578         super.visit(conditionalDeclaration);
579         // Don't put conditional decl into stack
580         // TODO: check conditional compilation conditions
581         //mixin(def("conditionalDeclaration")); 
582     }
583     override void visit(const ConditionalStatement conditionalStatement) { mixin(def("conditionalStatement")); }
584     override void visit(const Constraint constraint) { mixin(def("constraint")); }
585     override void visit(const Constructor constructor) { mixin(def("constructor")); }
586     override void visit(const ContinueStatement continueStatement) { mixin(def("continueStatement")); }
587     override void visit(const DebugCondition debugCondition) { mixin(def("debugCondition")); }
588     override void visit(const DebugSpecification debugSpecification) { mixin(def("debugSpecification")); }
589     override void visit(const Declaration declaration) { 
590         super.visit(declaration);
591         //mixin(def("declaration")); 
592     }
593     override void visit(const DeclarationOrStatement declarationsOrStatement) { 
594         super.visit(declarationsOrStatement);
595         //mixin(def("declarationsOrStatement")); 
596     }
597     override void visit(const DeclarationsAndStatements declarationsAndStatements) { mixin(def("declarationsAndStatements")); }
598     override void visit(const Declarator declarator) { 
599         mixin(deftoken("declarator", "name"));
600     }
601     override void visit(const DefaultStatement defaultStatement) { mixin(def("defaultStatement")); }
602     override void visit(const DeleteExpression deleteExpression) { mixin(def("deleteExpression")); }
603     override void visit(const DeleteStatement deleteStatement) { mixin(def("deleteStatement")); }
604     override void visit(const Deprecated deprecated_) { mixin(def("deprecated_")); }
605     override void visit(const Destructor destructor) { mixin(def("destructor")); }
606     override void visit(const DoStatement doStatement) { mixin(def("doStatement")); }
607     override void visit(const EnumBody enumBody) { mixin(def("enumBody")); }
608     override void visit(const EnumDeclaration enumDeclaration) { 
609         mixin(deftoken("enumDeclaration", "name")); 
610     }
611     override void visit(const EnumMember enumMember) { mixin(def("enumMember")); }
612     override void visit(const EponymousTemplateDeclaration eponymousTemplateDeclaration) { mixin(def("eponymousTemplateDeclaration")); }
613     override void visit(const EqualExpression equalExpression) { mixin(def("equalExpression")); }
614     override void visit(const Expression expression) { mixin(def("expression")); }
615     override void visit(const ExpressionStatement expressionStatement) { mixin(def("expressionStatement")); }
616     override void visit(const FinalSwitchStatement finalSwitchStatement) { mixin(def("finalSwitchStatement")); }
617     override void visit(const Finally finally_) { mixin(def("finally_")); }
618     override void visit(const ForStatement forStatement) { mixin(def("forStatement")); }
619     override void visit(const ForeachStatement foreachStatement) { mixin(def("foreachStatement")); }
620     override void visit(const ForeachType foreachType) { mixin(def("foreachType")); }
621     override void visit(const ForeachTypeList foreachTypeList) { mixin(def("foreachTypeList")); }
622     override void visit(const FunctionAttribute functionAttribute) { mixin(def("functionAttribute")); }
623     override void visit(const FunctionBody functionBody) {
624         mixin(defblock("functionBody"));
625     }
626     override void visit(const FunctionCallExpression functionCallExpression) { mixin(def("functionCallExpression")); }
627     override void visit(const FunctionDeclaration functionDeclaration) { 
628         mixin(deftoken("functionDeclaration", "name")); 
629     }
630     override void visit(const FunctionLiteralExpression functionLiteralExpression) { mixin(def("functionLiteralExpression")); }
631     override void visit(const GotoStatement gotoStatement) { mixin(def("gotoStatement")); }
632     override void visit(const IdentifierChain identifierChain) { mixin(def("identifierChain")); }
633     override void visit(const IdentifierList identifierList) { mixin(def("identifierList")); }
634     override void visit(const IdentifierOrTemplateChain identifierOrTemplateChain) { mixin(def("identifierOrTemplateChain")); }
635     override void visit(const IdentifierOrTemplateInstance identifierOrTemplateInstance) { mixin(def("identifierOrTemplateInstance")); }
636     override void visit(const IdentityExpression identityExpression) { mixin(def("identityExpression")); }
637     override void visit(const IfStatement ifStatement) { mixin(def("ifStatement")); }
638     override void visit(const ImportBind importBind) { mixin(def("importBind")); }
639     override void visit(const ImportBindings importBindings) { mixin(def("importBindings")); }
640     override void visit(const ImportDeclaration importDeclaration) {
641         foreach(imp; importDeclaration.singleImports) {
642             addImport(importDeclaration, importDeclToModuleName(imp.identifierChain));
643         }
644         mixin(def("importDeclaration")); 
645     }
646     override void visit(const ImportExpression importExpression) { mixin(def("importExpression")); }
647     override void visit(const IndexExpression indexExpression) { mixin(def("indexExpression")); }
648     override void visit(const InExpression inExpression) { mixin(def("inExpression")); }
649     override void visit(const InStatement inStatement) { mixin(def("inStatement")); }
650     override void visit(const Initialize initialize) { mixin(def("initialize")); }
651     override void visit(const Initializer initializer) { mixin(def("initializer")); }
652     override void visit(const InterfaceDeclaration interfaceDeclaration) { 
653         mixin(deftoken("interfaceDeclaration", "name")); 
654     }
655     override void visit(const Invariant invariant_) { mixin(def("invariant_")); }
656     override void visit(const IsExpression isExpression) { mixin(def("isExpression")); }
657     override void visit(const KeyValuePair keyValuePair) { mixin(def("keyValuePair")); }
658     override void visit(const KeyValuePairs keyValuePairs) { mixin(def("keyValuePairs")); }
659     override void visit(const LabeledStatement labeledStatement) { mixin(def("labeledStatement")); }
660     override void visit(const LambdaExpression lambdaExpression) { mixin(def("lambdaExpression")); }
661     override void visit(const LastCatch lastCatch) { mixin(def("lastCatch")); }
662     override void visit(const LinkageAttribute linkageAttribute) { mixin(def("linkageAttribute")); }
663     override void visit(const MemberFunctionAttribute memberFunctionAttribute) { mixin(def("memberFunctionAttribute")); }
664     override void visit(const MixinDeclaration mixinDeclaration) { mixin(def("mixinDeclaration")); }
665     override void visit(const MixinExpression mixinExpression) { mixin(def("mixinExpression")); }
666     override void visit(const MixinTemplateDeclaration mixinTemplateDeclaration) { mixin(def("mixinTemplateDeclaration")); }
667     override void visit(const MixinTemplateName mixinTemplateName) { mixin(def("mixinTemplateName")); }
668     override void visit(const Module module_) { mixin(def("module_")); }
669     override void visit(const ModuleDeclaration moduleDeclaration) { mixin(def("moduleDeclaration")); }
670     override void visit(const MulExpression mulExpression) { mixin(def("mulExpression")); }
671     override void visit(const NewAnonClassExpression newAnonClassExpression) { mixin(def("newAnonClassExpression")); }
672     override void visit(const NewExpression newExpression) { mixin(def("newExpression")); }
673     override void visit(const NonVoidInitializer nonVoidInitializer) { mixin(def("nonVoidInitializer")); }
674     override void visit(const Operands operands) { mixin(def("operands")); }
675     override void visit(const OrExpression orExpression) { mixin(def("orExpression")); }
676     override void visit(const OrOrExpression orOrExpression) { mixin(def("orOrExpression")); }
677     override void visit(const OutStatement outStatement) { mixin(def("outStatement")); }
678     override void visit(const Parameter parameter) { mixin(def("parameter")); }
679     override void visit(const Parameters parameters) { mixin(def("parameters")); }
680     override void visit(const Postblit postblit) { mixin(def("postblit")); }
681     override void visit(const PowExpression powExpression) { mixin(def("powExpression")); }
682     override void visit(const PragmaDeclaration pragmaDeclaration) { mixin(def("pragmaDeclaration")); }
683     override void visit(const PragmaExpression pragmaExpression) { mixin(def("pragmaExpression")); }
684     override void visit(const PrimaryExpression primaryExpression) { mixin(def("primaryExpression")); }
685     override void visit(const Register register) { mixin(def("register")); }
686     override void visit(const RelExpression relExpression) { mixin(def("relExpression")); }
687     override void visit(const ReturnStatement returnStatement) { mixin(def("returnStatement")); }
688     override void visit(const ScopeGuardStatement scopeGuardStatement) { mixin(def("scopeGuardStatement")); }
689     override void visit(const SharedStaticConstructor sharedStaticConstructor) { mixin(def("sharedStaticConstructor")); }
690     override void visit(const SharedStaticDestructor sharedStaticDestructor) { mixin(def("sharedStaticDestructor")); }
691     override void visit(const ShiftExpression shiftExpression) { mixin(def("shiftExpression")); }
692     override void visit(const SingleImport singleImport) { mixin(def("singleImport")); }
693     override void visit(const SliceExpression sliceExpression) { mixin(def("sliceExpression")); }
694     override void visit(const Statement statement) { 
695         //mixin(def("statement")); 
696         super.visit(statement);
697     }
698     override void visit(const StatementNoCaseNoDefault statementNoCaseNoDefault) { 
699         super.visit(statementNoCaseNoDefault);
700         //mixin(def("statementNoCaseNoDefault")); 
701     }
702     override void visit(const StaticAssertDeclaration staticAssertDeclaration) { mixin(def("staticAssertDeclaration")); }
703     override void visit(const StaticAssertStatement staticAssertStatement) { mixin(def("staticAssertStatement")); }
704     override void visit(const StaticConstructor staticConstructor) { mixin(def("staticConstructor")); }
705     override void visit(const StaticDestructor staticDestructor) { mixin(def("staticDestructor")); }
706     override void visit(const StaticIfCondition staticIfCondition) { mixin(def("staticIfCondition")); }
707     override void visit(const StorageClass storageClass) { mixin(def("storageClass")); }
708     override void visit(const StructBody structBody) { mixin(def("structBody")); }
709     override void visit(const StructDeclaration structDeclaration) { 
710         mixin(deftoken("structDeclaration", "name")); 
711     }
712     override void visit(const StructInitializer structInitializer) { mixin(def("structInitializer")); }
713     override void visit(const StructMemberInitializer structMemberInitializer) { mixin(def("structMemberInitializer")); }
714     override void visit(const StructMemberInitializers structMemberInitializers) { mixin(def("structMemberInitializers")); }
715     override void visit(const SwitchStatement switchStatement) { mixin(def("switchStatement")); }
716     override void visit(const Symbol symbol) { mixin(def("symbol")); }
717     override void visit(const SynchronizedStatement synchronizedStatement) { mixin(def("synchronizedStatement")); }
718     override void visit(const TemplateAliasParameter templateAliasParameter) { mixin(def("templateAliasParameter")); }
719     override void visit(const TemplateArgument templateArgument) { mixin(def("templateArgument")); }
720     override void visit(const TemplateArgumentList templateArgumentList) { mixin(def("templateArgumentList")); }
721     override void visit(const TemplateArguments templateArguments) { mixin(def("templateArguments")); }
722     override void visit(const TemplateDeclaration templateDeclaration) { mixin(def("templateDeclaration")); }
723     override void visit(const TemplateInstance templateInstance) { mixin(def("templateInstance")); }
724     override void visit(const TemplateMixinExpression templateMixinExpression) { mixin(def("templateMixinExpression")); }
725     override void visit(const TemplateParameter templateParameter) { mixin(def("templateParameter")); }
726     override void visit(const TemplateParameterList templateParameterList) { mixin(def("templateParameterList")); }
727     override void visit(const TemplateParameters templateParameters) { mixin(def("templateParameters")); }
728     override void visit(const TemplateSingleArgument templateSingleArgument) { mixin(def("templateSingleArgument")); }
729     override void visit(const TemplateThisParameter templateThisParameter) { mixin(def("templateThisParameter")); }
730     override void visit(const TemplateTupleParameter templateTupleParameter) { mixin(def("templateTupleParameter")); }
731     override void visit(const TemplateTypeParameter templateTypeParameter) { mixin(def("templateTypeParameter")); }
732     override void visit(const TemplateValueParameter templateValueParameter) { mixin(def("templateValueParameter")); }
733     override void visit(const TemplateValueParameterDefault templateValueParameterDefault) { mixin(def("templateValueParameterDefault")); }
734     override void visit(const TernaryExpression ternaryExpression) { mixin(def("ternaryExpression")); }
735     override void visit(const ThrowStatement throwStatement) { mixin(def("throwStatement")); }
736     override void visit(const TraitsExpression traitsExpression) { mixin(def("traitsExpression")); }
737     override void visit(const TryStatement tryStatement) { mixin(def("tryStatement")); }
738     override void visit(const Type type) { mixin(def("type")); }
739     override void visit(const Type2 type2) { mixin(def("type2")); }
740     override void visit(const TypeSpecialization typeSpecialization) { mixin(def("typeSpecialization")); }
741     override void visit(const TypeSuffix typeSuffix) { mixin(def("typeSuffix")); }
742     override void visit(const TypeidExpression typeidExpression) { mixin(def("typeidExpression")); }
743     override void visit(const TypeofExpression typeofExpression) { mixin(def("typeofExpression")); }
744     override void visit(const UnaryExpression unaryExpression) { 
745         super.visit(unaryExpression);
746         //mixin(def("unaryExpression")); 
747     }
748     override void visit(const UnionDeclaration unionDeclaration) { mixin(def("unionDeclaration")); }
749     override void visit(const Unittest unittest_) { mixin(def("unittest_")); }
750     override void visit(const VariableDeclaration variableDeclaration) { 
751         mixin(def("variableDeclaration")); 
752     }
753     override void visit(const Vector vector) { mixin(def("vector")); }
754     override void visit(const VersionCondition versionCondition) { mixin(def("versionCondition")); }
755     override void visit(const VersionSpecification versionSpecification) { mixin(def("versionSpecification")); }
756     override void visit(const WhileStatement whileStatement) { mixin(def("whileStatement")); }
757     override void visit(const WithStatement withStatement) { mixin(def("withStatement")); }
758     override void visit(const XorExpression xorExpression) { mixin(def("xorExpression")); }
759 }