summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Bytheway <jbytheway@gmail.com>2019-01-16 22:57:50 +0000
committerKim Gräsman <kim.grasman@gmail.com>2019-01-30 20:50:20 +0100
commit6e4330dfcf36c3c2b9a7f2dfa02df6081bd4f868 (patch)
tree0761965dee615e4924a00029c9996fe71b2dfe9a
parent4c7fa216ac12d8d81f8be9fb79710c128e8b3c25 (diff)
Better fix_includes handling of template lines
When multiple forward declarations were present of the form: template<typename T> class Foo; fix_includes.py would consider the multiple 'template<typename T>' lines to be duplicates and delete all but one. Fix that, and add a test for it.
-rwxr-xr-xfix_includes.py22
-rwxr-xr-xfix_includes_test.py66
2 files changed, 77 insertions, 11 deletions
diff --git a/fix_includes.py b/fix_includes.py
index cf9e9e5..c696e3f 100755
--- a/fix_includes.py
+++ b/fix_includes.py
@@ -1124,6 +1124,8 @@ def _DeleteDuplicateLines(file_lines, line_ranges):
particular, it should not cover lines that may have C literal
strings in them.
+ We only delete whole move_spans, not lines within them.
+
Arguments:
file_lines: an array of LineInfo objects.
line_ranges: a list of [start_line, end_line) pairs.
@@ -1131,13 +1133,21 @@ def _DeleteDuplicateLines(file_lines, line_ranges):
seen_lines = set()
for line_range in line_ranges:
for line_number in range(*line_range):
- if file_lines[line_number].type in (_BLANK_LINE_RE, _COMMENT_LINE_RE):
+ line_info = file_lines[line_number]
+ if line_info.type in (_BLANK_LINE_RE, _COMMENT_LINE_RE):
+ continue
+ if line_number != line_info.move_span[0]:
continue
- uncommented_line = _COMMENT_RE.sub('', file_lines[line_number].line)
- if uncommented_line in seen_lines:
- file_lines[line_number].deleted = True
- elif not file_lines[line_number].deleted:
- seen_lines.add(uncommented_line)
+ span_line_numbers = range(line_info.move_span[0], line_info.move_span[1])
+ line_infos_in_span = [file_lines[i] for i in span_line_numbers]
+ uncommented_lines = [
+ _COMMENT_RE.sub('', inf.line.strip()) for inf in line_infos_in_span]
+ uncommented_span = ' '.join(uncommented_lines)
+ if uncommented_span in seen_lines:
+ for info in line_infos_in_span:
+ info.deleted = True
+ elif not line_info.deleted:
+ seen_lines.add(uncommented_span)
def _DeleteExtraneousBlankLines(file_lines, line_range):
diff --git a/fix_includes_test.py b/fix_includes_test.py
index 09ffb69..1592b7c 100755
--- a/fix_includes_test.py
+++ b/fix_includes_test.py
@@ -2810,7 +2810,7 @@ The full include-list for comments_with_includes:
self.RegisterFileContents({'comments_with_includes': infile})
self.ProcessAndTest(iwyu_output)
- def testRemoveDuplicates(self):
+ def testRemoveDuplicateIncludes(self):
"""Tests we uniquify if an #include is in there twice."""
infile = """\
// Copyright 2010
@@ -2830,19 +2830,75 @@ The full include-list for comments_with_includes:
int main() { return 0; }
"""
iwyu_output = """\
-remove_duplicates should add these lines:
+remove_duplicate_includes should add these lines:
#include <stdio.h>
-remove_duplicates should remove these lines:
+remove_duplicate_includes should remove these lines:
- #include <notused.h> // lines 3-3
-The full include-list for remove_duplicates:
+The full include-list for remove_duplicate_includes:
#include <stdio.h>
#include "used.h"
#include "used2.h"
---
"""
- self.RegisterFileContents({'remove_duplicates': infile})
+ self.RegisterFileContents({'remove_duplicate_includes': infile})
+ self.ProcessAndTest(iwyu_output)
+
+ def testRemoveDuplicateForwardDeclarations(self):
+ """Tests we uniquify if an #include is in there twice."""
+ infile = """\
+#include <notused.h> ///-
+class A;
+template<typename T> // Comment in the middle not a problem
+class B;
+class A; ///-
+template<typename T> ///-
+class B; ///-
+template<typename T> class B; ///-
+
+int main() { return 0; }
+"""
+ iwyu_output = """\
+remove_duplicate_forward_declarations should add these lines:
+
+remove_duplicate_forward_declarations should remove these lines:
+- #include <notused.h> // lines 1-1
+
+The full include-list for remove_duplicate_forward_declarations:
+class A; // lines 2-2
+template <typename T> class B; // lines 3-4
+class A; // lines 5-5
+template <typename T> class B; // lines 6-7
+template <typename T> class B; // lines 8-8
+---
+"""
+ self.RegisterFileContents({'remove_duplicate_forward_declarations': infile})
+ self.ProcessAndTest(iwyu_output)
+
+ def testDontRemoveTemplateLines(self):
+ """Tests we don't accidentally think repeated template lines are dupes."""
+ infile = """\
+#include <notused.h> ///-
+template<typename T>
+class A;
+template<typename T>
+class B;
+
+void f(A&, B&);
+"""
+ iwyu_output = """\
+dont_remove_template_lines should add these lines:
+
+dont_remove_template_lines should remove these lines:
+- #include <notused.h> // lines 1-1
+
+The full include-list for dont_remove_template_lines:
+template <typename T> class A; // lines 2-3
+template <typename T> class B; // lines 4-5
+---
+"""
+ self.RegisterFileContents({'dont_remove_template_lines': infile})
self.ProcessAndTest(iwyu_output)
def testNestedNamespaces(self):