1 /** 2 Copyright: Copyright (c) 2020, Joakim Brännström. All rights reserved. 3 License: MPL-2 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This Source Code Form is subject to the terms of the Mozilla Public License, 7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain 8 one at http://mozilla.org/MPL/2.0/. 9 10 Extensions to the visitor in `cpptooling.analyzer.clang.ast`. 11 12 Intende to move this code to clang_extensions if this approach to extending the 13 clang AST works well. 14 */ 15 module dextool.plugin.mutate.backend.analyze.extensions; 16 17 import clang.Cursor : Cursor; 18 import cpptooling.analyzer.clang.ast : Visitor; 19 20 import my.set; 21 22 static import dextool.clang_extensions; 23 24 static import cpptooling.analyzer.clang.ast; 25 26 /** 27 * the ignoreCursors solution is not particularly principaled. It is an ugly hack that should be moved to the core AST `Visitor` and thus completely h 28 */ 29 class ExtendedVisitor : Visitor { 30 import cpptooling.analyzer.clang.ast; 31 import dextool.clang_extensions; 32 33 alias visit = Visitor.visit; 34 35 // A cursors that has been decorated as one of the extended should be 36 // "ignored" if it is found "again". Which happens for e.g. a 37 // BinaryOperator inside a if-statement. It will first occur as a 38 // IfStmtCond and then a BinaryOperator. 39 Set!size_t ignoreCursors; 40 41 void visit(const(IfStmtInit) value) { 42 visit(cast(const(Statement)) value); 43 } 44 45 void visit(const(IfStmtCond) value) { 46 visit(cast(const(Expression)) value); 47 } 48 49 void visit(const(IfStmtThen) value) { 50 visit(cast(const(Statement)) value); 51 } 52 53 void visit(const(IfStmtElse) value) { 54 visit(cast(const(Statement)) value); 55 } 56 } 57 58 // using dispatch because the wrapped cursor has to be re-visited as its 59 // original `type`. Not just the colored `IfStmt` node. 60 61 final class IfStmtInit : cpptooling.analyzer.clang.ast.Statement { 62 this(Cursor cursor) @safe { 63 super(cursor); 64 } 65 66 void accept(ExtendedVisitor v) @safe const { 67 static import cpptooling.analyzer.clang.ast; 68 69 cpptooling.analyzer.clang.ast.dispatch(cursor, v); 70 } 71 } 72 73 final class IfStmtCond : cpptooling.analyzer.clang.ast.Expression { 74 this(Cursor cursor) @safe { 75 super(cursor); 76 } 77 78 void accept(ExtendedVisitor v) @safe const { 79 static import cpptooling.analyzer.clang.ast; 80 81 cpptooling.analyzer.clang.ast.dispatch(cursor, v); 82 } 83 } 84 85 final class IfStmtThen : cpptooling.analyzer.clang.ast.Statement { 86 this(Cursor cursor) @safe { 87 super(cursor); 88 } 89 90 void accept(ExtendedVisitor v) @safe const { 91 static import cpptooling.analyzer.clang.ast; 92 93 cpptooling.analyzer.clang.ast.dispatch(cursor, v); 94 } 95 } 96 97 final class IfStmtElse : cpptooling.analyzer.clang.ast.Statement { 98 this(Cursor cursor) @safe { 99 super(cursor); 100 } 101 102 void accept(ExtendedVisitor v) @safe const { 103 static import cpptooling.analyzer.clang.ast; 104 105 cpptooling.analyzer.clang.ast.dispatch(cursor, v); 106 } 107 } 108 109 void accept(T)(const(cpptooling.analyzer.clang.ast.IfStmt) n, T v) 110 if (is(T : ExtendedVisitor)) { 111 import dextool.clang_extensions; 112 113 auto stmt = getIfStmt(n.cursor); 114 accept(stmt, v); 115 } 116 117 void accept(T)(ref dextool.clang_extensions.IfStmt n, T v) 118 if (is(T : ExtendedVisitor)) { 119 import std.traits : hasMember; 120 121 static if (hasMember!(T, "incr")) 122 v.incr; 123 124 if (n.init_.isValid) { 125 auto sub = new IfStmtInit(n.init_); 126 static if (__traits(hasMember, T, "ignoreCursors")) { 127 v.ignoreCursors.add(n.init_.toHash); 128 } 129 v.visit(sub); 130 } 131 if (n.cond.isValid) { 132 auto sub = new IfStmtCond(n.cond); 133 static if (__traits(hasMember, T, "ignoreCursors")) { 134 v.ignoreCursors.add(n.cond.toHash); 135 } 136 v.visit(sub); 137 } 138 if (n.then.isValid) { 139 auto sub = new IfStmtThen(n.then); 140 v.visit(sub); 141 } 142 if (n.else_.isValid) { 143 auto sub = new IfStmtElse(n.else_); 144 v.visit(sub); 145 } 146 147 static if (hasMember!(T, "decr")) 148 v.decr; 149 }