Skip to content

Commit e5970d6

Browse files
committed
Minor fixes for map key/value assignments.
1 parent 3bddc3a commit e5970d6

File tree

5 files changed

+94
-19
lines changed

5 files changed

+94
-19
lines changed

docker/android/android/soong.py

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,9 @@ def pairs(self, prod):
196196
def pairs(self, prod):
197197
return [prod.pair]
198198

199-
@_('ident COLON expr')
199+
@_('ident COLON expr', 'ident EQUALS expr')
200200
def pair(self, prod):
201-
return (prod.ident, prod.expr)
201+
return (prod.ident, MapValue(prod[1], prod.expr))
202202

203203
@_('ident', 'binary_operator', 'map', 'list', 'string', 'integer', 'bool')
204204
def expr(self, prod):
@@ -272,6 +272,9 @@ def is_map(self):
272272
def is_list(self):
273273
return False
274274

275+
def is_map_value(self):
276+
return False
277+
275278
def is_ident(self):
276279
return False
277280

@@ -390,6 +393,12 @@ def to_str(self, pretty=True, indent=4, depth=0):
390393
def is_binary_operator(self):
391394
return True
392395

396+
def str_op(self, cmp):
397+
return (
398+
(self.lhs.is_string() and self.lhs.str_op(cmp))
399+
or (self.rhs.is_string() and self.rhs.str_op(cmp))
400+
)
401+
393402
def __eq__(self, other):
394403
return (self.lhs, self.op, self.rhs) == (other.lhs, other.op, other.rhs)
395404

@@ -434,7 +443,7 @@ def __str__(self):
434443
def to_str(self, pretty=True, indent=4, depth=0):
435444
fmt = lambda x: x.to_str(pretty, indent, depth + 1)
436445
result = '{'
437-
pairs = [f'{fmt(k)}: {fmt(v)}' for k, v in self.items()]
446+
pairs = [f'{fmt(k)}{fmt(v)}' for k, v in self.items()]
438447
if len(self) == 0:
439448
result += '}'
440449
elif pretty:
@@ -454,13 +463,13 @@ def is_test(self):
454463
name = self.get('name')
455464
if name is None:
456465
return False
457-
return 'test' in name.lower()
466+
return 'test' in name.value.lower()
458467

459468
def is_benchmark(self):
460469
name = self.get('name')
461470
if name is None:
462471
return False
463-
return 'benchmark' in name.lower()
472+
return 'benchmark' in name.value.lower()
464473

465474
def is_dev(self):
466475
return self.is_test() or self.is_benchmark()
@@ -475,8 +484,8 @@ def recurse(self, max_depth=-1, depth=0):
475484
if depth != max_depth:
476485
for key, value in self.items():
477486
yield (key, value, depth + 1, self)
478-
if value.is_map():
479-
yield from value.recurse(max_depth, depth + 1)
487+
if value.value.is_map():
488+
yield from value.value.recurse(max_depth, depth + 1)
480489

481490

482491
class List(list, Node):
@@ -507,6 +516,41 @@ def filter(self, op):
507516
self[:] = [i for i in self if op(i)]
508517

509518

519+
class MapValue(Node):
520+
def __init__(self, delimiter, value):
521+
# map key/value separators can be `:` or `=`.
522+
assert delimiter in (':', '=')
523+
self.delimiter = delimiter
524+
self.value = value
525+
526+
def __repr__(self):
527+
return f'MapValue({str(self)})'
528+
529+
def __str__(self):
530+
return self.to_str(False)
531+
532+
def __eq__(self, other):
533+
# delimiter doesn't matter for equality comparison
534+
if isinstance(other, MapValue):
535+
return self.value == other.value
536+
return self.value == other
537+
538+
def __len__(self):
539+
return len(self.value)
540+
541+
def to_str(self, pretty=True, indent=4, depth=0):
542+
value = self.value.to_str(pretty, indent, depth)
543+
if self.delimiter == '=':
544+
return f' = {value}'
545+
return f': {value}'
546+
547+
def is_map_value(self):
548+
return True
549+
550+
def filter(self, op):
551+
self.value.filter(op)
552+
553+
510554
class Ident(str, Node):
511555
def __repr__(self):
512556
return f'Ident({str(self)})'
@@ -528,6 +572,9 @@ def __repr__(self):
528572
def to_str(self, *_, **__):
529573
return f'{super().__str__()}'
530574

575+
def str_op(self, cmp):
576+
return cmp(self)
577+
531578
def __str__(self):
532579
# `"target"` should be shown as `'target'`, not `'"target"'`
533580
return super().__str__()[1:-1]

