in build-support/iwyu/fix_includes.py [0:0]
def FixFileLines(iwyu_record, file_lines, flags):
"""Applies one block of lines from the iwyu output script.
Called once we have read all the lines from the iwyu output script
pertaining to a single source file, and parsed them into an
iwyu_record. At that point we edit the source file, remove the old
#includes and forward-declares, insert the #includes and
forward-declares, and reorder the lot, all as specified by the iwyu
output script. The resulting source code lines are returned.
Arguments:
iwyu_record: an IWYUOutputRecord object holding the parsed output
of the include-what-you-use script (run at verbose level 1 or
higher) pertaining to a single source file.
file_lines: a list of LineInfo objects holding the parsed output of
the file in iwyu_record.filename
flags: commandline flags, as parsed by optparse. We use
flags.safe_headers to turn off deleting lines, and use the
other flags indirectly (via calls to other routines).
Returns:
An array of 'fixed' source code lines, after modifications as
specified by iwyu.
"""
# First delete the includes and forward-declares that we should delete.
# This is easy since iwyu tells us the line numbers.
if not (flags.safe_headers and _MayBeHeaderFile(iwyu_record.filename)):
_DeleteLinesAccordingToIwyu(iwyu_record, file_lines)
# With these deletions, we may be able to merge together some
# reorder-spans. Recalculate them to see.
_CalculateReorderSpans(file_lines)
# For every move-span in our file -- that's every #include and
# forward-declare we saw -- 'decorate' the move-range to allow us
# to sort them.
move_spans = set([fl.move_span for fl in file_lines if fl.move_span])
decorated_move_spans = []
for (start_line, end_line) in move_spans:
decorated_span = _DecoratedMoveSpanLines(iwyu_record, file_lines,
file_lines[start_line:end_line],
flags)
if decorated_span:
decorated_move_spans.append(decorated_span)
# Now let's add in a decorated move-span for all the new #includes
# and forward-declares.
symbol_names_seen = set()
for line in iwyu_record.includes_and_forward_declares_to_add:
line_info = LineInfo(line)
m = _INCLUDE_RE.match(line)
if m:
line_info.type = _INCLUDE_RE
line_info.key = m.group(1)
else:
# Avoid duplicates that can arise if different template args
# were suggested by different iwyu analyses for this file.
symbol_name = _GetSymbolNameFromForwardDeclareLine(line)
if symbol_name in symbol_names_seen:
continue
symbol_names_seen.add(symbol_name)
line_info.type = _FORWARD_DECLARE_RE
decorated_span = _DecoratedMoveSpanLines(iwyu_record, file_lines,
[line_info], flags)
assert decorated_span, 'line to add is not an #include or fwd-decl?'
decorated_move_spans.append(decorated_span)
# Add a sentinel decorated move-span, to make life easy, and sort.
decorated_move_spans.append(((len(file_lines), len(file_lines)),
_EOF_KIND, '', []))
decorated_move_spans.sort()
# Now go through all the lines of the input file and construct the
# output file. Before we get to the next reorder-span, we just
# copy lines over verbatim (ignoring deleted lines, of course).
# In a reorder-span, we just print the sorted content, introducing
# blank lines when appropriate.
output_lines = []
line_number = 0
while line_number < len(file_lines):
current_reorder_span = decorated_move_spans[0][0]
# Just copy over all the lines until the next reorder span.
while line_number < current_reorder_span[0]:
if not file_lines[line_number].deleted:
output_lines.append(file_lines[line_number].line)
line_number += 1
# Now fill in the contents of the reorder-span from decorated_move_spans
new_lines = []
while (decorated_move_spans and
decorated_move_spans[0][0] == current_reorder_span):
new_lines.extend(decorated_move_spans[0][3]) # the full content
if (len(decorated_move_spans) > 1 and
_ShouldInsertBlankLine(decorated_move_spans[0],
decorated_move_spans[1], file_lines, flags)):
new_lines.append('')
decorated_move_spans = decorated_move_spans[1:] # pop
if not flags.keep_iwyu_namespace_format:
# Now do the munging to convert namespace lines from the iwyu input
# format to the 'official style' format:
# 'namespace foo { class Bar; }\n' -> 'namespace foo {\nclass Bar;\n}'
# along with collecting multiple classes in the same namespace.
new_lines = _NormalizeNamespaceForwardDeclareLines(new_lines)
output_lines.extend(new_lines)
line_number = current_reorder_span[1] # go to end of span
return [line for line in output_lines if line is not None]