-
Notifications
You must be signed in to change notification settings - Fork 10.4k
/
Copy pathline-directive
executable file
·115 lines (98 loc) · 3.33 KB
/
line-directive
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python
# line-directive.py - Transform line numbers in error messages -*- python -*-
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See http://swift.org/LICENSE.txt for license information
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
#
# ----------------------------------------------------------------------------
#
# Converts line numbers in error messages according to "line directive"
# comments.
#
# ----------------------------------------------------------------------------
import bisect
import re
import subprocess
import sys
line_pattern = re.compile(
r'^// ###sourceLocation\(file:\s*"([^"]+)",\s*line:\s*([0-9]+)\s*\)')
def _make_line_map(filename, stream=None):
"""
>>> from StringIO import StringIO
>>> _make_line_map('box',
... StringIO('''// ###sourceLocation(file: "foo.bar", line: 3)
... line 2
... line 3
... line 4
... // ###sourceLocation(file: "baz.txt", line: 20)
... line 6
... line 7
... '''))
[(0, 'box', 1), (1, 'foo.bar', 3), (5, 'baz.txt', 20)]
"""
result = [(0, filename, 1)]
input = stream or open(filename)
for i, l in enumerate(input.readlines()):
m = line_pattern.match(l)
if m:
result.append((i + 1, m.group(1), int(m.group(2))))
return result
_line_maps = {}
def fline_map(filename):
map = _line_maps.get(filename)
if map is None:
map = _make_line_map(filename)
_line_maps[filename] = map
return map
def map_line(filename, line_num):
assert(line_num > 0)
map = fline_map(filename)
index = bisect.bisect_left(map, (line_num, '', 0))
base = map[index - 1]
return base[1], base[2] + (line_num - base[0] - 1)
def run():
if len(sys.argv) <= 1:
import doctest
doctest.testmod()
else:
dashes = sys.argv.index('--')
sources = sys.argv[1:dashes]
command = subprocess.Popen(
sys.argv[dashes + 1:],
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
universal_newlines=True
)
error_pattern = re.compile(
'^(' + '|'.join(re.escape(s) for s in sources) +
'):([0-9]+):([0-9]+):(.*)')
assertion_pattern = re.compile(
'^(.*)(: file| at|#[0-9]+:) (' +
'|'.join(re.escape(s) for s in sources) +
')(, line |:)([0-9]+)(.*)')
while True:
line = command.stdout.readline()
if line == '':
break
l = line.rstrip('\n')
m = error_pattern.match(l)
if m:
file, line_num = map_line(m.group(1), int(m.group(2)))
line = '%s:%s:%s:%s\n' % (
file, line_num, int(m.group(3)), m.group(4))
else:
m = assertion_pattern.match(l)
if m:
file, line_num = map_line(m.group(3), int(m.group(5)))
line = '%s%s %s%s%s%s\n' % (
m.group(1), m.group(2), file, m.group(4), line_num,
m.group(6))
sys.stdout.write(line)
sys.exit(command.wait())
if __name__ == '__main__':
run()