from datetime import datetime
from textwrap import indent, dedent
from ast import *
from util import *
@linewise
def do_impl(s, field_name):
yield 'impl GetSpan for %s {' % s.name
yield ' fn get_span(&self) -> Span {'
if 'extend_span' not in s.attrs:
yield ' self.%s' % field_name
else:
attr_field = s.attrs['extend_span'] or 'attrs'
yield ' extend_span_attrs(self.%s, &self.%s)' % (field_name, attr_field)
yield ' }'
yield '}'
def find_span_field(s):
if 'no_span' in s.attrs:
return None
marked_fields = []
for f in s.fields:
if 'span' in f.attrs:
marked_fields.append(f.name)
if len(marked_fields) == 1:
return marked_fields[0]
elif len(marked_fields) > 1:
raise ValueError('struct %s has %d fields marked #[span] (expected 0 or 1)' %
(s.name, len(marked_fields)))
for f in s.fields:
if f.name == 'span':
return f.name
return None
@linewise
def generate(decls):
yield '// AUTOMATICALLY GENERATED - DO NOT EDIT'
yield '// Produced %s by process_ast.py' % (datetime.now(),)
yield ''
for d in decls:
if not isinstance(d, Struct):
continue
field_name = find_span_field(d)
if field_name is not None:
yield do_impl(d, field_name)
def has_get_span_impl(d):
return isinstance(d, Struct) and find_span_field(d) is not None