2022-12-16 20:03:39 +00:00
|
|
|
#!/usr/bin/env python3
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2011-05-04 19:20:05 +01:00
|
|
|
##===--- fix_includes_test.py - test for fix_includes.py ------------------===##
|
2011-02-04 22:28:15 +00:00
|
|
|
#
|
|
|
|
# The LLVM Compiler Infrastructure
|
|
|
|
#
|
|
|
|
# This file is distributed under the University of Illinois Open Source
|
|
|
|
# License. See LICENSE.TXT for details.
|
|
|
|
#
|
2011-05-04 19:20:05 +01:00
|
|
|
##===----------------------------------------------------------------------===##
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2015-05-11 21:35:50 +01:00
|
|
|
from __future__ import print_function
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
"""Test for fix_includes.py
|
|
|
|
|
|
|
|
Test test test!
|
|
|
|
"""
|
|
|
|
|
|
|
|
__author__ = 'csilvers@google.com (Craig Silverstein)'
|
|
|
|
|
2015-05-11 21:36:31 +01:00
|
|
|
try:
|
|
|
|
from cStringIO import StringIO
|
|
|
|
except ImportError:
|
|
|
|
from io import StringIO
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
import re
|
2011-04-13 04:11:35 +01:00
|
|
|
import sys
|
2015-05-11 21:39:15 +01:00
|
|
|
# I use unittest instead of googletest to ease opensourcing.
|
2011-02-04 22:28:15 +00:00
|
|
|
import unittest
|
|
|
|
import fix_includes
|
|
|
|
|
|
|
|
|
2011-05-04 19:20:05 +01:00
|
|
|
class FakeFlags(object):
|
2011-02-04 22:28:15 +00:00
|
|
|
def __init__(self):
|
|
|
|
self.blank_lines = False
|
2011-04-12 05:55:05 +01:00
|
|
|
self.comments = True
|
2021-09-27 02:53:20 +01:00
|
|
|
self.update_comments = False
|
2011-02-04 22:28:15 +00:00
|
|
|
self.dry_run = False
|
2011-04-13 04:11:19 +01:00
|
|
|
self.ignore_re = None
|
2018-06-14 15:46:01 +01:00
|
|
|
self.only_re = None
|
2011-04-27 00:24:47 +01:00
|
|
|
self.safe_headers = False
|
2011-04-12 05:54:44 +01:00
|
|
|
self.separate_project_includes = None
|
2011-05-13 00:11:08 +01:00
|
|
|
self.keep_iwyu_namespace_format = False
|
2018-07-07 03:09:06 +01:00
|
|
|
self.reorder = True
|
2016-03-22 12:33:54 +00:00
|
|
|
self.basedir = None
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2011-05-04 19:20:05 +01:00
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
class FixIncludesBase(unittest.TestCase):
|
|
|
|
"""Does setup that every test will want."""
|
|
|
|
|
2018-03-18 15:37:34 +00:00
|
|
|
def _ReadFile(self, filename, fileinfo):
|
2011-02-04 22:28:15 +00:00
|
|
|
assert filename in self.before_map, filename
|
|
|
|
return self.before_map[filename]
|
|
|
|
|
2018-03-18 15:37:34 +00:00
|
|
|
def _ParseFileInfo(self, filename):
|
2018-03-18 15:53:32 +00:00
|
|
|
return fix_includes.FileInfo('\n', 'utf-8')
|
2018-03-18 15:37:34 +00:00
|
|
|
|
|
|
|
def _WriteFile(self, filename, fileinfo, contents):
|
|
|
|
return self.actual_after_contents.extend(contents)
|
2018-03-19 20:02:13 +00:00
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def setUp(self):
|
|
|
|
self.flags = FakeFlags()
|
|
|
|
|
|
|
|
# Map from filename to its contents (a list of lines) before fixing.
|
|
|
|
self.before_map = {}
|
|
|
|
# Map from filename to the 'correct' contents it should have after fixing.
|
|
|
|
self.expected_after_map = {}
|
|
|
|
|
|
|
|
# INPUT: fix_includes._ReadFile takes a filename
|
|
|
|
# and returns the contents of filename (as a list).
|
2018-03-18 15:37:34 +00:00
|
|
|
# FileInfo controls encoding details of the file,
|
|
|
|
# wire it to return something that agrees with the
|
|
|
|
# tests.
|
2011-02-04 22:28:15 +00:00
|
|
|
fix_includes._ReadFile = self._ReadFile
|
2018-03-18 15:37:34 +00:00
|
|
|
fix_includes.FileInfo.parse = self._ParseFileInfo
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
# OUTPUT: Instead of writing to file, save full output.
|
|
|
|
self.actual_after_contents = []
|
2018-03-19 20:02:13 +00:00
|
|
|
fix_includes._WriteFile = self._WriteFile
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2016-03-09 16:01:43 +00:00
|
|
|
# Stub out stdout
|
|
|
|
self.stdout_stub = StringIO()
|
|
|
|
fix_includes.sys.stdout = self.stdout_stub
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def RegisterFileContents(self, file_contents_map):
|
|
|
|
"""Parses and stores the given map from filename to file-contents.
|
|
|
|
|
|
|
|
The values of the map are file 'contents', written in a simple
|
|
|
|
markup language that allows us to encode both the 'before' and
|
|
|
|
expected 'after' contents of a file. Every line is taken
|
|
|
|
literally to be in both the before and after, with the following
|
|
|
|
exceptions:
|
|
|
|
1) Lines that look like '///+foo' are removed from 'before',
|
|
|
|
and replaced by 'foo' in 'after'. (This is an 'add'
|
|
|
|
instruction.)
|
|
|
|
2) Lines that end in '///-' are removed from both 'after'
|
|
|
|
and the '\s*///-' suffix is removed from 'before'.
|
|
|
|
(This is a 'remove' instruction.)
|
|
|
|
|
|
|
|
This function processes the input map to produce self.before_map
|
|
|
|
and self.expected_after_map.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
file_contents_map: a map from filename to 'contents'. Contents
|
|
|
|
is a string, having the format mentioned above.
|
|
|
|
"""
|
|
|
|
remove_re = re.compile('\s*///-$')
|
2015-05-11 21:36:48 +01:00
|
|
|
for (filename, contents) in file_contents_map.items():
|
2011-02-04 22:28:15 +00:00
|
|
|
before_contents = []
|
|
|
|
expected_after_contents = []
|
2019-01-23 17:43:06 +00:00
|
|
|
for line in contents.splitlines(True):
|
2011-02-04 22:28:15 +00:00
|
|
|
m = remove_re.search(line)
|
|
|
|
if m:
|
2019-01-23 17:43:06 +00:00
|
|
|
# The trailing line separator is stripped, so append a '\n'.
|
|
|
|
before_contents.append(line[:m.start()] + '\n')
|
2011-02-04 22:28:15 +00:00
|
|
|
elif line.startswith('///+'):
|
|
|
|
expected_after_contents.append(line[len('///+'):])
|
|
|
|
else:
|
|
|
|
before_contents.append(line)
|
|
|
|
expected_after_contents.append(line)
|
|
|
|
self.before_map[filename] = before_contents
|
|
|
|
self.expected_after_map[filename] = expected_after_contents
|
|
|
|
|
2011-03-04 00:26:29 +00:00
|
|
|
def ProcessAndTest(self, iwyu_output, cmdline_files=None, unedited_files=[],
|
2016-03-22 12:33:54 +00:00
|
|
|
expected_num_modified_files=None, cwd=None):
|
2011-02-04 22:28:15 +00:00
|
|
|
"""For all files mentioned in iwyu_output, compare expected and actual.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
iwyu_output: the output the iwyu script gave when run over the
|
|
|
|
set of input files.
|
|
|
|
cmdline_files: files to pass in to ProcessIWYUOutput (that, in
|
|
|
|
an actual fix_includes run, would come from the commandline).
|
|
|
|
These limit what files fix_includes chooses to edit.
|
|
|
|
unedited_files: the list of files that are listed in iwyu_output,
|
|
|
|
but fix_files has chosen not to edit for some reason.
|
2011-03-04 00:26:29 +00:00
|
|
|
expected_num_modified_files: what we expect ProcessIWYUOutput to
|
|
|
|
return. If None, suppress this check.
|
2016-03-22 12:33:54 +00:00
|
|
|
cwd: working directory passed to ProcessIWYUOutput, used to normalize
|
|
|
|
paths in cmdline_files. If None, no normalization occurs.
|
2011-02-04 22:28:15 +00:00
|
|
|
"""
|
|
|
|
filenames = re.findall('^(\S+) should add these lines:', iwyu_output, re.M)
|
|
|
|
if not filenames: # This is the other possible starting-line
|
|
|
|
filenames = re.findall('^\((\S+) has correct #includes/fwd-decls\)',
|
|
|
|
iwyu_output, re.M)
|
2015-05-11 21:38:54 +01:00
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
expected_after = []
|
2015-05-11 21:38:54 +01:00
|
|
|
for filename in fix_includes.OrderedSet(filenames): # uniquify
|
2016-03-22 12:33:54 +00:00
|
|
|
filename = fix_includes.NormalizeFilePath(self.flags.basedir, filename)
|
2011-02-04 22:28:15 +00:00
|
|
|
if filename not in unedited_files:
|
|
|
|
expected_after.extend(self.expected_after_map[filename])
|
|
|
|
|
2015-05-11 21:36:31 +01:00
|
|
|
iwyu_output_as_file = StringIO(iwyu_output)
|
2011-03-04 00:26:29 +00:00
|
|
|
num_modified_files = fix_includes.ProcessIWYUOutput(iwyu_output_as_file,
|
|
|
|
cmdline_files,
|
2016-03-22 12:33:54 +00:00
|
|
|
self.flags,
|
|
|
|
cwd=cwd)
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2011-05-04 19:33:53 +01:00
|
|
|
if expected_after != self.actual_after_contents:
|
2015-05-11 21:35:50 +01:00
|
|
|
print("=== Expected:")
|
2011-05-04 19:33:53 +01:00
|
|
|
for line in expected_after:
|
2015-05-11 21:35:50 +01:00
|
|
|
print(line)
|
|
|
|
print("=== Got:")
|
2011-05-04 19:33:53 +01:00
|
|
|
for line in self.actual_after_contents:
|
2015-05-11 21:35:50 +01:00
|
|
|
print(line)
|
|
|
|
print("===")
|
2011-02-04 22:28:15 +00:00
|
|
|
self.assertListEqual(expected_after, self.actual_after_contents)
|
2011-03-04 00:26:29 +00:00
|
|
|
if expected_num_modified_files is not None:
|
|
|
|
self.assertEqual(expected_num_modified_files, num_modified_files)
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
class FixIncludesTest(FixIncludesBase):
|
|
|
|
"""End-to-end tests from input file to output file."""
|
|
|
|
|
|
|
|
def testSimple(self):
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
simple should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
simple should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for simple:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'simple': infile})
|
2011-03-04 00:26:29 +00:00
|
|
|
self.ProcessAndTest(iwyu_output, expected_num_modified_files=1)
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2016-03-09 16:01:43 +00:00
|
|
|
def testUnifiedDiffOutput(self):
|
|
|
|
"""Test the unified diff output generated by dry runs."""
|
|
|
|
infile = """
|
|
|
|
#include <notused.h>
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
unified_diff.cc should add these lines:
|
|
|
|
|
|
|
|
unified_diff.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 2-2
|
|
|
|
|
|
|
|
The full include-list for unified_diff.cc:
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
diff_expect = """\
|
|
|
|
>>> Fixing #includes in 'unified_diff.cc'
|
|
|
|
@@ -1,4 +1,2 @@
|
|
|
|
-
|
|
|
|
-#include <notused.h>
|
|
|
|
|
|
|
|
int main() { return 0; }
|
2017-09-16 20:42:23 +01:00
|
|
|
IWYU edited 1 files on your behalf.
|
2016-03-09 16:01:43 +00:00
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
self.flags.dry_run = True
|
|
|
|
self.RegisterFileContents({'unified_diff.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output, unedited_files=['unified_diff.cc'])
|
|
|
|
|
|
|
|
self.assertEqual(self.stdout_stub.getvalue(), diff_expect)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testNodiffOutput(self):
|
|
|
|
"""Tests handling of the '(<file> has correct #includes)' iwyu output."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2011-07-07 18:02:40 +01:00
|
|
|
#include <ctype.h> // iwyu will not reorder, even though non-alphabetical
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
namespace Foo;
|
|
|
|
|
|
|
|
namespace Bar;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = "(nodiffs.h has correct #includes/fwd-decls)\n"
|
|
|
|
self.RegisterFileContents({'nodiffs.h': infile})
|
2011-07-07 18:02:40 +01:00
|
|
|
# fix_includes gives special output when there are no changes, so
|
|
|
|
# we can't use the normal ProcessAndTest.
|
2015-05-11 21:36:31 +01:00
|
|
|
iwyu_output_as_file = StringIO(iwyu_output)
|
2011-07-07 18:02:40 +01:00
|
|
|
num_modified_files = fix_includes.ProcessIWYUOutput(iwyu_output_as_file,
|
2016-03-22 12:33:54 +00:00
|
|
|
None, self.flags, None)
|
2011-07-07 18:02:40 +01:00
|
|
|
self.assertListEqual([], self.actual_after_contents) # 'no diffs'
|
|
|
|
self.assertEqual(0, num_modified_files)
|
2011-03-04 00:26:29 +00:00
|
|
|
|
|
|
|
def testNodiffOutputWithNoSorting(self):
|
|
|
|
"""Tests 'correct #includes' iwyu output, but does not need reordering."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
namespace Foo;
|
|
|
|
|
|
|
|
namespace Bar;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = "(nodiffs_nosorting.h has correct #includes/fwd-decls)\n"
|
|
|
|
self.RegisterFileContents({'nodiffs_nosorting.h': infile})
|
|
|
|
# fix_includes gives special output when there are no changes, so
|
|
|
|
# we can't use the normal ProcessAndTest.
|
2015-05-11 21:36:31 +01:00
|
|
|
iwyu_output_as_file = StringIO(iwyu_output)
|
2011-03-04 00:26:29 +00:00
|
|
|
num_modified_files = fix_includes.ProcessIWYUOutput(iwyu_output_as_file,
|
2016-03-22 12:33:54 +00:00
|
|
|
None, self.flags, None)
|
2011-03-04 00:26:29 +00:00
|
|
|
self.assertListEqual([], self.actual_after_contents) # 'no diffs'
|
|
|
|
self.assertEqual(0, num_modified_files)
|
2011-02-04 22:28:15 +00:00
|
|
|
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
def testRemoveEmptyNamespace(self):
|
|
|
|
"""Tests we remove a namespace if we remove all fwd-decls inside it."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
namespace ns { ///-
|
|
|
|
class Foo; ///-
|
|
|
|
namespace ns2 { ///-
|
|
|
|
namespace ns3 { ///-
|
|
|
|
class Bar; ///-
|
|
|
|
} } ///-
|
|
|
|
class Baz; ///-
|
|
|
|
} ///-
|
|
|
|
///-
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
empty_namespace should add these lines:
|
|
|
|
|
|
|
|
empty_namespace should remove these lines:
|
|
|
|
- class Foo; // lines 6-6
|
|
|
|
- namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } // lines 9-9
|
|
|
|
- namespace ns { class Baz; } } // lines 11-11
|
|
|
|
|
2018-06-11 22:35:21 +01:00
|
|
|
The full include-list for empty_namespace:
|
|
|
|
#include <stdio.h>
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'empty_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testRemoveEmptyAllmanNamespace(self):
|
|
|
|
"""Tests we remove a namespace with Allman braces if we remove all fwd-decls inside it."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
namespace ns ///-
|
|
|
|
{ ///-
|
|
|
|
class Foo; ///-
|
|
|
|
namespace ns2 ///-
|
|
|
|
{ ///-
|
|
|
|
namespace ns3 ///-
|
|
|
|
{ ///-
|
|
|
|
class Bar; ///-
|
|
|
|
} ///-
|
|
|
|
} ///-
|
|
|
|
class Baz; ///-
|
|
|
|
} ///-
|
|
|
|
///-
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
empty_namespace should add these lines:
|
|
|
|
|
|
|
|
empty_namespace should remove these lines:
|
|
|
|
- class Foo; // lines 7-7
|
|
|
|
- namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } // lines 12-12
|
|
|
|
- namespace ns { class Baz; } } // lines 15-15
|
|
|
|
|
|
|
|
The full include-list for empty_namespace:
|
|
|
|
#include <stdio.h>
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'empty_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testRemoveEmptyMixedNamespace(self):
|
|
|
|
"""Tests we remove a namespace with mixed braces if we remove all fwd-decls inside it."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
namespace ns ///-
|
|
|
|
{ ///-
|
|
|
|
class Foo; ///-
|
|
|
|
namespace ns2 { namespace ns3 ///-
|
|
|
|
{ ///-
|
|
|
|
class Bar; ///-
|
|
|
|
} ///-
|
|
|
|
} ///-
|
|
|
|
class Baz; ///-
|
|
|
|
} ///-
|
|
|
|
///-
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
empty_namespace should add these lines:
|
|
|
|
|
|
|
|
empty_namespace should remove these lines:
|
|
|
|
- class Foo; // lines 7-7
|
|
|
|
- namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } // lines 10-10
|
|
|
|
- namespace ns { class Baz; } } // lines 13-13
|
|
|
|
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
The full include-list for empty_namespace:
|
|
|
|
#include <stdio.h>
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'empty_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
2019-01-31 16:22:54 +00:00
|
|
|
|
|
|
|
def testCXX17NS(self):
|
|
|
|
"""Tests handling of output using the --cxx17ns switch."""
|
|
|
|
infile = """\
|
|
|
|
#include "cxx17ns-i1.h"///-
|
|
|
|
///+
|
|
|
|
///+namespace a::b::c {
|
|
|
|
///+struct One;
|
|
|
|
///+} // namespace a::b::c
|
|
|
|
///+namespace a::b {
|
|
|
|
///+struct One2;
|
|
|
|
///+} // namespace a::b
|
|
|
|
///+namespace a {
|
|
|
|
///+struct One4;
|
|
|
|
///+struct One3;
|
|
|
|
///+} // namespace a
|
|
|
|
|
|
|
|
struct Two {
|
|
|
|
Two(a::b::c::One& one);
|
|
|
|
Two(a::b::One2& one);
|
|
|
|
Two(a::One3& one);
|
|
|
|
Two(a::One4& one);
|
|
|
|
};
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
cxx17ns.cc should add these lines:
|
|
|
|
namespace a { namespace { struct One4; } }
|
|
|
|
namespace a { struct One3; }
|
|
|
|
namespace a::b { struct One2; }
|
|
|
|
namespace a::b::c { struct One; }
|
|
|
|
|
|
|
|
cxx17ns.cc should remove these lines:
|
|
|
|
- #include "cxx17ns-i1.h" // lines 1-1
|
|
|
|
|
|
|
|
The full include-list for cxx17ns.cc:
|
|
|
|
namespace a { namespace { struct One4; } }
|
|
|
|
namespace a { struct One3; }
|
|
|
|
namespace a::b { struct One2; }
|
|
|
|
namespace a::b::c { struct One; }
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'cxx17ns.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
|
2022-05-23 20:33:42 +01:00
|
|
|
def testNamespaceAlias(self):
|
|
|
|
"""Tests we leave namespace aliases alone."""
|
|
|
|
infile = """\
|
|
|
|
#include <stdint.h> ///-
|
|
|
|
|
|
|
|
namespace outer {
|
|
|
|
namespace middle {
|
|
|
|
namespace inner {
|
|
|
|
|
|
|
|
enum Values {
|
|
|
|
VAL
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace inner
|
|
|
|
} // namespace middle
|
|
|
|
|
|
|
|
// This alias should not be mistaken for an Allman namespace dfn
|
|
|
|
namespace inner = middle::inner;
|
|
|
|
|
|
|
|
} // namespace outer
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
namespace_alias.cc should add these lines:
|
|
|
|
|
|
|
|
namespace_alias.cc should remove these lines:
|
|
|
|
- #include <stdint.h> // lines 1-1
|
|
|
|
|
|
|
|
The full include-list for namespace_alias.cc:
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'namespace_alias.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-12 06:02:00 +01:00
|
|
|
def testRemovePartOfEmptyNamespace(self):
|
|
|
|
"""Tests we remove a namespace if empty, but not enclosing namespaces."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
namespace maps_transit_realtime {
|
|
|
|
namespace service_alerts {
|
|
|
|
class StaticServiceAlertStore;
|
|
|
|
namespace trigger { ///-
|
|
|
|
class Trigger; ///-
|
|
|
|
} // namespace trigger ///-
|
|
|
|
namespace ui { ///-
|
|
|
|
class Alert; ///-
|
|
|
|
} // namespace ui ///-
|
|
|
|
} // namespace service_alerts
|
|
|
|
} // namespace maps_transit_realtime
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
empty_internal_namespace should add these lines:
|
|
|
|
|
|
|
|
empty_internal_namespace should remove these lines:
|
|
|
|
- namespace maps_transit_realtime { namespace service_alerts { namespace trigger { class Trigger; } } } // lines 7-7
|
|
|
|
- namespace maps_transit_realtime { namespace service_alerts { namespace ui { class Alert; } } } // lines 10-10
|
|
|
|
|
|
|
|
The full include-list for empty_internal_namespace:
|
|
|
|
namespace maps_transit_realtime { namespace service_alerts { class StaticServiceAlertStore; } } // lines 5-5
|
|
|
|
---
|
2018-06-11 22:35:21 +01:00
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'empty_internal_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testRemovePartOfEmptyAllmanNamespace(self):
|
|
|
|
"""Tests we remove a namespace with Allman braces if empty, but not enclosing namespaces."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
namespace maps_transit_realtime
|
|
|
|
{
|
|
|
|
namespace service_alerts
|
|
|
|
{
|
|
|
|
class StaticServiceAlertStore;
|
|
|
|
namespace trigger ///-
|
|
|
|
{ ///-
|
|
|
|
class Trigger; ///-
|
|
|
|
} // namespace trigger ///-
|
|
|
|
namespace ui ///-
|
|
|
|
{ ///-
|
|
|
|
class Alert; ///-
|
|
|
|
} // namespace ui ///-
|
|
|
|
} // namespace service_alerts
|
|
|
|
} // namespace maps_transit_realtime
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
empty_internal_namespace should add these lines:
|
|
|
|
|
|
|
|
empty_internal_namespace should remove these lines:
|
|
|
|
- namespace maps_transit_realtime { namespace service_alerts { namespace trigger { class Trigger; } } } // lines 10-10
|
|
|
|
- namespace maps_transit_realtime { namespace service_alerts { namespace ui { class Alert; } } } // lines 14-14
|
|
|
|
|
|
|
|
The full include-list for empty_internal_namespace:
|
|
|
|
namespace maps_transit_realtime { namespace service_alerts { class StaticServiceAlertStore; } } // lines 7-7
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'empty_internal_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testRemovePartOfEmptyMixedNamespace(self):
|
|
|
|
"""Tests we remove a namespace with mixed braces if empty, but not enclosing namespaces."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
namespace maps_transit_realtime
|
|
|
|
{
|
|
|
|
class StaticServiceAlertStore;
|
|
|
|
namespace service_alerts { namespace trigger ///-
|
|
|
|
{ ///-
|
|
|
|
class Trigger; ///-
|
|
|
|
} // namespace trigger ///-
|
|
|
|
namespace ui ///-
|
|
|
|
{ ///-
|
|
|
|
class Alert; ///-
|
|
|
|
} // namespace ui ///-
|
|
|
|
} // namespace service_alerts ///-
|
|
|
|
} // namespace maps_transit_realtime
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
empty_internal_namespace should add these lines:
|
|
|
|
|
|
|
|
empty_internal_namespace should remove these lines:
|
|
|
|
- namespace maps_transit_realtime { namespace service_alerts { namespace trigger { class Trigger; } } } // lines 8-8
|
|
|
|
- namespace maps_transit_realtime { namespace service_alerts { namespace ui { class Alert; } } } // lines 12-12
|
|
|
|
|
|
|
|
The full include-list for empty_internal_namespace:
|
|
|
|
namespace maps_transit_realtime { class StaticServiceAlertStore; } // lines 5-5
|
|
|
|
---
|
2011-04-12 06:02:00 +01:00
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'empty_internal_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testRemoveEmptyIfdef(self):
|
|
|
|
"""Tests we remove an #ifdef if we remove all #includes inside it."""
|
|
|
|
# Also makes sure we reorder properly around the removed ifdef.
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
///+#include <stdlib.h>
|
|
|
|
// Only on windows. ///-
|
|
|
|
#ifdef OS_WINDOWS ///-
|
|
|
|
#include <notused.h> ///-
|
|
|
|
#include <notused2.h> ///-
|
|
|
|
#endif ///-
|
|
|
|
#include "used.h"
|
|
|
|
#include <stdlib.h> ///-
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
empty_ifdef should add these lines:
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
empty_ifdef should remove these lines:
|
|
|
|
- #include <notused.h> // lines 6-6
|
|
|
|
- #include <notused2.h> // lines 7-7
|
|
|
|
|
|
|
|
The full include-list for empty_ifdef:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'empty_ifdef': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testRemoveEmptyNestedIfdef(self):
|
|
|
|
"""Tests we remove an empty #ifdef inside a non-empty #ifdef."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#ifdef NDEBUG
|
|
|
|
// Only on windows. ///-
|
|
|
|
# ifdef OS_WINDOWS ///-
|
|
|
|
# include <notused.h> ///-
|
|
|
|
# include <notused2.h> ///-
|
|
|
|
# endif ///-
|
|
|
|
# undef VERBOSE_LOGGING
|
|
|
|
#endif
|
|
|
|
///+#include <stdlib.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include <stdlib.h> ///-
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
empty_nested_ifdef should add these lines:
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
empty_nested_ifdef should remove these lines:
|
|
|
|
- #include <notused.h> // lines 7-7
|
|
|
|
- #include <notused2.h> // lines 8-8
|
|
|
|
|
|
|
|
The full include-list for empty_nested_ifdef:
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'empty_nested_ifdef': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testNonEmptyIfdef(self):
|
|
|
|
"""Tests we keep an #ifdef if we don't remove all #includes inside it."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#ifdef OS_WINDOWS
|
|
|
|
#include <notused.h> ///-
|
|
|
|
#include <used_win.h>
|
|
|
|
#endif
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
nonempty_ifdef should add these lines:
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
nonempty_ifdef should remove these lines:
|
|
|
|
- #include <notused.h> // lines 5-5
|
|
|
|
|
|
|
|
The full include-list for nonempty_ifdef:
|
|
|
|
#include <used_win.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'nonempty_ifdef': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testKeepIfdefsWithNonIncludes(self):
|
|
|
|
"""Tests we keep an #ifdef if we have a non-#include inside it."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#ifdef OS_WINDOWS
|
|
|
|
#define IN_WINDOWS
|
|
|
|
#include <notused.h> ///-
|
|
|
|
#endif
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
nonempty_ifdef should add these lines:
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
nonempty_ifdef should remove these lines:
|
|
|
|
- #include <notused.h> // lines 6-6
|
|
|
|
|
|
|
|
The full include-list for nonempty_ifdef:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'nonempty_ifdef': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testRemoveComments(self):
|
|
|
|
"""Tests we remove comments above #includes."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
// This file is not used. ///-
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///-
|
|
|
|
// This file is not used either. ///-
|
|
|
|
// It's not used. ///-
|
|
|
|
// Not used at all. ///-
|
|
|
|
#include <notused2.h> ///-
|
|
|
|
///-
|
|
|
|
#include "notused3.h" ///-
|
|
|
|
|
|
|
|
// This comment should stay, it's not before an #include.
|
|
|
|
const int kInt = 5;
|
|
|
|
// This file is used.
|
|
|
|
// It's definitedly used.
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
const int kInt2 = 6;
|
|
|
|
///-
|
|
|
|
// This forward-declare is in a reorder_span all by itself. ///-
|
|
|
|
class NotUsed; ///-
|
|
|
|
|
|
|
|
// This comment should stay, it's not before an #include.
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
remove_comments should add these lines:
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
remove_comments should remove these lines:
|
|
|
|
- #include <notused.h> // lines 5-5
|
|
|
|
- #include <notused2.h> // lines 10-10
|
|
|
|
- #include "notused3.h" // lines 12-12
|
|
|
|
- class NotUsed; // lines 23-23
|
|
|
|
|
|
|
|
The full include-list for remove_comments:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'remove_comments': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testNoBlankLineAfterTopOfFileCxxComments(self):
|
|
|
|
"""Tests we don't remove top-of-file c++ comments right before #includes."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
top_of_file_comments.cc should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
top_of_file_comments.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 2-2
|
|
|
|
|
|
|
|
The full include-list for top_of_file_comments.cc:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'top_of_file_comments.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testNoBlankLineAfterTopOfFileCComments(self):
|
|
|
|
"""Tests we don't remove top-of-file c comments right before #includes."""
|
|
|
|
infile = """\
|
|
|
|
/*
|
|
|
|
* Copyright 2010
|
|
|
|
*/
|
|
|
|
#include <notused.h> ///-
|
|
|
|
/* This is a one-line c-style comment. */ ///-
|
|
|
|
#include <notused2.h> /* this is a c-style comment after a line */ ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
top_of_file_comments.c should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
top_of_file_comments.c should remove these lines:
|
|
|
|
- #include <notused.h> // lines 4-4
|
|
|
|
- #include <notused2.h> // lines 6-6
|
|
|
|
|
|
|
|
The full include-list for top_of_file_comments.c:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'top_of_file_comments.c': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-27 00:26:53 +01:00
|
|
|
def testNotFullLineCComments(self):
|
|
|
|
"""Tests that we treat lines with c comments then code as code-lines."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
///+#include <stdio.h>
|
|
|
|
///+
|
|
|
|
/* code here */ x = 4;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
not_full_line_c_comments.c should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
not_full_line_c_comments.c should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for not_full_line_c_comments.c:
|
|
|
|
#include <stdio.h>
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'not_full_line_c_comments.c': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testUnusualHFileNames(self):
|
|
|
|
"""Tests we treat .pb.h files as header files."""
|
|
|
|
infile = """\
|
|
|
|
/*
|
|
|
|
* Copyright 2010
|
|
|
|
*/
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.pb.h"
|
|
|
|
///+#include "used2.pb.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
pb.h.cc should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.pb.h"
|
|
|
|
|
|
|
|
pb.h.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 4-4
|
|
|
|
|
|
|
|
The full include-list for pb.h.cc:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.pb.h"
|
|
|
|
#include "used2.pb.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'pb.h.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testFwdDeclLines(self):
|
|
|
|
"""Tests that we keep or remove forward declares based on iwyu output."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
struct KeepStruct;
|
|
|
|
class NoKeepClass; ///-
|
|
|
|
template<typename Foo> class KeepTplClass;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
fwd_decl should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
fwd_decl should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
- class NoKeepClass; // lines 7-7
|
|
|
|
|
|
|
|
The full include-list for fwd_decl:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
struct KeepStruct; // lines 6-6
|
|
|
|
template<typename Foo> class KeepTplClass; // lines 8-8
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'fwd_decl': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testMultiLineFwdDecls(self):
|
|
|
|
"""Tests we keep forward-decls that span more than one line."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
struct KeepStruct;
|
|
|
|
class NoKeepClass; ///-
|
|
|
|
template<typename Foo, typename Bar = Baz>
|
|
|
|
class Keep2LineTplClass;
|
|
|
|
template<typename Foo, typename Bar = Baz> ///-
|
|
|
|
class NoKeep2LineTplClass; ///-
|
|
|
|
template<typename Foo,
|
|
|
|
typename Bar = Baz>
|
|
|
|
class Keep3LineTplClass;
|
|
|
|
template<typename Foo, ///-
|
|
|
|
typename Bar = Baz> ///-
|
|
|
|
class NoKeep3LineTplClass; ///-
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
multiline_fwd_decl should add these lines:
|
|
|
|
|
|
|
|
multiline_fwd_decl should remove these lines:
|
|
|
|
- class NoKeepClass; // lines 4-4
|
|
|
|
- template<typename Foo, typename Bar = Baz> class NoKeep2LineTplClass; // lines 7-8
|
|
|
|
- template<typename Foo, typename Bar = Baz> class NoKeep3LineTplClass; // lines 12-14
|
|
|
|
|
|
|
|
The full include-list for multiline_fwd_decl:
|
|
|
|
struct KeepStruct; // lines 3-3
|
|
|
|
template<typename Foo, typename Bar=Baz> class Keep2LineTplClass; // lines 5-6
|
|
|
|
template<typename Foo, typename Bar=Baz> class Keep3LineTplClass; // lines 9-11
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'multiline_fwd_decl': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testKeepExplicitSpecializations(self):
|
|
|
|
"""Tests we don't interpret an explicit spec. as a forward-declare."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
struct KeepStruct;
|
|
|
|
class NoKeepClass; ///-
|
|
|
|
template<typename Foo> class KeepTplClass;
|
|
|
|
///+
|
|
|
|
template<> class KeepTplClass<int>;
|
|
|
|
template<typename T> void TplFn<T>();
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
explicit_specialization should add these lines:
|
|
|
|
|
|
|
|
explicit_specialization should remove these lines:
|
|
|
|
- class NoKeepClass; // lines 4-4
|
|
|
|
|
|
|
|
The full include-list for explicit_specialization:
|
|
|
|
struct KeepStruct; // lines 3-3
|
|
|
|
template<typename Foo> class KeepTplClass; // lines 5-5
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'explicit_specialization': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testKeepNestedForwardDeclares(self):
|
|
|
|
"""Tests that we don't remove forward-declares inside classes/structs."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
class Keep;
|
|
|
|
class NoKeep; ///-
|
|
|
|
///+
|
|
|
|
class Nest {
|
|
|
|
class NestedClass;
|
|
|
|
///+
|
|
|
|
class NestedClass {
|
|
|
|
};
|
|
|
|
class NestedClass2 { }; // looks just like a fwd declare, except for the {}
|
|
|
|
template<typename T>
|
|
|
|
class NestedTplClass; // test multi-line nested classes as well
|
|
|
|
///+
|
|
|
|
friend class NoKeep;
|
|
|
|
template<typename T> friend class NoKeepTpl;
|
|
|
|
};
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
nested_fwd_decl should add these lines:
|
|
|
|
|
|
|
|
nested_fwd_decl should remove these lines:
|
|
|
|
- class NoKeep; // lines 4-4
|
|
|
|
|
|
|
|
The full include-list for nested_fwd_decl:
|
|
|
|
class Keep; // lines 3-3
|
|
|
|
class Nest::NestedClass; // lines 6-6
|
|
|
|
template<typename T> class Nest::NestedTplClass; // lines 11-11
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'nested_fwd_decl': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddForwardDeclareBeforeUsingStatement(self):
|
|
|
|
"""Tests we never add a forward-declare after a contentful line."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
2011-04-12 05:54:21 +01:00
|
|
|
///+namespace Bar {
|
|
|
|
///+class Baz;
|
2011-04-26 23:57:34 +01:00
|
|
|
///+} // namespace Bar
|
2011-02-04 22:28:15 +00:00
|
|
|
///+
|
|
|
|
using Bar::baz;
|
|
|
|
|
2011-04-12 05:54:21 +01:00
|
|
|
namespace Foo { class Bang; } ///-
|
|
|
|
///+namespace Foo {
|
|
|
|
///+class Bang;
|
2011-04-26 23:57:34 +01:00
|
|
|
///+} // namespace Foo
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_before_using should add these lines:
|
|
|
|
namespace Bar { class Baz; }
|
|
|
|
|
|
|
|
add_fwd_decl_before_using should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_before_using:
|
|
|
|
#include "foo.h"
|
|
|
|
namespace Bar { class Baz; }
|
|
|
|
namespace Foo { class Bang; } // lines 7-7
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_before_using': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-12 05:54:21 +01:00
|
|
|
def testAddForwardDeclareInNamespace(self):
|
|
|
|
"""Make sure we normalize namespaces properly."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
///+namespace ns {
|
|
|
|
///+class Foo;
|
|
|
|
///+namespace ns2 {
|
|
|
|
///+namespace ns3 {
|
|
|
|
///+class Bar;
|
|
|
|
///+template <typename T> class Bang;
|
2011-04-26 23:57:34 +01:00
|
|
|
///+} // namespace ns3
|
|
|
|
///+} // namespace ns2
|
2011-04-12 05:54:21 +01:00
|
|
|
///+namespace ns4 {
|
|
|
|
///+class Baz;
|
2011-04-26 23:57:34 +01:00
|
|
|
///+} // namespace ns4
|
|
|
|
///+} // namespace ns
|
2011-04-12 05:54:21 +01:00
|
|
|
///+
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_inside_namespace should add these lines:
|
|
|
|
namespace ns { class Foo; }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class Bar; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } }
|
|
|
|
namespace ns { namespace ns4 { class Baz; } }
|
|
|
|
|
|
|
|
add_fwd_decl_inside_namespace should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_inside_namespace:
|
|
|
|
#include "foo.h" // lines 3-3
|
|
|
|
namespace ns { class Foo; }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class Bar; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } }
|
|
|
|
namespace ns { namespace ns4 { class Baz; } }
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_inside_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
def testAddForwardDeclareInsideNamespaceSometimes(self):
|
|
|
|
"""Tests that in special situations, we will put fwd-decls inside a ns."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
class Bar;
|
|
|
|
template <typename T> class Baz;
|
|
|
|
|
|
|
|
namespace ns {
|
|
|
|
|
|
|
|
namespace ns2 { // we sure do love nesting our namespaces!
|
|
|
|
|
|
|
|
class NsFoo;
|
2011-04-12 05:54:21 +01:00
|
|
|
///+namespace ns3 {
|
|
|
|
///+class NsBang;
|
|
|
|
///+template <typename T> class NsBaz;
|
2011-04-26 23:57:34 +01:00
|
|
|
///+} // namespace ns3
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
template <typename T> class NsBar;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_inside_namespace should add these lines:
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } }
|
|
|
|
|
|
|
|
add_fwd_decl_inside_namespace should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_inside_namespace:
|
|
|
|
#include "foo.h" // lines 3-3
|
|
|
|
class Bar; // lines 5-5
|
|
|
|
namespace ns { namespace ns2 { class NsFoo; } } // lines 12-12
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } }
|
|
|
|
namespace ns { namespace ns2 { template <typename T> class NsBar; } } // lines 13-13
|
|
|
|
template <typename T> class Baz; // lines 6-6
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_inside_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-05-13 00:09:36 +01:00
|
|
|
def testAddForwardDeclareInsideNamespaceWithHeaderGuard(self):
|
|
|
|
"""Tests that the header guard doesn't confuse our in-ns algorithm."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#ifndef HDR_GUARD
|
|
|
|
#define HDR_GUARD
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
class Bar;
|
|
|
|
template <typename T> class Baz;
|
|
|
|
|
|
|
|
namespace ns {
|
|
|
|
|
|
|
|
namespace ns2 { // we sure do love nesting our namespaces!
|
|
|
|
|
|
|
|
class NsFoo;
|
|
|
|
///+namespace ns3 {
|
|
|
|
///+class NsBang;
|
|
|
|
///+template <typename T> class NsBaz;
|
|
|
|
///+} // namespace ns3
|
|
|
|
template <typename T> class NsBar;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // HDR_GUARD
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_with_hdr_guard should add these lines:
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } }
|
|
|
|
|
|
|
|
add_fwd_decl_with_hdr_guard should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_with_hdr_guard:
|
|
|
|
#include "foo.h" // lines 6-6
|
|
|
|
class Bar; // lines 8-8
|
|
|
|
namespace ns { namespace ns2 { class NsFoo; } } // lines 15-15
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } }
|
|
|
|
namespace ns { namespace ns2 { template <typename T> class NsBar; } } // lines 16-16
|
|
|
|
template <typename T> class Baz; // lines 9-9
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_with_hdr_guard': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2018-07-12 00:20:20 +01:00
|
|
|
def testAddForwardDeclareInsideNamespaceWithIfDef(self):
|
|
|
|
"""Tests that ifdef blocks are ignored when finding namespaces."""
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
class Bar;
|
|
|
|
template <typename T> class Baz;
|
|
|
|
|
|
|
|
#ifdef THIS_IS_A_CONTENTFUL_LINE
|
|
|
|
#include "bar.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace ns {
|
|
|
|
|
|
|
|
namespace ns2 {
|
|
|
|
|
2018-07-12 00:20:20 +01:00
|
|
|
///+class NsBang;
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
class NsFoo;
|
|
|
|
template <typename T> class NsBar;
|
2018-07-12 00:20:20 +01:00
|
|
|
///+template <typename T> class NsBaz;
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
2018-07-12 00:20:20 +01:00
|
|
|
add_forward_declares_after_ifdef_code should add these lines:
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
namespace ns { namespace ns2 { class NsBang; } }
|
|
|
|
namespace ns { namespace ns2 { template <typename T> class NsBaz; } }
|
|
|
|
|
2018-07-12 00:20:20 +01:00
|
|
|
add_forward_declares_after_ifdef_code should remove these lines:
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
|
2018-07-12 00:20:20 +01:00
|
|
|
The full include-list for add_forward_declares_after_ifdef_code:
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
#include "foo.h" // lines 3-3
|
|
|
|
class Bar; // lines 5-5
|
|
|
|
namespace ns { namespace ns2 { class NsBang; } }
|
|
|
|
namespace ns { namespace ns2 { class NsFoo; } } // lines 16-16
|
|
|
|
namespace ns { namespace ns2 { template <typename T> class NsBar; } } // lines 17-17
|
|
|
|
namespace ns { namespace ns2 { template <typename T> class NsBaz; } }
|
|
|
|
template <typename T> class Baz; // lines 6-6
|
|
|
|
---
|
|
|
|
"""
|
2018-07-12 00:20:20 +01:00
|
|
|
self.RegisterFileContents({'add_forward_declares_after_ifdef_code': infile})
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-27 00:11:33 +01:00
|
|
|
def testAddForwardDeclareInsideNamespaceWithoutForwardDeclaresAlready(self):
|
|
|
|
"""Tests we put fwd-decls inside an ns even if the ns has no fwd-decl."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
class Bar;
|
|
|
|
template <typename T> class Baz;
|
|
|
|
|
|
|
|
namespace ns {
|
|
|
|
|
|
|
|
namespace ns2 { // we sure do love nesting our namespaces!
|
2018-07-12 00:20:20 +01:00
|
|
|
///-
|
2011-04-27 00:11:33 +01:00
|
|
|
///+namespace ns3 {
|
|
|
|
///+class NsBang;
|
|
|
|
///+template <typename T> class NsBaz;
|
|
|
|
///+} // namespace ns3
|
|
|
|
///+
|
|
|
|
int MyFunction() { }
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_inside_namespace_without_fwd_decl should add these lines:
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } }
|
|
|
|
|
|
|
|
add_fwd_decl_inside_namespace_without_fwd_decl should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_inside_namespace_without_fwd_decl:
|
|
|
|
#include "foo.h" // lines 3-3
|
|
|
|
class Bar; // lines 5-5
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } }
|
|
|
|
template <typename T> class Baz; // lines 6-6
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_inside_namespace_without_fwd_decl':
|
2018-08-10 12:05:04 +01:00
|
|
|
infile})
|
2011-04-27 00:11:33 +01:00
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2018-07-12 00:20:20 +01:00
|
|
|
def testAddForwardDeclareInsideNamespaceWithCompactEndings(self):
|
|
|
|
"""Tests we put fwd-decls inside an ns when using compact namespace endings."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 {
|
|
|
|
class Ns2Bang;
|
|
|
|
}} // namespace ns2 // namespace ns1
|
|
|
|
///+class NsBar;
|
|
|
|
class NsBaz;
|
|
|
|
///-
|
|
|
|
namespace ns3 { namespace ns4 { ///-
|
|
|
|
class Ns4Bye; ///-
|
|
|
|
}} // namespace ns4 // namespace ns3 ///-
|
|
|
|
} // namespace ns
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_inside_namespace_without_compact_endings should add these lines:
|
|
|
|
namespace ns { class NsBar; }
|
|
|
|
|
|
|
|
add_fwd_decl_inside_namespace_without_compact_endings should remove these lines:
|
|
|
|
- namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { namespace ns4 { class Ns4Bye; } } } } } // lines 9-9
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_inside_namespace_without_compact_endings:
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { class Ns2Bang; } } } // lines 4-4
|
|
|
|
namespace ns { class NsBaz; } // lines 6-6
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_inside_namespace_without_compact_endings':
|
|
|
|
infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-05-04 21:52:05 +01:00
|
|
|
def testAddForwardDeclareInsideNamespaceWithUnnamedNamespace(self):
|
|
|
|
"""Tests that unnamed namespaces do not mess up our in-ns calculation."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
class Bar;
|
|
|
|
|
|
|
|
namespace ns {
|
|
|
|
///+class NsBang;
|
|
|
|
///+template <typename T> class NsBaz;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
class NsFoo;
|
|
|
|
template <typename T> class NsBar;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_inside_namespace_unnamed_ns should add these lines:
|
|
|
|
namespace ns { class NsBang; }
|
|
|
|
namespace ns { template <typename T> class NsBaz; }
|
|
|
|
|
|
|
|
add_fwd_decl_inside_namespace_unnamed_ns should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_inside_namespace_unnamed_ns:
|
|
|
|
#include "foo.h" // lines 3-3
|
|
|
|
class Bar; // lines 5-5
|
2018-07-12 00:20:20 +01:00
|
|
|
namespace ns { namespace { class NsFoo; } } // lines 10-10
|
|
|
|
namespace ns { class NsBang; }
|
|
|
|
namespace ns { template <typename T> class NsBaz; }
|
|
|
|
namespace ns { namespace { template <typename T> class NsBar; } } // lines 11-11
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_inside_namespace_unnamed_ns':
|
|
|
|
infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddForwardDeclareInsideNamespacesWithUnnamedNamespaceAndContent(self):
|
|
|
|
"""Tests that nested namespaces with forward declares still get new additions."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
class Bar;
|
|
|
|
///+class Baz;
|
|
|
|
|
|
|
|
namespace ns {
|
|
|
|
///+class NsBang;
|
|
|
|
///+template <typename T> class NsBaz;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
///+class NsBaz;
|
|
|
|
class NsFoo;
|
|
|
|
template <typename T> class NsBar;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace ns1 {
|
|
|
|
///+class Ns1Bar;
|
|
|
|
///+class Ns1Baz;
|
|
|
|
class Ns1Foo;
|
|
|
|
|
|
|
|
int ns_int = 5; // here's my contentful line
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_inside_namespaces_with_existing_content should add these lines:
|
|
|
|
class Baz;
|
|
|
|
namespace ns { class NsBang; }
|
|
|
|
namespace ns { template <typename T> class NsBaz; }
|
|
|
|
namespace ns { namespace { class NsBaz; } }
|
|
|
|
namespace ns { namespace ns1 { class Ns1Bar; } }
|
|
|
|
namespace ns { namespace ns1 { class Ns1Baz; } }
|
|
|
|
|
|
|
|
add_fwd_decl_inside_namespaces_with_existing_content should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_inside_namespaces_with_existing_content:
|
|
|
|
#include "foo.h" // lines 3-3
|
|
|
|
class Bar; // lines 5-5
|
|
|
|
class Baz;
|
|
|
|
namespace ns { namespace { class NsFoo; } } // lines 10-10
|
|
|
|
namespace ns { namespace { class NsBaz; } }
|
|
|
|
namespace ns { class NsBang; }
|
|
|
|
namespace ns { template <typename T> class NsBaz; }
|
|
|
|
namespace ns { namespace { template <typename T> class NsBar; } } // lines 11-11
|
|
|
|
namespace ns { namespace ns1 { class Ns1Foo; } } // lines 15-15
|
|
|
|
namespace ns { namespace ns1 { class Ns1Bar; } }
|
|
|
|
namespace ns { namespace ns1 { class Ns1Baz; } }
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_inside_namespaces_with_existing_content':
|
|
|
|
infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddForwardDeclareInsideAllmanNamespacesWithUnnamedNamespaceAndContent(self):
|
|
|
|
"""Tests that nested Allman namespaces with forward declares still get new additions."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
class Bar;
|
|
|
|
///+class Baz;
|
|
|
|
|
|
|
|
namespace ns
|
|
|
|
{
|
|
|
|
///+class NsBang;
|
|
|
|
///+template <typename T> class NsBaz;
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
///+class NsBaz;
|
|
|
|
class NsFoo;
|
|
|
|
template <typename T> class NsBar;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace ns1
|
|
|
|
{
|
|
|
|
///+class Ns1Bar;
|
|
|
|
///+class Ns1Baz;
|
|
|
|
class Ns1Foo;
|
|
|
|
|
|
|
|
int ns_int = 5; // here's my contentful line
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_inside_allman_namespaces_with_existing_content should add these lines:
|
|
|
|
class Baz;
|
|
|
|
namespace ns { class NsBang; }
|
|
|
|
namespace ns { template <typename T> class NsBaz; }
|
|
|
|
namespace ns { namespace { class NsBaz; } }
|
|
|
|
namespace ns { namespace ns1 { class Ns1Bar; } }
|
|
|
|
namespace ns { namespace ns1 { class Ns1Baz; } }
|
|
|
|
|
|
|
|
add_fwd_decl_inside_allman_namespaces_with_existing_content should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_inside_allman_namespaces_with_existing_content:
|
|
|
|
#include "foo.h" // lines 3-3
|
|
|
|
class Bar; // lines 5-5
|
|
|
|
class Baz;
|
2011-05-04 21:52:05 +01:00
|
|
|
namespace ns { namespace { class NsFoo; } } // lines 12-12
|
2018-07-12 00:20:20 +01:00
|
|
|
namespace ns { namespace { class NsBaz; } }
|
2011-05-04 21:52:05 +01:00
|
|
|
namespace ns { class NsBang; }
|
|
|
|
namespace ns { template <typename T> class NsBaz; }
|
|
|
|
namespace ns { namespace { template <typename T> class NsBar; } } // lines 13-13
|
2018-07-12 00:20:20 +01:00
|
|
|
namespace ns { namespace ns1 { class Ns1Foo; } } // lines 18-18
|
|
|
|
namespace ns { namespace ns1 { class Ns1Bar; } }
|
|
|
|
namespace ns { namespace ns1 { class Ns1Baz; } }
|
2011-05-04 21:52:05 +01:00
|
|
|
---
|
|
|
|
"""
|
2018-07-12 00:20:20 +01:00
|
|
|
self.RegisterFileContents({'add_fwd_decl_inside_allman_namespaces_with_existing_content':
|
|
|
|
infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddForwardDeclareInsideMixedNamespacesWithUnnamedNamespaceAndContent(self):
|
|
|
|
"""Tests that nested mixed namespaces with forward declares still get new additions."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "bar.h"
|
|
|
|
///+
|
|
|
|
///+class Baz;
|
|
|
|
///+
|
|
|
|
namespace ns { namespace ns1 { namespace ns2
|
|
|
|
{
|
|
|
|
///+class Ns2Bang;
|
|
|
|
///+template <typename T> class Ns2Baz;
|
|
|
|
///+
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
///+class NsaBaz;
|
|
|
|
class NsaFoo;
|
|
|
|
template <typename T> class NsaBar;
|
|
|
|
} // namespace
|
|
|
|
namespace ns3 {
|
|
|
|
///+class Ns3Bar;
|
|
|
|
///+class Ns3Baz;
|
|
|
|
class Ns3Foo;
|
|
|
|
///+
|
|
|
|
int ns3_int = 5; // here's my contentful line
|
|
|
|
} // namespace ns3
|
|
|
|
} // namespace ns2
|
|
|
|
} // namespace ns1
|
|
|
|
} // namespace ns
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_inside_mixed_namespaces_with_existing_content should add these lines:
|
|
|
|
class Baz;
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { class Ns2Bang; } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { template <typename T> class Ns2Baz; } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace { class NsaBaz; } } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Bar; } } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Baz; } } } }
|
|
|
|
|
|
|
|
add_fwd_decl_inside_mixed_namespaces_with_existing_content should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_inside_mixed_namespaces_with_existing_content:
|
|
|
|
#include "bar.h" // lines 3-3
|
|
|
|
#include "foo.h"
|
|
|
|
class Baz;
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { class Ns2Bang; } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { template <typename T> class Ns2Baz; } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace { class NsaFoo; } } } } // lines 8-8
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace { template <typename T> class NsaBar; } } } } // lines 9-9
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace { class NsaBaz; } } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Bar; } } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Baz; } } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Foo; } } } } // lines 12-12
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_inside_mixed_namespaces_with_existing_content':
|
|
|
|
infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddForwardDeclareInsideNestedNamespacesAndTopLevelForComplexNamespaces(self):
|
|
|
|
"""Tests that nested namespaces still get new additions while putting hard to resolve forward declares at the top."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
///+namespace ns {
|
|
|
|
///+class NsBang;
|
|
|
|
///+namespace ns1 {
|
|
|
|
///+Ns1Bang;
|
|
|
|
///+} // namespace ns1
|
|
|
|
///+} // namespace ns
|
|
|
|
///+
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 {
|
|
|
|
class Ns2Bang;
|
|
|
|
class Ns2Bar; ///-
|
|
|
|
///+class Ns2Baz;
|
|
|
|
///+
|
|
|
|
namespace ns3 {
|
|
|
|
///+class Ns3Bang;
|
|
|
|
class Ns3Baz;
|
|
|
|
} // namespace ns3
|
|
|
|
} // namespace ns2
|
|
|
|
} // namespace ns1
|
|
|
|
} // namespace ns
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_inside_nested_namespaces_and_top_level_for_complex_namespaces should add these lines:
|
|
|
|
namespace ns { class NsBang; }
|
|
|
|
namespace ns { namespace ns1 { Ns1Bang; }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { class Ns2Baz; } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Bang; } } } }
|
|
|
|
|
|
|
|
add_fwd_decl_inside_nested_namespaces_and_top_level_for_complex_namespaces should remove these lines:
|
|
|
|
- namespace ns { namespace ns1 { namespace ns2 { class Ns2Bar; } } } // lines 5-5
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_inside_nested_namespaces_and_top_level_for_complex_namespaces:
|
|
|
|
namespace ns { class NsBang; }
|
|
|
|
namespace ns { namespace ns1 { Ns1Bang; }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { class Ns2Bang; } } } // lines 4-4
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { class Ns2Baz; } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Bang; } } } }
|
|
|
|
namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Baz; } } } } // lines 7-7
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_inside_nested_namespaces_and_top_level_for_complex_namespaces':
|
2018-08-10 12:05:04 +01:00
|
|
|
infile})
|
2011-05-04 21:52:05 +01:00
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testRemoveNamespaces(self):
|
|
|
|
"""Tests that we keep or remove ns's based on fwd decl content."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
namespace ns1 {
|
|
|
|
struct KeepStruct;
|
|
|
|
class NoKeepClass; ///-
|
|
|
|
template<typename Foo> class KeepTplClass;
|
|
|
|
}
|
|
|
|
///-
|
|
|
|
namespace ns1 { ///-
|
|
|
|
namespace ns2 { ///-
|
|
|
|
// This should all go away. ///-
|
|
|
|
// Even with the multi-line comment here. ///-
|
|
|
|
template<typename Foo> class NoKeepTplClass; ///-
|
|
|
|
} ///-
|
|
|
|
} ///-
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
ns_fwd_decl should add these lines:
|
|
|
|
|
|
|
|
ns_fwd_decl should remove these lines:
|
|
|
|
- class NoKeepClass; // lines 5-5
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
- namespace ns1 { namespace ns2 { template<typename Foo> class NoKeepTplClass; } } // lines 13-13
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
The full include-list for ns_fwd_decl:
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
namespace ns1 { struct KeepStruct; } // lines 4-4
|
|
|
|
namespace ns1 { template<typename Foo> class KeepTplClass; } // lines 6-6
|
2011-02-04 22:28:15 +00:00
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'ns_fwd_decl': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testKeepNamespacesWithNonForwardDecls(self):
|
|
|
|
"""Tests we never remove a ns with 'real' content in it."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
namespace ns1 {
|
|
|
|
int ns_int = 5;
|
|
|
|
class NoKeepClass; ///-
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
keep_ns_fwd_decl should add these lines:
|
|
|
|
|
|
|
|
keep_ns_fwd_decl should remove these lines:
|
|
|
|
- class NoKeepClass; // lines 5-5
|
|
|
|
|
|
|
|
The full include-list for keep_ns_fwd_decl:
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'keep_ns_fwd_decl': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testICUNamespaces(self):
|
|
|
|
"""Tests we treat the icu namespace macros as namespaces."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
U_NAMESPACE_BEGIN // macro from icu
|
|
|
|
struct KeepStruct;
|
|
|
|
class NoKeepClass; ///-
|
|
|
|
template<typename Foo> class KeepTplClass;
|
|
|
|
U_NAMESPACE_END
|
2011-04-27 00:05:25 +01:00
|
|
|
///-
|
|
|
|
U_NAMESPACE_BEGIN ///-
|
|
|
|
template<typename Foo> class NoKeepTplClass; ///-
|
|
|
|
U_NAMESPACE_END ///-
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
icu_namespace should add these lines:
|
|
|
|
|
|
|
|
icu_namespace should remove these lines:
|
|
|
|
- class NoKeepClass; // lines 5-5
|
|
|
|
- template<typename Foo> class NoKeepTplClass; // lines 10-10
|
|
|
|
|
|
|
|
The full include-list for icu_namespace:
|
In certain situations where it's easy to do, identify
forward-declares inside namespaces, and add new
forward-declares for that namespace inside the namespace as
well, rather than putting all new forward-declares at the top
of the file.
Because parsing where namespaces start and stop is difficult
in general, we only do this in certain situations, albeit the
most common ones. Having 'contentful' code before the
namespace starts cause us to abort. We could relax this to
only avoid 'contentful' code that might confuse our namespace
determination -- that's not difficult, but requires careful
thought as to tests to make sure we're not messing up ever.
I also fixed the test in a few other places to better match
the output that iwyu actual gives. I also-also fixed a regexp
involved in detecting when a namespace ends, that only
triggers when we end multiple nested namespaces on one line
(with '}}}'), which doesn't happen often in real life, which
is why we didn't see any problems before. I slightly modified
a test, by adding in whitespace, to test the fixed regexp.
R=dsturtevant
DELTA=276 (265 added, 0 deleted, 11 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=1076
2011-03-26 22:16:33 +00:00
|
|
|
namespace ns1 { struct KeepStruct; } // lines 4-4
|
|
|
|
namespace ns1 { template<typename Foo> class KeepTplClass; } // lines 6-6
|
2011-02-04 22:28:15 +00:00
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'icu_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-27 00:05:25 +01:00
|
|
|
def testHashNamespaces(self):
|
|
|
|
"""Tests we treat the hash namespace macros as namespaces."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
HASH_NAMESPACE_DECLARATION_START // macro from hash.h
|
|
|
|
struct KeepStruct;
|
|
|
|
class NoKeepClass; ///-
|
|
|
|
template<typename Foo> class KeepTplClass;
|
|
|
|
HASH_NAMESPACE_DECLARATION_END
|
|
|
|
///-
|
|
|
|
HASH_NAMESPACE_DECLARATION_START ///-
|
|
|
|
template<typename Foo> class NoKeepTplClass; ///-
|
|
|
|
HASH_NAMESPACE_DECLARATION_END ///-
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
hash_namespace should add these lines:
|
|
|
|
|
|
|
|
hash_namespace should remove these lines:
|
|
|
|
- class NoKeepClass; // lines 5-5
|
|
|
|
- template<typename Foo> class NoKeepTplClass; // lines 10-10
|
|
|
|
|
|
|
|
The full include-list for hash_namespace:
|
|
|
|
namespace ns1 { struct KeepStruct; } // lines 4-4
|
|
|
|
namespace ns1 { template<typename Foo> class KeepTplClass; } // lines 6-6
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'hash_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testElaboratedClasses(self):
|
|
|
|
"""Tests we don't remove lines like 'class Foo* fooptr'."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
struct KeepStruct;
|
|
|
|
class NoKeepClass; ///-
|
|
|
|
///+
|
|
|
|
struct NoKeepStruct* s;
|
|
|
|
struct NoKeepStruct& t;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
elaborated_class should add these lines:
|
|
|
|
|
|
|
|
elaborated_class should remove these lines:
|
|
|
|
- class NoKeepClass; // lines 4-4
|
|
|
|
|
|
|
|
The full include-list for elaborated_class:
|
|
|
|
struct KeepStruct; // lines 3-3
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'elaborated_class': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testBFlag(self):
|
|
|
|
"""Tests that --b properly separates sections."""
|
|
|
|
self.flags.blank_lines = True
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include "subdir/bflag.h"
|
|
|
|
///+
|
|
|
|
///+#include <stdio.h>
|
|
|
|
///+
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
subdir/bflag.cc should add these lines:
|
|
|
|
#include "subdir/bflag.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
subdir/bflag.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for subdir/bflag.cc:
|
|
|
|
#include "subdir/bflag.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'subdir/bflag.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-27 00:24:47 +01:00
|
|
|
def testSafeHeadersFlag(self):
|
|
|
|
"""Tests that --safe_headers causes us to not delete lines."""
|
|
|
|
self.flags.safe_headers = True
|
2011-03-18 06:55:50 +00:00
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
2011-04-27 00:27:23 +01:00
|
|
|
#include <notused.h>
|
|
|
|
#include <notused2.h> // Hello!
|
2011-03-18 06:55:50 +00:00
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
2011-04-27 00:27:23 +01:00
|
|
|
class Foo;
|
|
|
|
template<typename T>
|
|
|
|
class Bar;
|
2011-03-18 06:55:50 +00:00
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
2011-04-27 00:09:21 +01:00
|
|
|
safe_flag.h should add these lines:
|
2011-03-18 06:55:50 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
2011-04-27 00:09:21 +01:00
|
|
|
safe_flag.h should remove these lines:
|
2011-03-18 06:55:50 +00:00
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
- #include <notused.h> // lines 4-4
|
|
|
|
- class Foo // lines 7-7
|
2011-04-27 00:08:30 +01:00
|
|
|
- class Bar // lines 8-9
|
|
|
|
|
2011-04-27 00:09:21 +01:00
|
|
|
The full include-list for safe_flag.h:
|
2011-04-27 00:08:30 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
2011-04-27 00:09:21 +01:00
|
|
|
self.RegisterFileContents({'safe_flag.h': infile})
|
2011-04-27 00:08:30 +01:00
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-27 00:24:47 +01:00
|
|
|
def testSafeHeadersFlagTwice(self):
|
|
|
|
"""Tests running --safe_headers 2ce in a row doesn't duplicate comments."""
|
|
|
|
self.flags.safe_headers = True
|
2011-04-27 00:08:30 +01:00
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> // iwyu says this can be removed
|
|
|
|
#include <notused2.h> // Hello!; iwyu says this can be removed
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
class Foo; // iwyu says this can be removed
|
|
|
|
template<typename T> // iwyu says this can be removed
|
|
|
|
class Bar; // iwyu says this can be removed
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
2011-04-27 00:09:21 +01:00
|
|
|
safe_flag_twice.h should add these lines:
|
2011-04-27 00:08:30 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
2011-04-27 00:09:21 +01:00
|
|
|
safe_flag_twice.h should remove these lines:
|
2011-04-27 00:08:30 +01:00
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
- #include <notused.h> // lines 4-4
|
|
|
|
- class Foo // lines 7-7
|
|
|
|
- class Bar // lines 8-9
|
2011-03-18 06:55:50 +00:00
|
|
|
|
2011-04-27 00:09:21 +01:00
|
|
|
The full include-list for safe_flag_twice.h:
|
2011-03-18 06:55:50 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
2011-04-27 00:09:21 +01:00
|
|
|
self.RegisterFileContents({'safe_flag_twice.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-27 00:24:47 +01:00
|
|
|
def testSafeHeadersFlagOnCcFiles(self):
|
|
|
|
"""Tests that we delete even in --safe_headers mode, on .cc files."""
|
|
|
|
self.flags.safe_headers = True
|
2011-04-27 00:09:21 +01:00
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
#include <notused2.h> // Hello! ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
class Foo; ///-
|
|
|
|
template<typename T> ///-
|
|
|
|
class Bar; ///-
|
|
|
|
///-
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
safe_flag.cc should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
safe_flag.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
- #include <notused.h> // lines 4-4
|
|
|
|
- class Foo // lines 7-7
|
|
|
|
- class Bar // lines 8-9
|
|
|
|
|
|
|
|
The full include-list for safe_flag.cc:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'safe_flag.cc': infile})
|
2011-03-18 06:55:50 +00:00
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testIncludeComments(self):
|
|
|
|
"""Tests that we properly include comments on #include lines."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include "subdir/include_comments.h"
|
|
|
|
///+#include <stdio.h> // for printf(), etc.
|
|
|
|
#include "used.h" ///-
|
|
|
|
///+#include "used.h" // for Used
|
|
|
|
///+#include "used2.h" // for Used2, Used2::Used2, Used2::~Used2, Used2::Used_Enum, operator==()
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
subdir/include_comments.cc should add these lines:
|
|
|
|
#include "subdir/include_comments.h"
|
|
|
|
#include <stdio.h> // for printf(), etc.
|
|
|
|
#include "used2.h" // for Used2, Used2::Used2, Used2::~Used2, Used2::Used_Enum, operator==()
|
|
|
|
|
|
|
|
subdir/include_comments.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for subdir/include_comments.cc:
|
|
|
|
#include "subdir/include_comments.h"
|
|
|
|
#include <stdio.h> // for printf(), etc.
|
|
|
|
#include "used.h" // for Used
|
|
|
|
#include "used2.h" // for Used2, Used2::Used2, Used2::~Used2, Used2::Used_Enum, operator==()
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'subdir/include_comments.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testNocommentsFlag(self):
|
|
|
|
"""Tests we properly don't include/modify comments with --nocomments."""
|
2011-04-12 05:55:05 +01:00
|
|
|
self.flags.comments = False
|
2011-02-04 22:28:15 +00:00
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include "subdir/include_comments.h"
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h" // my favorite #include!
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
subdir/include_comments.cc should add these lines:
|
|
|
|
#include "subdir/include_comments.h"
|
|
|
|
#include <stdio.h> // for printf(), etc.
|
|
|
|
#include "used2.h" // for Used2, Used2::Used2, Used2::~Used2, Used2::Used_Enum, operator==()
|
|
|
|
|
|
|
|
subdir/include_comments.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for subdir/include_comments.cc:
|
|
|
|
#include "subdir/include_comments.h"
|
|
|
|
#include <stdio.h> // for printf(), etc.
|
|
|
|
#include "used.h" // for Used
|
|
|
|
#include "used2.h" // for Used2, Used2::Used2, Used2::~Used2, Used2::Used_Enum, operator==()
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'subdir/include_comments.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2021-09-27 02:53:20 +01:00
|
|
|
def testUpdateCommentsFlag(self):
|
|
|
|
"""Tests we update comments with --update_comments."""
|
|
|
|
self.flags.update_comments = True
|
|
|
|
infile = """\
|
|
|
|
#include "must_keep.h" // IWYU pragma: keep
|
|
|
|
#include "used.h" // for SomethingElse ///-
|
|
|
|
///+#include "used.h" // for Used
|
|
|
|
|
|
|
|
Used used;
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
subdir/include_comments.cc should add these lines:
|
|
|
|
|
|
|
|
subdir/include_comments.cc should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for subdir/include_comments.cc:
|
|
|
|
#include "must_keep.h"
|
|
|
|
#include "used.h" // for Used
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'subdir/include_comments.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testNoUpdateCommentsFlag(self):
|
|
|
|
"""Tests we don't update comments with --noupdate_comments."""
|
|
|
|
self.flags.update_comments = False
|
|
|
|
infile = """\
|
|
|
|
#include "must_keep.h" // IWYU pragma: keep
|
|
|
|
#include "used.h" // for SomethingElse
|
|
|
|
|
|
|
|
Used used;
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
subdir/include_comments.cc should add these lines:
|
|
|
|
|
|
|
|
subdir/include_comments.cc should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for subdir/include_comments.cc:
|
|
|
|
#include "must_keep.h"
|
|
|
|
#include "used.h" // for Used
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'subdir/include_comments.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output,
|
|
|
|
unedited_files=['subdir/include_comments.cc'])
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testFixingTwoFiles(self):
|
|
|
|
"""Make sure data for one fix doesn't overlap with a second."""
|
|
|
|
file_a = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
#include "used_only_in_file_a.h"
|
|
|
|
#include "used_only_in_file_b.h" ///-
|
|
|
|
|
|
|
|
class FileAClass; // kept for file A, not for file B
|
|
|
|
class FileBClass; // kept for file B, not for file A ///-
|
|
|
|
"""
|
|
|
|
file_b = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
#include "used_only_in_file_a.h" ///-
|
|
|
|
#include "used_only_in_file_b.h"
|
|
|
|
|
|
|
|
class FileAClass; // kept for file A, not for file B ///-
|
|
|
|
class FileBClass; // kept for file B, not for file A
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
file_a.cc should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
file_a.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
- #include "used_only_in_file_b.h" // lines 6-6
|
|
|
|
- class FileBClass; // lines 9-9
|
|
|
|
|
|
|
|
The full include-list for file_a.cc:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
#include "used_only_in_file_a.h"
|
|
|
|
class FileAClass; // lines 8-8
|
|
|
|
---
|
|
|
|
|
|
|
|
file_b.cc should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
file_b.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
- #include "used_only_in_file_a.h" // lines 5-5
|
|
|
|
- class FileAClass; // lines 8-8
|
|
|
|
|
|
|
|
The full include-list for file_b.cc:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
#include "used_only_in_file_b.h"
|
|
|
|
class FileBClass; // lines 9-9
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'file_a.cc': file_a, 'file_b.cc': file_b})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testListingTheSameFileTwice(self):
|
|
|
|
"""Test when foo.cc is specified twice. It should fix conservatively."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
2011-04-27 00:11:07 +01:00
|
|
|
///+#include "include_this_file" // for reason 2
|
2011-02-04 22:28:15 +00:00
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
#include "used_only_in_file_a.h"
|
|
|
|
#include "used_only_in_file_b.h" ///-
|
|
|
|
|
|
|
|
class FileAClass; // kept for file A, not for file B
|
|
|
|
class FileBClass; // kept for file B, not for file A ///-
|
2011-05-04 19:33:53 +01:00
|
|
|
///+namespace foo {
|
|
|
|
///+template <typename Arg1> ClassTemplate;
|
|
|
|
///+} // namespace foo
|
|
|
|
///+template <typename Arg1> ClassTemplate;
|
2011-02-04 22:28:15 +00:00
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
twice.cc should add these lines:
|
|
|
|
#include <stdio.h>
|
2011-04-27 00:11:07 +01:00
|
|
|
#include "include_this_file" // for reason 1
|
2011-05-04 19:33:53 +01:00
|
|
|
namespace foo { template <typename Arg1> ClassTemplate; }
|
|
|
|
template <typename Arg1> ClassTemplate;
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
twice.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
- #include "used_only_in_file_a.h" // lines 5-5
|
|
|
|
- #include "used_only_in_file_b.h" // lines 6-6
|
|
|
|
- class FileAClass; // lines 8-8
|
|
|
|
- class FileBClass; // lines 9-9
|
|
|
|
|
|
|
|
The full include-list for twice.cc:
|
|
|
|
#include <stdio.h>
|
2011-04-27 00:11:07 +01:00
|
|
|
#include "include_this_file" // for reason 1
|
2011-02-04 22:28:15 +00:00
|
|
|
#include "used.h"
|
2011-05-04 19:33:53 +01:00
|
|
|
namespace foo { template <typename Arg1> ClassTemplate; }
|
|
|
|
template <typename Arg1> ClassTemplate;
|
2011-02-04 22:28:15 +00:00
|
|
|
---
|
|
|
|
|
|
|
|
twice.cc should add these lines:
|
|
|
|
#include "used2.h"
|
2011-04-27 00:11:07 +01:00
|
|
|
#include "include_this_file" // for reason 2
|
2011-05-04 19:33:53 +01:00
|
|
|
namespace foo { template <typename Arg2> ClassTemplate; }
|
|
|
|
template <typename Arg2> ClassTemplate;
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
twice.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
- #include "used_only_in_file_b.h" // lines 6-6
|
|
|
|
- class FileBClass; // lines 9-9
|
|
|
|
|
|
|
|
The full include-list for twice.cc:
|
2011-04-27 00:11:07 +01:00
|
|
|
#include "include_this_file" // for reason 2
|
2011-02-04 22:28:15 +00:00
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
#include "used_only_in_file_a.h"
|
|
|
|
class FileAClass; // lines 8-8
|
2011-05-04 19:33:53 +01:00
|
|
|
namespace foo { template <typename Arg2> ClassTemplate; }
|
|
|
|
template <typename Arg2> ClassTemplate;
|
2011-02-04 22:28:15 +00:00
|
|
|
---
|
2011-09-23 18:18:46 +01:00
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'twice.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testListingTheSameFileTwiceAndOnceIsANoop(self):
|
|
|
|
"""Test when foo.cc is specified twice, once with 'all correct'."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h>
|
|
|
|
///+#include <stdio.h>
|
|
|
|
///+#include "include_this_file" // for reason 1
|
|
|
|
#include "used.h"
|
|
|
|
#include "used_only_in_file_a.h"
|
|
|
|
|
|
|
|
class FileAClass;
|
|
|
|
///+namespace foo {
|
|
|
|
///+template <typename Arg1> ClassTemplate;
|
|
|
|
///+} // namespace foo
|
|
|
|
///+template <typename Arg1> ClassTemplate;
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
twice.cc should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "include_this_file" // for reason 1
|
|
|
|
namespace foo { template <typename Arg1> ClassTemplate; }
|
|
|
|
template <typename Arg1> ClassTemplate;
|
|
|
|
|
|
|
|
twice.cc should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
- #include "used_only_in_file_a.h" // lines 5-5
|
|
|
|
- class FileAClass; // lines 7-7
|
|
|
|
|
|
|
|
The full include-list for twice.cc:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "include_this_file" // for reason 1
|
|
|
|
#include "used.h"
|
|
|
|
namespace foo { template <typename Arg1> ClassTemplate; }
|
|
|
|
template <typename Arg1> ClassTemplate;
|
|
|
|
---
|
|
|
|
|
|
|
|
(twice.cc has correct #includes/fwd-decls)
|
2011-02-04 22:28:15 +00:00
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'twice.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddForwardDeclare(self):
|
|
|
|
"""Test adding a forward-declare, rather than keeping one."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
///+
|
|
|
|
///+struct NotUsed;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
new_fwd_decl should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
struct NotUsed;
|
|
|
|
|
|
|
|
new_fwd_decl should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for new_fwd_decl:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
struct NotUsed;
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'new_fwd_decl': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddAndKeepForwardDeclare(self):
|
|
|
|
"""Test adding a forward-declare in addition to keeping one."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
class ForwardDeclClass;
|
|
|
|
///+struct NotUsed;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
new_and_keep_fwd_decl should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
struct NotUsed;
|
|
|
|
|
|
|
|
new_and_keep_fwd_decl should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for new_and_keep_fwd_decl:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
class ForwardDeclareClass; // lines 6-6
|
|
|
|
struct NotUsed;
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'new_and_keep_fwd_decl': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddIncludeToFileThatHasOnlyForwardDeclarations(self):
|
|
|
|
"""Tests we add an #include in an appropriate place if none exist."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
///+#include <stdio.h>
|
|
|
|
///+#include "used.h"
|
|
|
|
///+
|
|
|
|
const int kFoo = 5; // we should insert before the contentful line.
|
|
|
|
|
|
|
|
class Foo;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
no_include_fwd_decl should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
|
|
|
|
no_include_fwd_decl should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for no_include_fwd_decl:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
class Foo; // lines 5-5
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'no_include_fwd_decl': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddForwardDeclarationToFileThatHasOnlyIncludes(self):
|
|
|
|
"""Tests we add a forward-declare in an appropriate place if none exist."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
const int kFoo = 5; // make sure we don't just insert at the beginning
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+
|
|
|
|
///+class Foo;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
no_fwd_decl_include should add these lines:
|
|
|
|
class Foo;
|
|
|
|
|
|
|
|
no_fwd_decl_include should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for no_fwd_decl_include:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
class Foo;
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'no_fwd_decl_include': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddIncludeToContentlessFile(self):
|
|
|
|
"""Tests we add an #include ok to a basically empty file.."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
///+#include <stdio.h>
|
|
|
|
///+#include "used.h"
|
|
|
|
///+
|
|
|
|
///+class Foo;
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
no_include should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
class Foo;
|
|
|
|
|
|
|
|
no_include should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for no_include:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
class Foo;
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'no_include': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddIncludeToEmptyFile(self):
|
2011-04-27 00:08:52 +01:00
|
|
|
"""Tests we add an #include ok to an empty file.."""
|
2011-02-04 22:28:15 +00:00
|
|
|
infile = ''
|
|
|
|
iwyu_output = """\
|
|
|
|
empty_file should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
class Foo;
|
|
|
|
|
|
|
|
empty_file should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for empty_file:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
class Foo;
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'empty_file': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-27 00:26:53 +01:00
|
|
|
def testAddIncludeToOnlyOneContentfulLineFile(self):
|
|
|
|
"""Prevent regression when the only contentful line was the last."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
///+
|
|
|
|
///+#include <stdio.h>
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
only_one_contentful_line.c should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
only_one_contentful_line.c should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for only_one_contentful_line.c:
|
|
|
|
#include <stdio.h>
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'only_one_contentful_line.c': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-14 05:47:42 +01:00
|
|
|
def testCommentsAtEndOfFile(self):
|
|
|
|
"""Tests we don't crash if a file ends with #includs and then a comment."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
const int kFoo = 5; // make sure we don't just insert at the beginning
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+
|
|
|
|
///+class Foo;
|
|
|
|
// Comments, and then...nothing
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
comments_at_end_of_file should add these lines:
|
|
|
|
class Foo;
|
|
|
|
|
|
|
|
comments_at_end_of_file should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for comments_at_end_of_file:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
class Foo;
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'comments_at_end_of_file': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testAddSystemIncludeToFileWithoutAny(self):
|
|
|
|
"""Tests we add a system #include to a non-sys location when needed."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#ifdef HAVE_TYPE_TRAITS_H
|
|
|
|
#include <type_traits.h>
|
|
|
|
#endif
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
system_include should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
system_include should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for system_include:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'system_include': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddNonSystemHeaderUnderMainCUHeader(self):
|
|
|
|
"""Tests we distinguish main-cu headers from other non-system headers."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
///+#include "main_cu.h"
|
|
|
|
#include "main_cu-inl.h"
|
|
|
|
///-
|
|
|
|
#include <stdio.h>
|
|
|
|
///+#include <stdlib.h>
|
|
|
|
#ifdef WINDOWS
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
main_cu_test.cc should add these lines:
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "main_cu.h"
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
main_cu_test.cc should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for main_cu_test.cc:
|
|
|
|
#include "main_cu.h"
|
|
|
|
#include "main_cu-inl.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'main_cu_test.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddWithNearestIncludes(self):
|
|
|
|
"""Tests we add "includes" with <includes> when there's a choice."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "nearest_include.h"
|
|
|
|
|
|
|
|
static int x = 6;
|
|
|
|
#include <stdio.h>
|
|
|
|
///+#include "used.h"
|
|
|
|
|
|
|
|
static int y = 7;
|
|
|
|
class Foo;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
nearest_include.cc should add these lines:
|
|
|
|
#include "used.h"
|
|
|
|
|
|
|
|
nearest_include.cc should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for nearest_include.cc:
|
|
|
|
#include "nearest_include.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
class Foo; // lines 9-9
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'nearest_include.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-14 05:47:42 +01:00
|
|
|
def testFalseAlarmHeaderGuard(self):
|
|
|
|
"""Tests we calculate top-level-ness even in face of a fake header-guard."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "nearest_toplevel_include.h"
|
|
|
|
|
|
|
|
static int x = 6;
|
|
|
|
#include <stdio.h>
|
|
|
|
///+#include "used.h"
|
|
|
|
|
|
|
|
#ifndef MAP_ANONYMOUS // This is the fake header guard!
|
|
|
|
# define MAP_ANONYMOUS MAP_ANON
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef FOO
|
|
|
|
#include <foo.h>
|
|
|
|
#endif
|
|
|
|
#if defined(BAR)
|
|
|
|
#include <bar.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int y = 7;
|
|
|
|
class Foo;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
nearest_toplevel_include.cc should add these lines:
|
|
|
|
#include "used.h"
|
|
|
|
|
|
|
|
nearest_toplevel_include.cc should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for nearest_toplevel_include.cc:
|
|
|
|
#include "nearest_toplevel_include.h"
|
|
|
|
#include <bar.h>
|
|
|
|
#include <foo.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
class Foo; // lines 9-9
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'nearest_toplevel_include.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testAddIncludeAfterHeaderGuard(self):
|
|
|
|
"""Test that we are willing to insert .h's inside a header guard."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#ifndef SIMPLE_H_
|
|
|
|
#define SIMPLE_H_
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
simple.h should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
simple.h should remove these lines:
|
|
|
|
- #include <notused.h> // lines 6-6
|
|
|
|
|
|
|
|
The full include-list for simple.h:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'simple.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2015-01-30 20:27:19 +00:00
|
|
|
def testAddIncludeAfterSoloPragmaOnce(self):
|
|
|
|
"""Test that we are willing to insert .h's after #pragma once."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
pragma_once.h should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
pragma_once.h should remove these lines:
|
|
|
|
- #include <notused.h> // lines 5-5
|
|
|
|
|
|
|
|
The full include-list for pragma_once.h:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'pragma_once.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddIncludeAfterPragmaOnceWithHeaderGuard(self):
|
|
|
|
"""Test that we are willing to insert .h's after #pragma once and header
|
|
|
|
guard."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#ifndef PRAGMA_ONCE_H_
|
|
|
|
#define PRAGMA_ONCE_H_
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
pragma_once_with_guard.h should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
pragma_once_with_guard.h should remove these lines:
|
|
|
|
- #include <notused.h> // lines 7-7
|
|
|
|
|
|
|
|
The full include-list for pragma_once_with_guard.h:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'pragma_once_with_guard.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddIncludeAfterEarlyPragmaOnce(self):
|
|
|
|
"""Test that we are willing to insert .h's after early #pragma once."""
|
|
|
|
infile = """\
|
|
|
|
#pragma once
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
early_pragma_once.h should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
early_pragma_once.h should remove these lines:
|
|
|
|
- #include <notused.h> // lines 4-4
|
|
|
|
|
|
|
|
The full include-list for early_pragma_once.h:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'early_pragma_once.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddIncludeAfterEarlyPragmaOnceWithHeaderGuard(self):
|
|
|
|
"""Test that we are willing to insert .h's after early #pragma once and
|
|
|
|
header guard."""
|
|
|
|
infile = """\
|
|
|
|
#pragma once
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#ifndef PRAGMA_ONCE_H_
|
|
|
|
#define PRAGMA_ONCE_H_
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
early_pragma_once_with_guard.h should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
early_pragma_once_with_guard.h should remove these lines:
|
|
|
|
- #include <notused.h> // lines 7-7
|
|
|
|
|
|
|
|
The full include-list for early_pragma_once_with_guard.h:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'early_pragma_once_with_guard.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddIncludeAfterWeirdPragmaOnce(self):
|
|
|
|
"""Test that we are willing to insert .h's after creatively formatted
|
|
|
|
#pragma once."""
|
|
|
|
infile = """\
|
|
|
|
# pragma once
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
weird_pragma_once.h should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
weird_pragma_once.h should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for weird_pragma_once.h:
|
|
|
|
#include <stdio.h>
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'weird_pragma_once.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddIncludeBeforePragmaMessage(self):
|
|
|
|
"""Test that non-once #pragmas are pushed after the #includes."""
|
|
|
|
infile = """\
|
|
|
|
///+#include <stdio.h>
|
|
|
|
///+
|
|
|
|
#pragma message "Hello world!"
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
weird_pragma_once.h should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
weird_pragma_once.h should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for weird_pragma_once.h:
|
|
|
|
#include <stdio.h>
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'weird_pragma_once.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testAddIncludeAfterWeirdHeaderGuard(self):
|
|
|
|
"""Test that we are willing to insert .h's inside a non-standard h-guard."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#if ! defined (SIMPLE_H_)
|
|
|
|
#define SIMPLE_H_
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
simple.h should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
simple.h should remove these lines:
|
|
|
|
- #include <notused.h> // lines 6-6
|
|
|
|
|
|
|
|
The full include-list for simple.h:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'simple.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-14 05:47:42 +01:00
|
|
|
def testAddIncludeAfterHeaderGuardLikeIfdef(self):
|
|
|
|
"""Test that we are willing to insert .h's inside a h-guard-*like* line."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#ifdef __linux // serves the same role as a header guard
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Comments are allowed after the header guard.
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
os_header_guard.h should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
os_header_guard.h should remove these lines:
|
|
|
|
- #include <notused.h> // lines 5-5
|
|
|
|
|
|
|
|
The full include-list for os_header_guard.h:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'os_header_guard.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddIncludeAfterHeaderGuardButBeforeComments(self):
|
|
|
|
"""Test that we introduce new #includes right after a header guard."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#ifndef SIMPLE_WITH_COMMENT_H_
|
|
|
|
#define SIMPLE_WITH_COMMENT_H_
|
|
|
|
|
|
|
|
///+#include <stdio.h>
|
|
|
|
///+#include "used.h"
|
|
|
|
///+
|
|
|
|
// This is a comment
|
|
|
|
void ForThisFunction();
|
|
|
|
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
simple_with_comment.h should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
|
|
|
|
simple_with_comment.h should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for simple_with_comment.h:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'simple_with_comment.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-09-20 12:44:55 +01:00
|
|
|
def testIdentifyingHeaderGuardLines(self):
|
|
|
|
"""Test that not all #defines look like header guards."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#ifndef IDENTIFYING_HEADER_GUARD_LINES_H_
|
|
|
|
#define IDENTIFYING_HEADER_GUARD_LINES_H_
|
|
|
|
|
|
|
|
namespace foo {
|
|
|
|
///+namespace bar {
|
|
|
|
///+class Baz;
|
|
|
|
///+} // namespace bar
|
|
|
|
///+
|
2018-07-12 00:20:20 +01:00
|
|
|
// The namespace decl should come before this #define, not after.
|
|
|
|
// It will, unless we wrongly say the #define is a header-guard define.
|
2011-09-20 12:44:55 +01:00
|
|
|
#define NOT_A_HEADER_GUARD_LINE 1
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
identifying_header_guard_lines.h should add these lines:
|
|
|
|
namespace foo { namespace bar { class Baz; } }
|
|
|
|
|
|
|
|
identifying_header_guard_lines.h should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for identifying_header_guard_lines.h:
|
|
|
|
namespace foo { namespace bar { class Baz; } }
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'identifying_header_guard_lines.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testIncludeOfCcFile(self):
|
|
|
|
"""Test that iwyu leaves .cc #includes alone."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int kFoo = 5;
|
|
|
|
|
|
|
|
#include "not_mentioned.cc"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
cc_include should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
cc_include should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for cc_include:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'cc_include': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testCommentsBeforeIncludeLines(self):
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+// This is the first include.
|
|
|
|
///+// Or it will be, after we reorder.
|
|
|
|
///+#include <stdio.h>
|
|
|
|
// This is the second include.
|
|
|
|
// Or *it* will be, after we reorder.
|
|
|
|
#include "used.h"
|
|
|
|
// This is the first include. ///-
|
|
|
|
// Or it will be, after we reorder. ///-
|
|
|
|
#include <stdio.h> ///-
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
comments_with_includes should add these lines:
|
|
|
|
|
|
|
|
comments_with_includes should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for comments_with_includes:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'comments_with_includes': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2019-01-16 22:57:50 +00:00
|
|
|
def testRemoveDuplicateIncludes(self):
|
2011-02-04 22:28:15 +00:00
|
|
|
"""Tests we uniquify if an #include is in there twice."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
#include "used.h" // same line even though it has a comment ///-
|
|
|
|
// Even though these two comment-lines are the same, they won't get de-duped.
|
|
|
|
// Even though these two comment-lines are the same, they won't get de-duped.
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
// But keep this one because it's in an #ifdef.
|
|
|
|
#include "used.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
2019-01-16 22:57:50 +00:00
|
|
|
remove_duplicate_includes should add these lines:
|
2011-02-04 22:28:15 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2019-01-16 22:57:50 +00:00
|
|
|
remove_duplicate_includes should remove these lines:
|
2011-02-04 22:28:15 +00:00
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
2019-01-16 22:57:50 +00:00
|
|
|
The full include-list for remove_duplicate_includes:
|
2011-02-04 22:28:15 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
2019-01-16 22:57:50 +00:00
|
|
|
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})
|
2011-02-04 22:28:15 +00:00
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2020-03-10 19:32:46 +00:00
|
|
|
def testDontRemoveSimilarNestedDeclarations(self):
|
|
|
|
"""Tests we don't accidentally think repeated nested forward declarations
|
|
|
|
are dupes."""
|
|
|
|
infile = """\
|
|
|
|
#include <notused.h> ///-
|
|
|
|
|
|
|
|
class A {
|
|
|
|
class Inner;
|
|
|
|
};
|
|
|
|
|
|
|
|
class B {
|
|
|
|
class Inner;
|
|
|
|
};
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
dont_remove_similar_nested should add these lines:
|
|
|
|
|
|
|
|
dont_remove_similar_nested should remove these lines:
|
|
|
|
- #include <notused.h> // lines 1-1
|
|
|
|
|
|
|
|
The full include-list for dont_remove_similar_nested:
|
|
|
|
class A::Inner; // lines 4-4
|
|
|
|
class B::Inner; // lines 8-8
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'dont_remove_similar_nested': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testNestedNamespaces(self):
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
///+#include <stdio.h>
|
|
|
|
///+
|
|
|
|
namespace X {
|
|
|
|
class OneA
|
|
|
|
///+
|
|
|
|
namespace Y {
|
|
|
|
///+class TwoA;
|
|
|
|
class TwoB;
|
|
|
|
class TwoA; ///-
|
|
|
|
}}
|
|
|
|
class Toplevel;
|
|
|
|
///-
|
|
|
|
namespace A { ///-
|
|
|
|
namespace B { namespace C { ///-
|
|
|
|
class Delete1; ///-
|
|
|
|
}}} ///-
|
|
|
|
///-
|
|
|
|
namespace A { namespace B { class Delete2; } } ///-
|
2011-04-27 00:05:25 +01:00
|
|
|
///-
|
|
|
|
namespace A { ///-
|
|
|
|
namespace B { ///-
|
|
|
|
class Delete3; ///-
|
|
|
|
} ///-
|
|
|
|
} // namespace A ///-
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
many_namespaces should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
many_namespaces should remove these lines:
|
|
|
|
- class Delete1; // lines 13-13
|
|
|
|
- class Delete2; // lines 16-16
|
2011-04-27 00:05:25 +01:00
|
|
|
- class Delete3; // lines 20-20
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
The full include-list for many_namespaces:
|
|
|
|
#include <stdio.h>
|
|
|
|
class Toplevel; // lines 9-9
|
|
|
|
class TwoA; // lines 7-7
|
|
|
|
class TwoB; // lines 6-6
|
|
|
|
class OneA; // lines 4-4
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'many_namespaces': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testDoNotInsertIncludeIntoAClass(self):
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
///+#include <stdio.h>
|
|
|
|
///+
|
|
|
|
class Foo {
|
|
|
|
};
|
|
|
|
|
|
|
|
class Bar {
|
|
|
|
class FwdDecl;
|
|
|
|
|
|
|
|
FwdDecl* f;
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
include_not_in_class should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
include_not_in_class should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for include_not_in_class:
|
|
|
|
#include <stdio.h>
|
|
|
|
class FwdDecl; // lines 7-7
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'include_not_in_class': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testIdenticalForwardDeclaredNamesInDifferentNamespaces(self):
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
2011-05-04 19:33:53 +01:00
|
|
|
///+namespace ns1 {
|
|
|
|
///+class ForwardDeclared;
|
|
|
|
///+} // namespace ns1
|
|
|
|
///+namespace ns2 {
|
|
|
|
///+class ForwardDeclared;
|
|
|
|
///+} // namespace ns2
|
2011-02-04 22:28:15 +00:00
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
identical_names should add these lines:
|
2011-05-04 19:33:53 +01:00
|
|
|
namespace ns1 { class ForwardDeclared; }
|
|
|
|
namespace ns2 { class ForwardDeclared; }
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
identical_names should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for identical_names:
|
2011-05-04 19:33:53 +01:00
|
|
|
namespace ns1 { class ForwardDeclared; }
|
|
|
|
namespace ns2 { class ForwardDeclared; }
|
2011-02-04 22:28:15 +00:00
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'identical_names': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testIterativeNamespaceDelete(self):
|
|
|
|
"""Tests deleting a namespace with an emptied #ifdef inside it."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
///-
|
|
|
|
namespace foo { ///-
|
|
|
|
#ifdef FWD_DECL ///-
|
|
|
|
class Bar; ///-
|
|
|
|
#endif ///-
|
|
|
|
} ///-
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
iterative_namespace should add these lines:
|
|
|
|
|
|
|
|
iterative_namespace should remove these lines:
|
|
|
|
- class Bar; // lines 5-5
|
|
|
|
|
2018-06-11 22:35:21 +01:00
|
|
|
The full include-list for iterative_namespace:
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'iterative_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testIterativeAllmanNamespaceDelete(self):
|
|
|
|
"""Tests deleting an Allman namespace with an emptied #ifdef inside it."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
///-
|
|
|
|
namespace foo ///-
|
|
|
|
{ ///-
|
|
|
|
#ifdef FWD_DECL ///-
|
|
|
|
class Bar; ///-
|
|
|
|
#endif ///-
|
|
|
|
} ///-
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
iterative_namespace should add these lines:
|
|
|
|
|
|
|
|
iterative_namespace should remove these lines:
|
|
|
|
- class Bar; // lines 6-6
|
|
|
|
|
|
|
|
The full include-list for iterative_namespace:
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'iterative_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testIterativeMixedNamespaceDelete(self):
|
|
|
|
"""Tests deleting a namespace with mixed braces with an emptied #ifdef inside it."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
///-
|
|
|
|
namespace foo { namespace baz ///-
|
|
|
|
{ ///-
|
|
|
|
#ifdef FWD_DECL ///-
|
|
|
|
class Bar; ///-
|
|
|
|
#endif ///-
|
|
|
|
} ///-
|
|
|
|
} ///-
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
iterative_namespace should add these lines:
|
|
|
|
|
|
|
|
iterative_namespace should remove these lines:
|
|
|
|
- class Bar; // lines 6-6
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
The full include-list for iterative_namespace:
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'iterative_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testIterativeIfdefDelete(self):
|
|
|
|
"""Tests deleting an ifdef with an emptied namespace inside it."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
///-
|
|
|
|
#ifdef FWD_DECL ///-
|
|
|
|
namespace foo { ///-
|
|
|
|
class Bar; ///-
|
|
|
|
} ///-
|
|
|
|
#endif ///-
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
iterative_ifdef should add these lines:
|
|
|
|
|
|
|
|
iterative_ifdef should remove these lines:
|
|
|
|
- class Bar; // lines 5-5
|
|
|
|
|
|
|
|
The full include-list for iterative_ifdef:
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'iterative_ifdef': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testOutOfRangeLineNumber(self):
|
|
|
|
"""Test we skip editing completely if iwyu has a really big line number."""
|
|
|
|
# fix_includes skips the file-editing if it detects a problem, as
|
|
|
|
# in this test case. The way that skipping is evidenced in the
|
|
|
|
# test, is the output is empty.
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010 ///-
|
|
|
|
///-
|
|
|
|
#include <notused.h> ///-
|
|
|
|
#include "used.h" ///-
|
|
|
|
///-
|
|
|
|
int main() { return 0; } ///-
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
out_of_range should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
out_of_range should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
- #include <bignumber.h> // lines 3000-3000
|
|
|
|
|
|
|
|
The full include-list for out_of_range:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'out_of_range': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testDeleteExtraneousBlankLines(self):
|
|
|
|
"""Test we delete blank lines around deleted spans correctly."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
class Foo { };
|
|
|
|
///-
|
|
|
|
class Bar; ///-
|
|
|
|
|
|
|
|
|
|
|
|
class Baz { };
|
|
|
|
|
|
|
|
|
|
|
|
class Bang; ///-
|
|
|
|
///-
|
|
|
|
class Qux { };
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
extraneous_blank_lines should add these lines:
|
|
|
|
|
|
|
|
extraneous_blank_lines should remove these lines:
|
|
|
|
- class Bar; // lines 5-5
|
|
|
|
- class Bang; // lines 11-11
|
|
|
|
|
|
|
|
The full include-list for extraneous_blank_lines:
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'extraneous_blank_lines': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testKeepNolintComment(self):
|
|
|
|
"""Test we keep a nolint comment."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "bar.h" // NOLINT(iwyu)
|
|
|
|
#include "baz.h" // NOLINT(iwyu): blah blah
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
keep_nolint should add these lines:
|
|
|
|
|
|
|
|
keep_nolint should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for keep_nolint:
|
|
|
|
#include "bar.h" // lines 3-3
|
|
|
|
#include "baz.h" // lines 4-4
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
|
|
|
|
self.RegisterFileContents({'keep_nolint': infile})
|
|
|
|
# No files are written, because there are no changes.
|
|
|
|
self.ProcessAndTest(iwyu_output, unedited_files=['keep_nolint'])
|
|
|
|
|
|
|
|
def testKeepNolintCommentInNocommentMode(self):
|
|
|
|
"""Test we keep a nolint comment even with --nocomments."""
|
2011-04-12 05:55:05 +01:00
|
|
|
self.flags.comments = False
|
2011-02-04 22:28:15 +00:00
|
|
|
self.testKeepNolintComment()
|
|
|
|
|
|
|
|
# Test the IWYUOutputParser method _MatchSectionHeading.
|
|
|
|
|
|
|
|
def testIWYUOutputParserMatchSectionHeadingSuccess(self):
|
|
|
|
parser = fix_includes.IWYUOutputParser()
|
|
|
|
self.assertEqual(None, parser.current_section)
|
|
|
|
self.assertEqual('<unknown file>', parser.filename)
|
|
|
|
|
2015-05-11 21:39:15 +01:00
|
|
|
self.assertTrue(parser._ProcessOneLine(''))
|
2011-02-04 22:28:15 +00:00
|
|
|
self.assertEqual(None, parser.current_section)
|
|
|
|
self.assertEqual('<unknown file>', parser.filename)
|
|
|
|
|
2015-05-11 21:39:15 +01:00
|
|
|
self.assertTrue(parser._ProcessOneLine(
|
2011-02-04 22:28:15 +00:00
|
|
|
'myfile.cc should add these lines:'))
|
|
|
|
self.assertEqual(parser._ADD_SECTION_RE, parser.current_section)
|
|
|
|
self.assertEqual('add', parser._RE_TO_NAME[parser.current_section])
|
|
|
|
self.assertEqual('myfile.cc', parser.filename)
|
|
|
|
|
2015-05-11 21:39:15 +01:00
|
|
|
self.assertTrue(parser._ProcessOneLine(
|
2011-02-04 22:28:15 +00:00
|
|
|
'myfile.cc should remove these lines:'))
|
|
|
|
self.assertEqual(parser._REMOVE_SECTION_RE, parser.current_section)
|
|
|
|
self.assertEqual('remove', parser._RE_TO_NAME[parser.current_section])
|
|
|
|
self.assertEqual('myfile.cc', parser.filename)
|
|
|
|
|
2015-05-11 21:39:15 +01:00
|
|
|
self.assertTrue(parser._ProcessOneLine(
|
2011-02-04 22:28:15 +00:00
|
|
|
'The full include-list for myfile.cc:'))
|
|
|
|
self.assertEqual(parser._TOTAL_SECTION_RE, parser.current_section)
|
|
|
|
self.assertEqual('total', parser._RE_TO_NAME[parser.current_section])
|
|
|
|
self.assertEqual('myfile.cc', parser.filename)
|
|
|
|
|
2015-05-11 21:39:15 +01:00
|
|
|
self.assertTrue(not parser._ProcessOneLine('---'))
|
2011-02-04 22:28:15 +00:00
|
|
|
self.assertEqual(parser._SECTION_END_RE, parser.current_section)
|
|
|
|
self.assertEqual('end', parser._RE_TO_NAME[parser.current_section])
|
|
|
|
self.assertEqual('myfile.cc', parser.filename)
|
|
|
|
|
2017-07-02 11:03:38 +01:00
|
|
|
def testIWYUOutputParserMatchSectionHeadingWindowsPaths(self):
|
|
|
|
# Windows path names can contain the ':' character, so make sure that parses
|
|
|
|
# correctly. IWYU uses POSIX-style forward slashes consistently, so follow
|
|
|
|
# suit here.
|
|
|
|
parser = fix_includes.IWYUOutputParser()
|
|
|
|
self.assertTrue(parser._ProcessOneLine(
|
|
|
|
'C:/src/myfile.cc should add these lines:'))
|
|
|
|
self.assertEqual(parser._ADD_SECTION_RE, parser.current_section)
|
|
|
|
self.assertEqual('add', parser._RE_TO_NAME[parser.current_section])
|
|
|
|
self.assertEqual('C:/src/myfile.cc', parser.filename)
|
|
|
|
|
|
|
|
self.assertTrue(parser._ProcessOneLine(
|
|
|
|
'C:/src/myfile.cc should remove these lines:'))
|
|
|
|
self.assertEqual(parser._REMOVE_SECTION_RE, parser.current_section)
|
|
|
|
self.assertEqual('remove', parser._RE_TO_NAME[parser.current_section])
|
|
|
|
self.assertEqual('C:/src/myfile.cc', parser.filename)
|
|
|
|
|
|
|
|
self.assertTrue(parser._ProcessOneLine(
|
|
|
|
'The full include-list for C:/src/myfile.cc:'))
|
|
|
|
self.assertEqual(parser._TOTAL_SECTION_RE, parser.current_section)
|
|
|
|
self.assertEqual('total', parser._RE_TO_NAME[parser.current_section])
|
|
|
|
self.assertEqual('C:/src/myfile.cc', parser.filename)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testIWYUOutputParserProcessOneLineProcessNoEditsHeader(self):
|
|
|
|
parser = fix_includes.IWYUOutputParser()
|
|
|
|
line = '(myfile.cc has correct #includes/fwd-decls)'
|
2015-05-11 21:39:15 +01:00
|
|
|
self.assertTrue(not parser._ProcessOneLine(line))
|
2011-02-04 22:28:15 +00:00
|
|
|
self.assertEqual(parser._NO_EDITS_RE, parser.current_section)
|
|
|
|
self.assertEqual('no_edits', parser._RE_TO_NAME[parser.current_section])
|
|
|
|
self.assertEqual('myfile.cc', parser.filename)
|
|
|
|
|
|
|
|
def testIWYUOutputParserProcessOneLineAddNotSeenFirst(self):
|
|
|
|
parser = fix_includes.IWYUOutputParser()
|
|
|
|
self.assertRaises(fix_includes.FixIncludesError,
|
|
|
|
parser._ProcessOneLine,
|
|
|
|
'myfile.cc should remove these lines:')
|
|
|
|
|
|
|
|
def testIWYUOutputParserProcessOneLineOutOfOrder(self):
|
|
|
|
parser = fix_includes.IWYUOutputParser()
|
2015-05-11 21:39:15 +01:00
|
|
|
self.assertTrue(parser._ProcessOneLine(
|
2011-02-04 22:28:15 +00:00
|
|
|
'myfile.cc should add these lines:'))
|
|
|
|
self.assertRaises(fix_includes.FixIncludesError,
|
|
|
|
parser._ProcessOneLine,
|
|
|
|
'The full include-list for myfile.cc:')
|
|
|
|
|
|
|
|
def testIWYUOutputParserProcessOneLineIncorrectFilename(self):
|
|
|
|
parser = fix_includes.IWYUOutputParser()
|
2015-05-11 21:39:15 +01:00
|
|
|
self.assertTrue(parser._ProcessOneLine(
|
2011-02-04 22:28:15 +00:00
|
|
|
'myfile.cc should add these lines:'))
|
|
|
|
self.assertRaises(fix_includes.FixIncludesError,
|
|
|
|
parser._ProcessOneLine,
|
|
|
|
'not_myfile.cc should remove these lines:')
|
|
|
|
|
|
|
|
def testIWYUOutputParserProcessOneLineNoMatcher(self):
|
|
|
|
parser = fix_includes.IWYUOutputParser()
|
|
|
|
# We successfully process this not-in-any-section line, but update no data.
|
2015-05-11 21:39:15 +01:00
|
|
|
self.assertTrue(parser._ProcessOneLine('#include <foo>'))
|
2011-02-04 22:28:15 +00:00
|
|
|
self.assertEqual(None, parser.current_section)
|
|
|
|
self.assertEqual('<unknown file>', parser.filename)
|
|
|
|
|
|
|
|
def testIWYUOutputParserSuccess(self):
|
|
|
|
"""Tests the IWYUOutputParser method ParseOneRecord."""
|
|
|
|
iwyu_output = """\
|
|
|
|
simple should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
namespace ns {class ForwardDeclared;}
|
|
|
|
|
|
|
|
simple should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for simple:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
namespace ns {class ForwardDeclared;}
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
parser = fix_includes.IWYUOutputParser()
|
|
|
|
record = parser.ParseOneRecord(iwyu_output.splitlines(), self.flags)
|
|
|
|
|
|
|
|
self.assertEqual('simple', record.filename)
|
2015-05-11 21:39:15 +01:00
|
|
|
self.assertSetEqual(set([3]), record.lines_to_delete)
|
|
|
|
self.assertSetEqual(set(('#include <stdio.h>',
|
|
|
|
'#include "used2.h"',
|
|
|
|
'namespace ns {class ForwardDeclared;}')),
|
|
|
|
record.includes_and_forward_declares_to_add)
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
def testIWYUOutputParserRemoveLineNoComment(self):
|
|
|
|
iwyu_output = """\
|
|
|
|
no_comment should add these lines:
|
|
|
|
|
|
|
|
no_comment should remove these lines:
|
|
|
|
- #include <notused.h>
|
|
|
|
|
|
|
|
The full include-list for no_key:
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
parser = fix_includes.IWYUOutputParser()
|
|
|
|
self.assertRaises(fix_includes.FixIncludesError,
|
|
|
|
parser.ParseOneRecord,
|
|
|
|
iwyu_output.splitlines(),
|
|
|
|
self.flags)
|
|
|
|
|
|
|
|
def testFileSpecifiedOnCommandline(self):
|
|
|
|
"""Test we limit editing to files specified on the commandline."""
|
|
|
|
changed_infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
unchanged_infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h>
|
|
|
|
#include "used.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
changed should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
changed should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for changed:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
# Have the exact same iwyu output for 'unchanged' as for 'changed'.
|
|
|
|
iwyu_output += iwyu_output.replace('changed', 'unchanged')
|
|
|
|
|
|
|
|
self.RegisterFileContents({'changed': changed_infile,
|
|
|
|
'unchanged': unchanged_infile})
|
|
|
|
# unchanged should not be edited, since it is not listed on the 'cmdline'.
|
|
|
|
self.ProcessAndTest(iwyu_output, cmdline_files=['changed'],
|
|
|
|
unedited_files=['unchanged'])
|
|
|
|
|
2011-04-13 04:11:19 +01:00
|
|
|
def testIgnoreRe(self):
|
|
|
|
"""Test the behavior of the --ignore_re flag."""
|
|
|
|
changed_infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
unchanged_infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h>
|
|
|
|
#include "used.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
changed should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
changed should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for changed:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
# Have the exact same iwyu output for 'unchanged' as for 'changed'.
|
|
|
|
iwyu_output += iwyu_output.replace('changed', 'unchanged')
|
|
|
|
|
|
|
|
self.RegisterFileContents({'changed': changed_infile,
|
|
|
|
'unchanged': unchanged_infile})
|
|
|
|
# unchanged should not be edited, since it matches ignore_re.
|
|
|
|
self.flags.ignore_re = 'nch'
|
|
|
|
self.ProcessAndTest(iwyu_output, unedited_files=['unchanged'])
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2018-06-14 15:46:01 +01:00
|
|
|
def testOnlyRe(self):
|
|
|
|
"""Test the behavior of the --only_re flag."""
|
|
|
|
changed_infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
unchanged_infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h>
|
|
|
|
#include "used.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
output should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
output should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for output:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
# Have the exact same iwyu output for 'alice.cpp' as for 'bob.cpp'.
|
|
|
|
iwyu_output = (iwyu_output.replace('output', 'alice.cpp') +
|
|
|
|
iwyu_output.replace('output', 'bob.cpp'))
|
|
|
|
|
|
|
|
self.RegisterFileContents({'alice.cpp': changed_infile,
|
|
|
|
'bob.cpp': unchanged_infile})
|
|
|
|
# only alice.cpp should be edited, since it matches only_re.
|
|
|
|
self.flags.only_re = 'lice'
|
|
|
|
self.ProcessAndTest(iwyu_output, unedited_files=['bob.cpp'])
|
|
|
|
|
|
|
|
def testIgnoreAndOnlyRe(self):
|
|
|
|
"""Test the behavior of both --ignore_re and --only_re flags."""
|
|
|
|
changed_infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h> ///-
|
|
|
|
///+#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
///+#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
unchanged_infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h>
|
|
|
|
#include "used.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
output should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
output should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for output:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
# Have the exact same iwyu output for 'alice.cpp' as for 'bob.cpp' and 'charlie.cpp'
|
|
|
|
iwyu_output = (iwyu_output.replace('output', 'alice.cpp') +
|
|
|
|
iwyu_output.replace('output', 'bob.cpp') +
|
|
|
|
iwyu_output.replace('output', 'charlie.cpp'))
|
|
|
|
|
|
|
|
self.RegisterFileContents({'alice.cpp': changed_infile,
|
|
|
|
'bob.cpp': unchanged_infile,
|
|
|
|
'charlie.cpp': changed_infile})
|
|
|
|
# only alice.cpp should be edited, since it matches only_re and not ignore_re
|
|
|
|
self.flags.only_re = 'li'
|
|
|
|
self.flags.ignore_re = 'char'
|
|
|
|
self.ProcessAndTest(iwyu_output, unedited_files=['bob.cpp', 'charlie.cpp'])
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testSortIncludes(self):
|
|
|
|
"""Test sorting includes only -- like running fix_includes.py -s."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
// This file is not used.
|
|
|
|
#include <notused.h>
|
|
|
|
|
|
|
|
// This file is not used either.
|
|
|
|
// It's not used.
|
|
|
|
// Not used at all.
|
|
|
|
#include <notused2.h>
|
|
|
|
|
|
|
|
#include "notused3.h"
|
|
|
|
|
|
|
|
// This comment should stay, it's not before an #include.
|
|
|
|
const int kInt = 5;
|
|
|
|
// This file is used.
|
|
|
|
// It's definitedly used.
|
|
|
|
#include "used.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
const int kInt2 = 6;
|
|
|
|
|
|
|
|
#include "foo.cc"
|
|
|
|
|
|
|
|
// This comment should stay, it's not before an #include.
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
// This file is not used.
|
|
|
|
#include <notused.h>
|
|
|
|
// This file is not used either.
|
|
|
|
// It's not used.
|
|
|
|
// Not used at all.
|
|
|
|
#include <notused2.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "notused3.h"
|
|
|
|
|
|
|
|
// This comment should stay, it's not before an #include.
|
|
|
|
const int kInt = 5;
|
|
|
|
#include <stdlib.h>
|
|
|
|
// This file is used.
|
|
|
|
// It's definitedly used.
|
|
|
|
#include "used.h"
|
|
|
|
|
|
|
|
const int kInt2 = 6;
|
|
|
|
|
|
|
|
#include "foo.cc"
|
|
|
|
|
|
|
|
// This comment should stay, it's not before an #include.
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'sort': infile})
|
2011-03-04 00:27:43 +00:00
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(['sort'], self.flags)
|
2019-01-23 17:43:06 +00:00
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
2011-02-04 22:28:15 +00:00
|
|
|
self.actual_after_contents)
|
2011-03-04 00:27:43 +00:00
|
|
|
self.assertEqual(1, num_files_modified)
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2011-04-27 00:08:52 +01:00
|
|
|
def testSortingMultipleFiles(self):
|
|
|
|
"""Tests passing more than one argument to SortIncludesInFiles()."""
|
|
|
|
infile1 = """\
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
"""
|
|
|
|
infile2 = """\
|
|
|
|
#include "z.h"
|
|
|
|
#include "y.h"
|
|
|
|
#include "x.y"
|
|
|
|
"""
|
|
|
|
|
|
|
|
expected_output = """\
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "x.y"
|
|
|
|
#include "y.h"
|
|
|
|
#include "z.h"
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'f1': infile1, 'f2': infile2})
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(['f1', 'f2'],
|
|
|
|
self.flags)
|
2019-01-23 17:43:06 +00:00
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
2011-04-27 00:08:52 +01:00
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(2, num_files_modified)
|
|
|
|
|
2011-03-04 00:27:43 +00:00
|
|
|
def testSortingIncludesAlreadySorted(self):
|
|
|
|
"""Tests sorting includes only, when includes are already sorted."""
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
namespace Foo; // fwd-decls are out of order, but sorter ignores them
|
|
|
|
|
|
|
|
namespace Bar;
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'sort_nosorting.h': infile})
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(['sort_nosorting.h'],
|
|
|
|
self.flags)
|
|
|
|
self.assertListEqual([], self.actual_after_contents)
|
|
|
|
self.assertEqual(0, num_files_modified)
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2011-04-12 06:02:20 +01:00
|
|
|
def testBarrierIncludes(self):
|
|
|
|
"""Tests that we correctly sort 'around' _BARRIER_INCLUDES."""
|
2011-04-12 05:59:54 +01:00
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <linux/a_stay_top.h>
|
|
|
|
#include <stdlib.h> ///-
|
|
|
|
#include <linux/can_sort_around_this_deleted_include> ///-
|
|
|
|
#include <stdio.h>
|
|
|
|
///+#include <stdlib.h>
|
|
|
|
#include "user/include.h"
|
|
|
|
///+#include "user/new_include.h"
|
|
|
|
#include <linux/c_stay_second.h>
|
|
|
|
#include <linux/b_stay_third.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <cpp_include>
|
|
|
|
///+#include <new_cpp_include>
|
|
|
|
#include <linux/d_stay_fourth.h>
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
2011-04-12 06:02:20 +01:00
|
|
|
barrier_includes.h should add these lines:
|
2011-04-12 05:59:54 +01:00
|
|
|
#include "user/new_include.h"
|
|
|
|
#include <new_cpp_include>
|
|
|
|
|
2011-04-12 06:02:20 +01:00
|
|
|
barrier_includes.h should remove these lines:
|
2011-04-12 05:59:54 +01:00
|
|
|
- #include <linux/can_sort_around_this_deleted_include> // lines 5-5
|
|
|
|
|
2011-04-12 06:02:20 +01:00
|
|
|
The full include-list for barrier_includes.h:
|
2011-04-12 05:59:54 +01:00
|
|
|
#include "user/include.h"
|
|
|
|
#include "user/new_include.h"
|
|
|
|
#include <cpp_include>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <linux/a_stay_top.h>
|
|
|
|
#include <linux/b_stay_third.h>
|
|
|
|
#include <linux/c_stay_second.h>
|
|
|
|
#include <linux/d_stay_fourth.h>
|
|
|
|
#include <new_cpp_include>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
---
|
|
|
|
"""
|
2011-04-12 06:02:20 +01:00
|
|
|
self.RegisterFileContents({'barrier_includes.h': infile})
|
2011-04-12 05:59:54 +01:00
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-07-07 18:02:06 +01:00
|
|
|
def testSortingMainCUIncludeInSameDirectory(self):
|
|
|
|
"""Check that we identify when first .h file is a main-cu #include."""
|
|
|
|
infile = """\
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "me/subdir0/foo.h"
|
|
|
|
#include "other/baz.h"
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
#include "me/subdir0/foo.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "other/baz.h"
|
2019-01-05 16:19:58 +00:00
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'me/subdir0/foo.cc': infile})
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(
|
|
|
|
['me/subdir0/foo.cc'], self.flags)
|
2019-01-23 17:43:06 +00:00
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
2019-01-05 16:19:58 +00:00
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(1, num_files_modified)
|
|
|
|
|
|
|
|
def testSortingMainCUIncludeViaPragma(self):
|
|
|
|
"""Check that we treat (potentially multiple) associated headers as
|
|
|
|
main-cu #includes."""
|
|
|
|
infile = """\
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "other/dir/bar.h" // IWYU pragma: associated
|
|
|
|
#include "other/baz.h" // IWYU pragma: associated
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
#include "other/baz.h" // IWYU pragma: associated
|
|
|
|
#include "other/dir/bar.h" // IWYU pragma: associated
|
|
|
|
#include <stdio.h>
|
2011-07-07 18:02:06 +01:00
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'me/subdir0/foo.cc': infile})
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(
|
|
|
|
['me/subdir0/foo.cc'], self.flags)
|
2019-01-23 17:43:06 +00:00
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
2011-07-07 18:02:06 +01:00
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(1, num_files_modified)
|
|
|
|
|
2017-06-30 10:19:26 +01:00
|
|
|
def testSortingMainCUIncludeWithUpperCaseH(self):
|
|
|
|
"""Check that we identify when first .H file is a main-cu #include."""
|
|
|
|
infile = """\
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "foo.H"
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
#include "foo.H"
|
|
|
|
#include <stdio.h>
|
2019-11-25 10:52:46 +00:00
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'foo.cc': infile})
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(
|
|
|
|
['foo.cc'], self.flags)
|
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(1, num_files_modified)
|
|
|
|
|
|
|
|
def testSortingMainCUIncludeWithHpp(self):
|
|
|
|
"""Check that we identify when first .hpp file is a main-cu #include."""
|
|
|
|
infile = """\
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "foo.hpp"
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
#include "foo.hpp"
|
|
|
|
#include <stdio.h>
|
2019-11-26 10:17:40 +00:00
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'foo.cc': infile})
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(
|
|
|
|
['foo.cc'], self.flags)
|
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(1, num_files_modified)
|
|
|
|
|
|
|
|
def testSortingMainCUIncludeWithMixedCaseInl(self):
|
|
|
|
"""Check that we identify when first -inl.hpp file with mixed case
|
|
|
|
is a main-cu #include."""
|
|
|
|
infile = """\
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "foo-InL.h"
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
#include "foo-InL.h"
|
|
|
|
#include <stdio.h>
|
2017-06-30 10:19:26 +01:00
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'foo.cc': infile})
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(
|
|
|
|
['foo.cc'], self.flags)
|
2019-01-23 17:43:06 +00:00
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
2017-06-30 10:19:26 +01:00
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(1, num_files_modified)
|
|
|
|
|
2011-07-07 18:02:06 +01:00
|
|
|
def testSortingMainCUIncludeInSameDirectoryWithInl(self):
|
|
|
|
"""Check that we identify when first -inl.h file is a main-cu #include."""
|
|
|
|
infile = """\
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "me/subdir0/foo-inl.h"
|
|
|
|
#include "other/baz.h"
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
#include "me/subdir0/foo-inl.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "other/baz.h"
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'me/subdir0/foo.cc': infile})
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(
|
|
|
|
['me/subdir0/foo.cc'], self.flags)
|
2019-01-23 17:43:06 +00:00
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
2011-07-07 18:02:06 +01:00
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(1, num_files_modified)
|
|
|
|
|
|
|
|
def testSortingMainCUIncludeInDifferentDirectory(self):
|
|
|
|
"""Check that we identify when first .h file is a main-cu #include."""
|
|
|
|
infile = """\
|
|
|
|
#include "me/subdir0/foo.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "other/baz.h"
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'me/other_subdir/foo.cc': infile})
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(
|
|
|
|
['me/other_subdir/foo.cc'], self.flags)
|
|
|
|
self.assertListEqual([], self.actual_after_contents)
|
|
|
|
self.assertEqual(0, num_files_modified)
|
|
|
|
|
|
|
|
def testSortingMainCUIncludeInDifferentDirectoryWhenNotFirst(self):
|
|
|
|
"""Check that we don't let second .h be a main-cu #include."""
|
|
|
|
infile = """\
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "me/subdir0/foo.h"
|
|
|
|
#include "other/baz.h"
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'me/other_subdir/foo.cc': infile})
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(
|
|
|
|
['me/other_subdir/foo.cc'], self.flags)
|
|
|
|
self.assertListEqual([], self.actual_after_contents)
|
|
|
|
self.assertEqual(0, num_files_modified)
|
|
|
|
|
2011-04-12 05:54:44 +01:00
|
|
|
def testSortingProjectIncludesAuto(self):
|
|
|
|
"""Check that project includes can be sorted separately."""
|
|
|
|
infile = """\
|
|
|
|
#include "me/subdir0/foo.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "me/subdir2/bar.h"
|
|
|
|
#include "me/subdir1/bar.h"
|
|
|
|
#include "me/subdir0/bar.h"
|
|
|
|
#include "other/baz.h"
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
#include "me/subdir0/foo.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "other/baz.h"
|
|
|
|
#include "me/subdir0/bar.h"
|
|
|
|
#include "me/subdir1/bar.h"
|
|
|
|
#include "me/subdir2/bar.h"
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'me/subdir0/foo.cc': infile})
|
|
|
|
self.flags.separate_project_includes = '<tld>'
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(['me/subdir0/foo.cc'],
|
|
|
|
self.flags)
|
2019-01-23 17:43:06 +00:00
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
2011-04-12 05:54:44 +01:00
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(1, num_files_modified)
|
|
|
|
|
|
|
|
def testSortingProjectIncludesUserSpecified(self):
|
|
|
|
"""Test user-specified project directory name."""
|
|
|
|
infile = """\
|
|
|
|
#include "me/subdir0/foo.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "me/subdir2/bar.h"
|
|
|
|
#include "me/subdir1/bar.h"
|
|
|
|
#include "me/subdir0/bar.h"
|
|
|
|
#include "other/baz.h"
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
#include "me/subdir0/foo.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "me/subdir1/bar.h"
|
|
|
|
#include "me/subdir2/bar.h"
|
|
|
|
#include "other/baz.h"
|
|
|
|
#include "me/subdir0/bar.h"
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'me/subdir0/foo.cc': infile})
|
|
|
|
self.flags.separate_project_includes = 'me/subdir0'
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(['me/subdir0/foo.cc'],
|
|
|
|
self.flags)
|
2019-01-23 17:43:06 +00:00
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
2011-04-12 05:54:44 +01:00
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(1, num_files_modified)
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
def testAddingNewIncludesAfterRemovingOldOnes(self):
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2008 Google Inc. All Rights Reserved.
|
|
|
|
// Author: zhifengc@google.com (Zhifeng Chen)
|
|
|
|
|
|
|
|
#ifndef STRUCTUREDSEARCH_COMMON_INTERNAL_DFS_H_
|
|
|
|
#define STRUCTUREDSEARCH_COMMON_INTERNAL_DFS_H_
|
|
|
|
|
|
|
|
#include "util/task/status.h" ///-
|
|
|
|
#include "strings/stringpiece.h" ///-
|
|
|
|
///+#include <string> // for string
|
|
|
|
///+#include "base/macros.h" // for DISALLOW_COPY_AND_ASSIGN
|
|
|
|
///+#include "base/scoped_ptr.h" // for scoped_ptr
|
|
|
|
|
|
|
|
class Query;
|
2011-04-12 05:54:21 +01:00
|
|
|
///+namespace util {
|
|
|
|
///+class Status;
|
2011-04-26 23:57:34 +01:00
|
|
|
///+} // namespace util
|
2011-02-04 22:28:15 +00:00
|
|
|
|
|
|
|
namespace structuredsearch {
|
|
|
|
|
|
|
|
///+class FieldSpecification;
|
|
|
|
class FieldTokenizer;
|
|
|
|
class FieldSpecification; ///-
|
|
|
|
class TokenizationSpec;
|
|
|
|
|
|
|
|
class QueryXlator { ... };
|
2011-04-14 05:47:42 +01:00
|
|
|
|
|
|
|
#endif // #define STRUCTUREDSEARCH_COMMON_INTERNAL_DFS_H_
|
2011-02-04 22:28:15 +00:00
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
structuredsearch/common/internal/query_field_xlate.h should add these lines:
|
|
|
|
#include <string> // for string
|
|
|
|
#include "base/macros.h" // for DISALLOW_COPY_AND_ASSIGN
|
|
|
|
#include "base/scoped_ptr.h" // for scoped_ptr
|
|
|
|
namespace util { class Status; }
|
|
|
|
|
|
|
|
structuredsearch/common/internal/query_field_xlate.h should remove these lines:
|
|
|
|
- #include "strings/stringpiece.h" // lines 8-8
|
|
|
|
- #include "util/task/status.h" // lines 7-7
|
|
|
|
|
|
|
|
The full include-list for structuredsearch/common/internal/query_field_xlate.h:
|
|
|
|
#include <string> // for string
|
|
|
|
#include "base/macros.h" // for DISALLOW_COPY_AND_ASSIGN
|
|
|
|
#include "base/scoped_ptr.h" // for scoped_ptr
|
|
|
|
class Query; // lines 10-10
|
|
|
|
namespace structuredsearch { class FieldSpecification; } // lines 15-15
|
|
|
|
namespace structuredsearch { class FieldTokenizer; } // lines 14-14
|
|
|
|
namespace structuredsearch { class TokenizationSpec; } // lines 16-16
|
|
|
|
namespace util { class Status; }
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents(
|
|
|
|
{'structuredsearch/common/internal/query_field_xlate.h': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
2011-04-27 00:08:52 +01:00
|
|
|
def testDryRun(self):
|
|
|
|
"""Tests that --dry_run mode does not modify files."""
|
|
|
|
self.flags.dry_run = True
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include <notused.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
dry_run should add these lines:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used2.h"
|
|
|
|
|
|
|
|
dry_run should remove these lines:
|
|
|
|
- #include <notused.h> // lines 3-3
|
|
|
|
|
|
|
|
The full include-list for dry_run:
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "used.h"
|
|
|
|
#include "used2.h"
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'dry_run': infile})
|
|
|
|
num_modified_files = fix_includes.ProcessIWYUOutput(
|
2016-03-22 12:33:54 +00:00
|
|
|
StringIO(iwyu_output), ['dry_run'], self.flags, None)
|
2011-04-27 00:08:52 +01:00
|
|
|
self.assertListEqual([], self.actual_after_contents)
|
2017-09-16 20:42:23 +01:00
|
|
|
self.assertEqual(1, num_modified_files)
|
2011-04-27 00:08:52 +01:00
|
|
|
|
2011-05-13 00:12:33 +01:00
|
|
|
def testAddForwardDeclareAndKeepIwyuNamespaceFormat(self):
|
|
|
|
"""Tests that --keep_iwyu_namespace_format writes namespace lines
|
|
|
|
using the IWYU one-line format.
|
|
|
|
Input code similar to case testAddForwardDeclareInNamespace."""
|
|
|
|
self.flags.keep_iwyu_namespace_format = True
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
///+namespace ns { class Foo; }
|
|
|
|
///+namespace ns { namespace ns2 { namespace ns3 { class Bar; } } }
|
|
|
|
///+namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } }
|
|
|
|
///+namespace ns { namespace ns4 { class Baz; } }
|
|
|
|
///+
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_declare_keep_iwyu_namespace should add these lines:
|
|
|
|
namespace ns { class Foo; }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class Bar; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } }
|
|
|
|
namespace ns { namespace ns4 { class Baz; } }
|
|
|
|
|
|
|
|
add_fwd_declare_keep_iwyu_namespace should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_declare_keep_iwyu_namespace:
|
|
|
|
#include "foo.h" // lines 3-3
|
|
|
|
namespace ns { class Foo; }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class Bar; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } }
|
|
|
|
namespace ns { namespace ns4 { class Baz; } }
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_declare_keep_iwyu_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output, expected_num_modified_files=1)
|
|
|
|
|
|
|
|
def testAddNestedForwardDeclaresWithKeepIwyuNamespaceFormat(self):
|
|
|
|
"""Tests that --keep_iwyu_namespace_format writes namespace lines
|
|
|
|
using the IWYU one-line format.
|
|
|
|
Input code similar to case
|
|
|
|
testAddForwardDeclareInsideNamespaceWithoutForwardDeclaresAlready."""
|
|
|
|
self.flags.keep_iwyu_namespace_format = True
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
class Bar;
|
|
|
|
///+class Foo;
|
|
|
|
///+namespace ns1 { class NsFoo; }
|
|
|
|
///+namespace ns1 { namespace ns2 { namespace ns3 { class NsBaz; } } }
|
|
|
|
///+namespace ns1 { namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } }
|
|
|
|
template <typename T> class Baz;
|
|
|
|
|
|
|
|
|
|
|
|
namespace ns {
|
2018-07-12 00:20:20 +01:00
|
|
|
///-
|
2011-05-13 00:12:33 +01:00
|
|
|
///+class NsFoo;
|
|
|
|
///+namespace ns2 { namespace ns3 { class NsBaz; } }
|
|
|
|
///+namespace ns2 { namespace ns3 { template <typename T> class NsBang; } }
|
|
|
|
///+
|
|
|
|
class NsBar;
|
|
|
|
|
|
|
|
namespace ns2 { // we sure do love nesting our namespaces!
|
|
|
|
|
|
|
|
int MyFunction() { }
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_decl_with_keep_iwyu_format should add these lines:
|
|
|
|
class Foo;
|
|
|
|
namespace ns { class NsFoo; }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class NsBaz; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } }
|
|
|
|
namespace ns1 { class NsFoo; }
|
|
|
|
namespace ns1 { namespace ns2 { namespace ns3 { class NsBaz; } } }
|
|
|
|
namespace ns1 { namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } }
|
|
|
|
|
|
|
|
add_fwd_decl_with_keep_iwyu_format should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_decl_with_keep_iwyu_format:
|
|
|
|
#include "foo.h" // lines 3-3
|
|
|
|
class Bar; // lines 5-5
|
|
|
|
class Foo;
|
|
|
|
namespace ns { class NsFoo; }
|
|
|
|
namespace ns { namespace ns2 { class NsBar; } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class NsBaz; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } }
|
|
|
|
namespace ns1 { class NsFoo; }
|
|
|
|
namespace ns1 { namespace ns2 { namespace ns3 { class NsBaz; } } }
|
|
|
|
namespace ns1 { namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } }
|
|
|
|
template <typename T> class Baz; // lines 6-6
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_decl_with_keep_iwyu_format': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output)
|
|
|
|
|
|
|
|
def testAddForwardDeclareInNamespaceWithKeepIwyuNamespaceFormat(self):
|
|
|
|
"""Tests that --keep_iwyu_namespace_format writes namespace lines
|
|
|
|
using the IWYU one-line format.
|
|
|
|
Input code similar to case testAddForwardDeclareInNamespace."""
|
|
|
|
self.flags.keep_iwyu_namespace_format = True
|
|
|
|
infile = """\
|
|
|
|
// Copyright 2010
|
|
|
|
|
|
|
|
#include "foo.h"
|
|
|
|
|
|
|
|
///+namespace ns { class Foo; }
|
|
|
|
///+namespace ns { namespace ns2 { namespace ns3 { class Bar; } } }
|
|
|
|
///+namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } }
|
|
|
|
///+namespace ns { namespace ns4 { class Baz; } }
|
|
|
|
///+
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
iwyu_output = """\
|
|
|
|
add_fwd_declare_keep_iwyu_namespace should add these lines:
|
|
|
|
namespace ns { class Foo; }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class Bar; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } }
|
|
|
|
namespace ns { namespace ns4 { class Baz; } }
|
|
|
|
|
|
|
|
add_fwd_declare_keep_iwyu_namespace should remove these lines:
|
|
|
|
|
|
|
|
The full include-list for add_fwd_declare_keep_iwyu_namespace:
|
|
|
|
#include "foo.h" // lines 3-3
|
|
|
|
namespace ns { class Foo; }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { class Bar; } } }
|
|
|
|
namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } }
|
|
|
|
namespace ns { namespace ns4 { class Baz; } }
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'add_fwd_declare_keep_iwyu_namespace': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output, expected_num_modified_files=1)
|
2011-04-27 00:08:52 +01:00
|
|
|
|
2016-03-22 12:33:54 +00:00
|
|
|
def testBasedir(self):
|
|
|
|
self.flags.basedir = "/project/build/"
|
|
|
|
iwyu_output = """\
|
|
|
|
../src/source.cc should add these lines:
|
|
|
|
|
|
|
|
../src/source.cc should remove these lines:
|
|
|
|
- #include <unused.h> // lines 1-1
|
|
|
|
|
|
|
|
The full include-list for ../src/source.cc:
|
|
|
|
#include <used.h>
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
infile = """\
|
|
|
|
#include <unused.h> ///-
|
|
|
|
#include <used.h>
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'/project/src/source.cc': infile})
|
|
|
|
self.ProcessAndTest(iwyu_output, expected_num_modified_files=1)
|
|
|
|
|
|
|
|
def testBasedirWithFilesToProcess(self):
|
|
|
|
self.flags.basedir = "/project/build/"
|
|
|
|
iwyu_output = """\
|
|
|
|
../src/changed.cc should add these lines:
|
|
|
|
|
|
|
|
../src/changed.cc should remove these lines:
|
|
|
|
- #include <unused.h> // lines 1-1
|
|
|
|
|
|
|
|
The full include-list for ../src/changed.cc:
|
|
|
|
#include <used.h>
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
changed_file = """\
|
|
|
|
#include <unused.h> ///-
|
|
|
|
#include <used.h>
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
unchanged_file = """\
|
|
|
|
#include <unused.h>
|
|
|
|
#include <used.h>
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
|
|
|
|
iwyu_output += iwyu_output.replace('changed.cc', 'unchanged.cc')
|
|
|
|
|
|
|
|
self.RegisterFileContents({
|
|
|
|
'/project/src/changed.cc': changed_file,
|
|
|
|
'/project/src/unchanged.cc': unchanged_file
|
|
|
|
})
|
|
|
|
self.ProcessAndTest(iwyu_output, cmdline_files=['/project/src/changed.cc'],
|
|
|
|
unedited_files=['/project/src/unchanged.cc'])
|
|
|
|
|
|
|
|
def testBasedirWithRelativeCmdlineFiles(self):
|
|
|
|
self.flags.basedir = "/project/build/"
|
|
|
|
iwyu_output = """\
|
|
|
|
../src/changed.cc should add these lines:
|
|
|
|
|
|
|
|
../src/changed.cc should remove these lines:
|
|
|
|
- #include <unused.h> // lines 1-1
|
|
|
|
|
|
|
|
The full include-list for ../src/changed.cc:
|
|
|
|
#include <used.h>
|
|
|
|
---
|
|
|
|
"""
|
|
|
|
changed_file = """\
|
|
|
|
#include <unused.h> ///-
|
|
|
|
#include <used.h>
|
|
|
|
|
|
|
|
int main() { return 0; }
|
|
|
|
"""
|
|
|
|
|
|
|
|
self.RegisterFileContents({
|
|
|
|
# File path is normalized to absolute by ProcessIWYUOutput.
|
|
|
|
'/project/src/changed.cc': changed_file,
|
|
|
|
})
|
|
|
|
self.ProcessAndTest(iwyu_output, cmdline_files=['changed.cc'],
|
|
|
|
cwd='/project/src')
|
|
|
|
|
2011-04-13 04:11:35 +01:00
|
|
|
def testMain(self):
|
|
|
|
"""Make sure calling main doesn't crash. Inspired by a syntax-error bug."""
|
|
|
|
# Give an empty stdin so we don't actually try to parse anything.
|
|
|
|
old_stdin = sys.stdin
|
|
|
|
try:
|
2015-05-11 21:36:31 +01:00
|
|
|
sys.stdin = StringIO()
|
2011-04-13 04:11:35 +01:00
|
|
|
fix_includes.main(['fix_includes.py']) # argv[0] doesn't really matter
|
|
|
|
finally:
|
|
|
|
sys.stdin = old_stdin
|
|
|
|
|
|
|
|
def testFilenamesForSortingInMain(self):
|
|
|
|
"""Make sure if we use s, we have a filename specified, in main()."""
|
|
|
|
# -s without any files to sort.
|
|
|
|
self.assertRaises(SystemExit, fix_includes.main,
|
|
|
|
['fix_includes.py', '-s'])
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2018-07-07 03:09:06 +01:00
|
|
|
def testReorderingInclusions(self):
|
|
|
|
"""Show that the --reorder flag causes #includes to be sorted."""
|
|
|
|
infile = """\
|
|
|
|
// namespace B
|
|
|
|
namespace B { class BC; } // B
|
|
|
|
// namespace A
|
|
|
|
namespace A { class AC; } // A
|
|
|
|
// b
|
|
|
|
#include "b" // b
|
|
|
|
// c
|
|
|
|
#include <c> // c
|
|
|
|
// a
|
|
|
|
#include <a> // a
|
|
|
|
// a
|
|
|
|
#include "a" // a
|
|
|
|
// asdf
|
|
|
|
#ifdef asdf
|
|
|
|
// x
|
|
|
|
#include <x> // x
|
|
|
|
// endif
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
// namespace B
|
|
|
|
namespace B { class BC; } // B
|
|
|
|
// namespace A
|
|
|
|
namespace A { class AC; } // A
|
|
|
|
// a
|
|
|
|
#include <a> // a
|
|
|
|
// c
|
|
|
|
#include <c> // c
|
|
|
|
// a
|
|
|
|
#include "a" // a
|
|
|
|
// b
|
|
|
|
#include "b" // b
|
|
|
|
// asdf
|
|
|
|
#ifdef asdf
|
|
|
|
// x
|
|
|
|
#include <x> // x
|
|
|
|
// endif
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'inclusions_reordered.cc': infile})
|
|
|
|
self.flags.reorder = True
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(
|
|
|
|
['inclusions_reordered.cc'], self.flags)
|
2019-01-23 17:43:06 +00:00
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
2018-07-07 03:09:06 +01:00
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(1, num_files_modified)
|
|
|
|
|
|
|
|
def testNoReorderingInclusions(self):
|
|
|
|
"""Show that the --noreorder flag causes #includes not to be sorted."""
|
|
|
|
infile = """\
|
|
|
|
// namespace B
|
|
|
|
namespace B { class BC; } // B
|
|
|
|
// namespace A
|
|
|
|
namespace A { class AC; } // A
|
|
|
|
// b
|
|
|
|
#include "b" // b
|
|
|
|
// c
|
|
|
|
#include <c> // c
|
|
|
|
// a
|
|
|
|
#include <a> // a
|
|
|
|
// a
|
|
|
|
#include "a" // a
|
|
|
|
// asdf
|
|
|
|
#ifdef asdf
|
|
|
|
// x
|
|
|
|
#include <x> // x
|
|
|
|
// endif
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
expected_output = """\
|
|
|
|
// namespace B
|
|
|
|
namespace B { class BC; } // B
|
|
|
|
// namespace A
|
|
|
|
namespace A { class AC; } // A
|
|
|
|
// c
|
|
|
|
#include <c> // c
|
|
|
|
// a
|
|
|
|
#include <a> // a
|
|
|
|
// b
|
|
|
|
#include "b" // b
|
|
|
|
// a
|
|
|
|
#include "a" // a
|
|
|
|
// asdf
|
|
|
|
#ifdef asdf
|
|
|
|
// x
|
|
|
|
#include <x> // x
|
|
|
|
// endif
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
self.RegisterFileContents({'inclusions_not_reordered.cc': infile})
|
|
|
|
self.flags.reorder = False
|
|
|
|
num_files_modified = fix_includes.SortIncludesInFiles(
|
|
|
|
['inclusions_not_reordered.cc'], self.flags)
|
2019-01-23 17:43:06 +00:00
|
|
|
self.assertListEqual(expected_output.splitlines(True),
|
2018-07-07 03:09:06 +01:00
|
|
|
self.actual_after_contents)
|
|
|
|
self.assertEqual(1, num_files_modified)
|
|
|
|
|
2011-05-04 19:16:58 +01:00
|
|
|
|
2018-03-18 13:59:37 +00:00
|
|
|
class FileInfoTest(unittest.TestCase):
|
|
|
|
""" Unit test for file info detection """
|
|
|
|
|
|
|
|
def testEndingsWindows(self):
|
|
|
|
buf = b'first\r\nsecond\r\nthird\r\n'
|
|
|
|
self.assertEqual('\r\n', fix_includes.FileInfo.guess_linesep(buf))
|
|
|
|
|
|
|
|
def testEndingsUnix(self):
|
|
|
|
buf = b'first\nsecond\nthird\n'
|
|
|
|
self.assertEqual('\n', fix_includes.FileInfo.guess_linesep(buf))
|
|
|
|
|
|
|
|
def testEndingsMixedUnixMajority(self):
|
|
|
|
buf = b'first\nsecond\nsecond-and-a-half\r\nthird\nfourth\r\n'
|
|
|
|
self.assertEqual('\n', fix_includes.FileInfo.guess_linesep(buf))
|
|
|
|
|
|
|
|
def testEndingsMixedWindowsMajority(self):
|
|
|
|
buf = b'first\nsecond\r\nsecond-and-a-half\r\nthird\nfourth\r\n'
|
|
|
|
self.assertEqual('\r\n', fix_includes.FileInfo.guess_linesep(buf))
|
|
|
|
|
|
|
|
def testEndingsMixedTie(self):
|
|
|
|
buf = b'first\nsecond\nthird\r\nfourth\r\n'
|
|
|
|
self.assertEqual(fix_includes.FileInfo.DEFAULT_LINESEP,
|
|
|
|
fix_includes.FileInfo.guess_linesep(buf))
|
|
|
|
|
2018-03-18 15:53:32 +00:00
|
|
|
def testEncodingASCII(self):
|
|
|
|
buf = b'abcdefgh'
|
|
|
|
self.assertEqual('ascii', fix_includes.FileInfo.guess_encoding(buf))
|
|
|
|
|
|
|
|
def testEncodingUTF8BOM(self):
|
|
|
|
buf = b'\xef\xbb\xbfSomeASCIIButWithTheBOM'
|
2018-11-27 01:46:23 +00:00
|
|
|
self.assertEqual('utf-8-sig', fix_includes.FileInfo.guess_encoding(buf))
|
2018-03-18 15:53:32 +00:00
|
|
|
|
|
|
|
def testEncodingUTF8NoBOM(self):
|
|
|
|
# This is a recurring test input in Swedish, translates to "shrimp sandwich"
|
|
|
|
# and contains all three Swedish exotic characters.
|
|
|
|
buf = b'r\xc3\xa4ksm\xc3\xb6rg\xc3\xa5s'
|
|
|
|
self.assertEqual('utf-8', fix_includes.FileInfo.guess_encoding(buf))
|
|
|
|
|
|
|
|
def testEncodingISO8859_1(self):
|
|
|
|
# Yours truly
|
|
|
|
buf = b'Kim Gr\xe4sman'
|
|
|
|
self.assertEqual('windows-1250', fix_includes.FileInfo.guess_encoding(buf))
|
|
|
|
|
2018-03-18 13:59:37 +00:00
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
if __name__ == '__main__':
|
|
|
|
unittest.main()
|