1 | import os |
2 | from clang.cindex import Config |
3 | if 'CLANG_LIBRARY_PATH' in os.environ: |
4 | Config.set_library_path(os.environ['CLANG_LIBRARY_PATH']) |
5 | |
6 | from clang.cindex import Cursor |
7 | from clang.cindex import File |
8 | from clang.cindex import SourceLocation |
9 | from clang.cindex import SourceRange |
10 | from .util import get_cursor |
11 | from .util import get_tu |
12 | |
13 | import unittest |
14 | |
15 | |
16 | baseInput="int one;\nint two;\n" |
17 | |
18 | |
19 | class TestLocation(unittest.TestCase): |
20 | def assert_location(self, loc, line, column, offset): |
21 | self.assertEqual(loc.line, line) |
22 | self.assertEqual(loc.column, column) |
23 | self.assertEqual(loc.offset, offset) |
24 | |
25 | def test_location(self): |
26 | tu = get_tu(baseInput) |
27 | one = get_cursor(tu, 'one') |
28 | two = get_cursor(tu, 'two') |
29 | |
30 | self.assertIsNotNone(one) |
31 | self.assertIsNotNone(two) |
32 | |
33 | self.assert_location(one.location,line=1,column=5,offset=4) |
34 | self.assert_location(two.location,line=2,column=5,offset=13) |
35 | |
36 | # adding a linebreak at top should keep columns same |
37 | tu = get_tu('\n' + baseInput) |
38 | one = get_cursor(tu, 'one') |
39 | two = get_cursor(tu, 'two') |
40 | |
41 | self.assertIsNotNone(one) |
42 | self.assertIsNotNone(two) |
43 | |
44 | self.assert_location(one.location,line=2,column=5,offset=5) |
45 | self.assert_location(two.location,line=3,column=5,offset=14) |
46 | |
47 | # adding a space should affect column on first line only |
48 | tu = get_tu(' ' + baseInput) |
49 | one = get_cursor(tu, 'one') |
50 | two = get_cursor(tu, 'two') |
51 | |
52 | self.assert_location(one.location,line=1,column=6,offset=5) |
53 | self.assert_location(two.location,line=2,column=5,offset=14) |
54 | |
55 | # define the expected location ourselves and see if it matches |
56 | # the returned location |
57 | tu = get_tu(baseInput) |
58 | |
59 | file = File.from_name(tu, 't.c') |
60 | location = SourceLocation.from_position(tu, file, 1, 5) |
61 | cursor = Cursor.from_location(tu, location) |
62 | |
63 | one = get_cursor(tu, 'one') |
64 | self.assertIsNotNone(one) |
65 | self.assertEqual(one, cursor) |
66 | |
67 | # Ensure locations referring to the same entity are equivalent. |
68 | location2 = SourceLocation.from_position(tu, file, 1, 5) |
69 | self.assertEqual(location, location2) |
70 | location3 = SourceLocation.from_position(tu, file, 1, 4) |
71 | self.assertNotEqual(location2, location3) |
72 | |
73 | offset_location = SourceLocation.from_offset(tu, file, 5) |
74 | cursor = Cursor.from_location(tu, offset_location) |
75 | verified = False |
76 | for n in [n for n in tu.cursor.get_children() if n.spelling == 'one']: |
77 | self.assertEqual(n, cursor) |
78 | verified = True |
79 | |
80 | self.assertTrue(verified) |
81 | |
82 | def test_extent(self): |
83 | tu = get_tu(baseInput) |
84 | one = get_cursor(tu, 'one') |
85 | two = get_cursor(tu, 'two') |
86 | |
87 | self.assert_location(one.extent.start,line=1,column=1,offset=0) |
88 | self.assert_location(one.extent.end,line=1,column=8,offset=7) |
89 | self.assertEqual(baseInput[one.extent.start.offset:one.extent.end.offset], "int one") |
90 | |
91 | self.assert_location(two.extent.start,line=2,column=1,offset=9) |
92 | self.assert_location(two.extent.end,line=2,column=8,offset=16) |
93 | self.assertEqual(baseInput[two.extent.start.offset:two.extent.end.offset], "int two") |
94 | |
95 | file = File.from_name(tu, 't.c') |
96 | location1 = SourceLocation.from_position(tu, file, 1, 1) |
97 | location2 = SourceLocation.from_position(tu, file, 1, 8) |
98 | |
99 | range1 = SourceRange.from_locations(location1, location2) |
100 | range2 = SourceRange.from_locations(location1, location2) |
101 | self.assertEqual(range1, range2) |
102 | |
103 | location3 = SourceLocation.from_position(tu, file, 1, 6) |
104 | range3 = SourceRange.from_locations(location1, location3) |
105 | self.assertNotEqual(range1, range3) |
106 | |