docker/android/scripts/build-system.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,11 @@ def remove_soong_tests(path, args, *_):
5050
# or those with `{name: "test"}`, etc.
5151
ast.filter(lambda x: not (x.is_scope() and x.is_dev()))
5252
# need to remove test and benchmark subdirs
53+
test_names = ('test', 'benchmark')
5354
subdirs = [i for i in ast if i.name == 'subdirs']
54-
for subdir in subdirs:
55-
assert type(subdir.expr) is android.soong.List
56-
subdir.expr.filter(lambda x: not any(i in x.lower() for i in ('test', 'benchmark')))
55+
for sub in subdirs:
56+
assert type(sub.expr) is android.soong.List
57+
sub.expr.filter(lambda x: x.str_op(lambda y: not any(i in y.lower() for i in test_names)))
5758
# remove gtest dependencies from regular targets.
5859
for node in ast:
5960
map = None
@@ -65,7 +66,7 @@ def remove_soong_tests(path, args, *_):
6566
map = node.expr
6667
for key, value, *_ in map.recurse():
6768
if value.is_list():
68-
value.filter(lambda x: 'libgtest' not in x.lower())
69+
value.filter(lambda x: x.str_op(lambda y: 'libgtest' not in y.lower()))
6970

7071
with open(path, 'w') as file:
7172
ast.dump(file)

docker/android/tests/Android.bp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,8 @@ cc_test_host {
6464
"-l" + "z",
6565
],
6666
shared_libs: [],
67+
cflags = [
68+
"-Wall",
69+
"-fstrict-aliasing",
70+
],
6771
}

docker/android/tests/test_soong.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ def test_addition():
133133
assert ast[26].expr[2].rhs == 'test'
134134
assert ast[26].expr[2].rhs.is_ident()
135135

136+
# test a few binops, just in case
137+
binop = ast[26].expr[1]
138+
assert binop.str_op(lambda x: 'test' in x.lower())
139+
assert binop.lhs.str_op(lambda x: 'test' in x.lower())
140+
136141

137142
def test_empty():
138143
path = os.path.join(TEST_DIR, 'Empty.bp')
@@ -143,19 +148,20 @@ def test_empty():
143148
def test_ast():
144149
array = soong.List([soong.String('"value1"'), soong.String('"value2"')])
145150
assignment = soong.Assignment(soong.Ident('name'), array)
146-
map = soong.Map({soong.Ident('key'): soong.String('"value"')})
151+
value = soong.MapValue('=', soong.String('"value"'))
152+
map = soong.Map({soong.Ident('key'): value})
147153
scope = soong.Scope(soong.Ident('name'), map)
148154
ast = soong.Ast([assignment, scope])
149155
assert repr(ast) == '''Ast(name = ["value1", "value2"]
150-
name {key: "value"})'''
156+
name {key = "value"})'''
151157
assert str(ast) == '''name = ["value1", "value2"]
152-
name {key: "value"}'''
158+
name {key = "value"}'''
153159
assert ast.to_str() == '''name = [
154160
"value1",
155161
"value2",
156162
]
157163
name {
158-
key: "value",
164+
key = "value",
159165
}'''
160166

161167

@@ -196,7 +202,8 @@ def test_binary_operator():
196202

197203

198204
def test_scope():
199-
map = soong.Map({soong.Ident('key'): soong.String('"value"')})
205+
value = soong.MapValue(':', soong.String('"value"'))
206+
map = soong.Map({soong.Ident('key'): value})
200207
scope = soong.Scope(soong.Ident('name'), map)
201208
assert repr(scope) == 'Scope(name {key: "value"})'
202209
assert str(scope) == 'name {key: "value"}'
@@ -210,7 +217,8 @@ def test_scope():
210217

211218

212219
def test_map():
213-
map = soong.Map({soong.Ident('key'): soong.String('"value"')})
220+
value = soong.MapValue(':', soong.String('"value"'))
221+
map = soong.Map({soong.Ident('key'): value})
214222
assert repr(map) == 'Map({key: "value"})'
215223
assert str(map) == '{key: "value"}'
216224
assert map.to_str(pretty=False) == '{key: "value"}'
@@ -266,6 +274,18 @@ def test_list():
266274
assert sequence.to_str() == '[]'
267275

268276

277+
def test_map_value():
278+
value = soong.MapValue(':', soong.String('"value"'))
279+
assert repr(value) == 'MapValue(: "value")'
280+
assert str(value) == ': "value"'
281+
assert value.to_str() == ': "value"'
282+
283+
value = soong.MapValue('=', soong.String('"value"'))
284+
assert repr(value) == 'MapValue( = "value")'
285+
assert str(value) == ' = "value"'
286+
assert value.to_str() == ' = "value"'
287+
288+
269289
def test_ident():
270290
ident = soong.Ident('name')
271291
assert repr(ident) == 'Ident(name)'

docker/android/tox.ini

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ passenv =
1616

1717
[flake8]
1818
max-line-length = 100
19-
# we use lambdas for short, one-line conditions and formatters
20-
ignore = E731
19+
ignore =
20+
# we use lambdas for short, one-line conditions and formatters
21+
E731
22+
# opt-in to new behavior with operators after line breaks
23+
W503
2124
per-file-ignores =
2225
# the sly grammar uses variables before they are defined via a metaclass
2326
# likewise, it uses redefinitions to extend parsers via SLR grammar

0 commit comments

Comments
 (0)