On 7/1/12 11:03 PM, Manuel Klimek wrote:
High-level remark:
The idea of having multiple different parameters of which only one
must ever be set seems strange to me. Why not instead have multiple
methods with different names? I'd also prefer having 1 parameter and
finding out what methods it provides.
Changed API to single argument with type detection. I don't like having
multiple methods with different names because that feels too "Java-y"
for me. I prefer a single method that just works and accepts whatever is
thrown at it.
On Sat, Jun 30, 2012 at 4:15 AM, Gregory Szorc
<[email protected] <mailto:[email protected]>> wrote:
Updated patch.
On Fri, Jun 29, 2012 at 8:47 AM, Gregory Szorc
<[email protected] <mailto:[email protected]>> wrote:
> Having thought about this in my sleep, I may want to rescind this
> review request and refactor things a little.
>
> 1) I may change "range" and "source_range" names to "extent" since
> that is what is used elsewhere.
> 2) I may combine the bounds to obtain ranges/extents from two
> arguments to 2-tuples.
> 3) I may remove the "_source" from get_source_location and
> get_source_extent. I don't think that's any less clear.
>
> This will of course invalidate the token API patch that followed,
> albeit trivially.
>
> On Fri, Jun 29, 2012 at 12:13 AM, Gregory Szorc
<[email protected] <mailto:[email protected]>> wrote:
>> These are just convenience APIs to make obtaining File,
>> SourceLocation, and SourceRange instances easier.
>>
>> Old way:
>>
>> f = File.from_name(tu, 'foo.c')
>> location = SourceLocation.from_offset(tu, f, 10)
>>
>> New way:
>>
>> location = tu.get_source_location('foo.c', offset=10)
>From 9caaae34db916a7ef8a4ea6017ec25dc9a1a4c84 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <[email protected]>
Date: Thu, 28 Jun 2012 23:48:12 -0700
Subject: [PATCH 2/3] [clang.py] Add
TranslationUnit.get_{file,source_location,source_range}
---
bindings/python/clang/cindex.py | 61 ++++++++++++++++++++
.../python/tests/cindex/test_translation_unit.py | 66 ++++++++++++++++++++++
2 files changed, 127 insertions(+)
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index b21eedb..2d0c677 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -1890,16 +1890,77 @@ class TranslationUnit(ClangObject):
# Automatically adapt CIndex/ctype pointers to python objects
includes = []
lib.clang_getInclusions(self,
callbacks['translation_unit_includes'](visitor), includes)
return iter(includes)
+ def get_file(self, filename):
+ """Obtain a File from this translation unit."""
+
+ return File.from_name(self, filename)
+
+ def get_location(self, filename, position):
+ """Obtain a SourceLocation for a file in this translation unit.
+
+ The position can be specified by passing:
+
+ - Integer file offset. Initial file offset is 0.
+ - 2-tuple of (line number, column number). Initial file position is
+ (0, 0)
+ """
+ f = self.get_file(filename)
+
+ if isinstance(position, int):
+ return SourceLocation.from_offset(self, f, position)
+
+ return SourceLocation.from_position(self, f, position[0], position[1])
+
+ def get_extent(self, filename, locations):
+ """Obtain a SourceRange from this translation unit.
+
+ The bounds of the SourceRange must ultimately be defined by a start and
+ end SourceLocation. For the locations argument, you can pass:
+
+ - 2 SourceLocation instances in a 2-tuple or list.
+ - 2 int file offsets via a 2-tuple or list.
+ - 2 2-tuple or lists of (line, column) pairs in a 2-tuple or list.
+
+ e.g.
+
+ get_extent('foo.c', (5, 10))
+ get_extent('foo.c', ((1, 1), (1, 15)))
+ """
+ f = self.get_file(filename)
+
+ if len(locations) < 2:
+ raise Exception('Must pass object with at least 2 elements')
+
+ start_location, end_location = locations
+
+ if hasattr(start_location, '__len__'):
+ start_location = SourceLocation.from_position(self, f,
+ start_location[0], start_location[1])
+ elif isinstance(start_location, int):
+ start_location = SourceLocation.from_offset(self, f,
+ start_location)
+
+ if hasattr(end_location, '__len__'):
+ end_location = SourceLocation.from_position(self, f,
+ end_location[0], end_location[1])
+ elif isinstance(end_location, int):
+ end_location = SourceLocation.from_offset(self, f, end_location)
+
+ assert isinstance(start_location, SourceLocation)
+ assert isinstance(end_location, SourceLocation)
+
+ return SourceRange.from_locations(start_location, end_location)
+
@property
def diagnostics(self):
"""
Return an iterable (and indexable) object containing the diagnostics.
"""
class DiagIterator:
def __init__(self, tu):
self.tu = tu
diff --git a/bindings/python/tests/cindex/test_translation_unit.py
b/bindings/python/tests/cindex/test_translation_unit.py
index 982a608..9de12ad 100644
--- a/bindings/python/tests/cindex/test_translation_unit.py
+++ b/bindings/python/tests/cindex/test_translation_unit.py
@@ -1,11 +1,14 @@
from clang.cindex import CursorKind
from clang.cindex import Cursor
+from clang.cindex import File
from clang.cindex import Index
+from clang.cindex import SourceLocation
+from clang.cindex import SourceRange
from clang.cindex import TranslationUnitSaveError
from clang.cindex import TranslationUnit
from .util import get_cursor
from .util import get_tu
import os
kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS')
@@ -146,8 +149,71 @@ def test_load():
os.unlink(path)
def test_index_parse():
path = os.path.join(kInputsDir, 'hello.cpp')
index = Index.create()
tu = index.parse(path)
assert isinstance(tu, TranslationUnit)
+
+def test_get_file():
+ """Ensure tu.get_file() works appropriately."""
+
+ tu = get_tu('int foo();')
+
+ f = tu.get_file('t.c')
+ assert isinstance(f, File)
+ assert f.name == 't.c'
+
+ try:
+ f = tu.get_file('foobar.cpp')
+ except:
+ pass
+ else:
+ assert False
+
+def test_get_source_location():
+ """Ensure tu.get_source_location() works."""
+
+ tu = get_tu('int foo();')
+
+ location = tu.get_location('t.c', 2)
+ assert isinstance(location, SourceLocation)
+ assert location.offset == 2
+ assert location.file.name == 't.c'
+
+ location = tu.get_location('t.c', (1, 3))
+ assert isinstance(location, SourceLocation)
+ assert location.line == 1
+ assert location.column == 3
+ assert location.file.name == 't.c'
+
+def test_get_source_range():
+ """Ensure tu.get_source_range() works."""
+
+ tu = get_tu('int foo();')
+
+ r = tu.get_extent('t.c', (1,4))
+ assert isinstance(r, SourceRange)
+ assert r.start.offset == 1
+ assert r.end.offset == 4
+ assert r.start.file.name == 't.c'
+ assert r.end.file.name == 't.c'
+
+ r = tu.get_extent('t.c', ((1,2), (1,3)))
+ assert isinstance(r, SourceRange)
+ assert r.start.line == 1
+ assert r.start.column == 2
+ assert r.end.line == 1
+ assert r.end.column == 3
+ assert r.start.file.name == 't.c'
+ assert r.end.file.name == 't.c'
+
+ start = tu.get_location('t.c', 0)
+ end = tu.get_location('t.c', 5)
+
+ r = tu.get_extent('t.c', (start, end))
+ assert isinstance(r, SourceRange)
+ assert r.start.offset == 0
+ assert r.end.offset == 5
+ assert r.start.file.name == 't.c'
+ assert r.end.file.name == 't.c'
--
1.7.11.1
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits