Run include order check in doc-check
[alexxy/gromacs.git] / docs / doxygen / gmxtree.py
index 1c28e6a3e416fee1ce5209ed18b16cb2bb065e09..67240f391f603074436a3e1c5297ecd2f3a572aa 100644 (file)
@@ -54,6 +54,7 @@ import collections
 import os
 import os.path
 import re
+import subprocess
 
 import doxygenxml as xml
 import reporter
@@ -76,7 +77,7 @@ class IncludedFile(object):
 
     """Information about an #include directive in a file."""
 
-    def __init__(self, including_file, lineno, included_file, included_path, is_relative, is_system):
+    def __init__(self, including_file, lineno, included_file, included_path, is_relative, is_system, line):
         self._including_file = including_file
         self._line_number = lineno
         self._included_file = included_file
@@ -84,6 +85,7 @@ class IncludedFile(object):
         #self._used_include_path = used_include_path
         self._is_relative = is_relative
         self._is_system = is_system
+        self._line = line
 
     def __str__(self):
         if self._is_system:
@@ -109,6 +111,12 @@ class IncludedFile(object):
     def get_line_number(self):
         return self._line_number
 
+    def get_full_line(self):
+        """Return the full source line on which this include appears.
+
+        Trailing newline is included."""
+        return self._line
+
     def get_reporter_location(self):
         return reporter.Location(self._including_file.get_abspath(), self._line_number)
 
@@ -154,6 +162,7 @@ class File(object):
         self._include_blocks = []
         self._main_header = None
         self._lines = None
+        self._filter = None
         directory.add_file(self)
 
     def set_doc_xml(self, rawdoc, sourcetree):
@@ -173,12 +182,16 @@ class File(object):
         """Mark the file installed."""
         self._installed = True
 
+    def set_git_filter_attribute(self, filtername):
+        """Set the git filter attribute associated with the file."""
+        self._filter = filtername
+
     def set_main_header(self, included_file):
         """Set the main header file for a source file."""
         assert self.is_source_file()
         self._main_header = included_file
 
-    def _process_include(self, lineno, is_system, includedpath, sourcetree):
+    def _process_include(self, lineno, is_system, includedpath, line, sourcetree):
         """Process #include directive during scan()."""
         is_relative = False
         if is_system:
@@ -192,7 +205,7 @@ class File(object):
             else:
                 fileobj = sourcetree.find_include_file(includedpath)
         included_file = IncludedFile(self, lineno, fileobj, includedpath,
-            is_relative, is_system)
+            is_relative, is_system, line)
         self._includes.append(included_file)
         return included_file
 
@@ -211,7 +224,7 @@ class File(object):
                     is_system = (match.group('quote') == '<')
                     includedpath = match.group('path')
                     included_file = self._process_include(lineno, is_system,
-                            includedpath, sourcetree)
+                            includedpath, line, sourcetree)
                     if current_block is None:
                         current_block = IncludeBlock(included_file)
                         self._include_blocks.append(current_block)
@@ -237,6 +250,10 @@ class File(object):
     def is_test_file(self):
         return self._dir.is_test_directory()
 
+    def should_includes_be_sorted(self):
+        """Return whether the include directives in the file should be sorted."""
+        return self._filter in ('includesort', 'uncrustify')
+
     def is_documented(self):
         return self._rawdoc and self._rawdoc.is_documented()
 
@@ -602,6 +619,9 @@ class GromacsTree(object):
     subdirectories.  At this point, only information that is accessible from
     file names and paths only is available.
 
+    load_git_attributes() can be called to load attribute information from
+    .gitattributes for all the files.
+
     load_installed_file_list() can be called to load the list of installed
     files from the build tree (generated by the find-installed-headers target).
 
@@ -872,6 +892,19 @@ class GromacsTree(object):
             if testpath in self._files:
                 return self._files[testpath]
 
+    def load_git_attributes(self):
+        """Load git attribute information for files."""
+        args = ['git', 'check-attr', '--stdin', 'filter']
+        git_check_attr = subprocess.Popen(args, stdin=subprocess.PIPE,
+                stdout=subprocess.PIPE, cwd=self._source_root)
+        filelist = '\n'.join(map(File.get_relpath, self._files.itervalues()))
+        filters = git_check_attr.communicate(filelist)[0]
+        for fileinfo in filters.splitlines():
+            path, dummy, value = fileinfo.split(': ')
+            fileobj = self._files.get(path)
+            assert fileobj is not None
+            fileobj.set_git_filter_attribute(value)
+
     def load_installed_file_list(self):
         """Load list of installed files from the build tree."""
         listpath = os.path.join(self._build_root, 'docs', 'doxygen', 'installed-headers.txt')