1 /** 2 Copyright: Copyright (c) 2015-2016, Joakim Brännström. All rights reserved. 3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 */ 6 module clang.SourceRange; 7 8 import std.conv; 9 import std.string; 10 import std.experimental.logger; 11 12 import clang.c.Index; 13 14 import clang.SourceLocation; 15 16 /// 17 struct SourceRange { 18 import std.format : FormatSpec; 19 import clang.Util; 20 21 mixin CX; 22 23 /// Retrieve a NULL (invalid) source range. 24 static SourceRange empty() @trusted { 25 auto r = clang_getNullRange(); 26 return SourceRange(r); 27 } 28 29 /// Retrieve a source location representing the first character within a source range. 30 @property SourceLocation start() const @trusted { 31 auto r = clang_getRangeStart(cx); 32 return SourceLocation(r); 33 } 34 35 /// Retrieve a source location representing the last character within a source range. 36 @property SourceLocation end() const @trusted { 37 auto r = clang_getRangeEnd(cx); 38 return SourceLocation(r); 39 } 40 41 @property string path() const @trusted { 42 return start.path; 43 } 44 45 /// 46 bool isNull() const @trusted { 47 return clang_Range_isNull(cx) != 0; 48 } 49 50 /// 51 equals_t opEquals(const ref SourceRange range2) const { 52 return clang_equalRanges(cast(CXSourceRange) cx, cast(CXSourceRange) range2) != 0; 53 } 54 55 string toString() @safe const { 56 import std.exception : assumeUnique; 57 import std.format : FormatSpec; 58 59 char[] buf; 60 buf.reserve(100); 61 auto fmt = FormatSpec!char("%s"); 62 toString((const(char)[] s) { buf ~= s; }, fmt); 63 auto trustedUnique(T)(T t) @trusted { 64 return assumeUnique(t); 65 } 66 67 return trustedUnique(buf); 68 } 69 70 void toString(Writer, Char)(scope Writer w, FormatSpec!Char fmt) const { 71 import std.format : formattedWrite; 72 73 auto start = this.start.presumed; 74 auto end = this.end.presumed; 75 76 if (isValid) { 77 formattedWrite(w, "%s [start='%s:%s' end='%s:%s']", start.file, 78 start.line, start.column, end.line, end.column); 79 } else { 80 formattedWrite(w, "%s(%s)", typeid(this), cx); 81 } 82 } 83 } 84 85 /** Check if two source ranges intersect 86 */ 87 bool intersects(in SourceRange a, in SourceRange b) { 88 return a.path == b.path && a.end.offset >= b.start.offset && b.end.offset >= a.start.offset; 89 } 90 91 /// Retrieve a source range given the beginning and ending source locations. 92 SourceRange range(ref SourceLocation begin, SourceLocation end) { 93 auto r = clang_getRange(begin.cx, end.cx); 94 return SourceRange(r); 95 } 96 97 unittest { 98 // Test of null range. 99 auto r = SourceRange.empty(); 100 101 assert(r.isNull == true); 102 }