2 # A tool to parse creates a document outlining how clang formatted the
8 from datetime
import datetime
11 def get_git_revision_short_hash():
12 """Get the get SHA in short hash form."""
14 subprocess
.check_output(["git", "rev-parse", "--short", "HEAD"])
15 .decode(sys
.stdout
.encoding
)
20 def get_style(count
, passed
):
21 """Determine if this directory is good based on the number of clean
22 files vs the number of files in total."""
30 TOP_DIR
= os
.path
.join(os
.path
.dirname(__file__
), "../../..")
31 CLANG_DIR
= os
.path
.join(os
.path
.dirname(__file__
), "../..")
32 DOC_FILE
= os
.path
.join(CLANG_DIR
, "docs/ClangFormattedStatus.rst")
33 CLEAN_FILE
= os
.path
.join(CLANG_DIR
, "docs/tools/clang-formatted-files.txt")
37 skipped_dirs
= [".git", "test"]
38 suffixes
= (".cpp", ".h")
43 <style type="text/css">
44 .total {{ font-weight: bold; }}
45 .none {{ background-color: #FFFF99; height: 20px; display: inline-block; width: 120px; text-align: center; border-radius: 5px; color: #000000; font-family="Verdana,Geneva,DejaVu Sans,sans-serif" }}
46 .part {{ background-color: #FFCC99; height: 20px; display: inline-block; width: 120px; text-align: center; border-radius: 5px; color: #000000; font-family="Verdana,Geneva,DejaVu Sans,sans-serif" }}
47 .good {{ background-color: #2CCCFF; height: 20px; display: inline-block; width: 120px; text-align: center; border-radius: 5px; color: #000000; font-family="Verdana,Geneva,DejaVu Sans,sans-serif" }}
55 ======================
56 Clang Formatted Status
57 ======================
59 :doc:`ClangFormattedStatus` describes the state of LLVM source
60 tree in terms of conformance to :doc:`ClangFormat` as of: {today} (`{sha} <https://github.com/llvm/llvm-project/commit/{sha}>`_).
63 .. list-table:: LLVM Clang-Format Status
64 :widths: 50 25 25 25 25
78 - {style2}`{percent}%`
82 with
open(DOC_FILE
, "wb") as output
:
83 cleanfiles
= open(CLEAN_FILE
, "wb")
84 sha
= get_git_revision_short_hash()
85 today
= datetime
.now().strftime("%B %d, %Y %H:%M:%S")
86 output
.write(bytes(RST_PREFIX
.format(today
=today
, sha
=sha
).encode("utf-8")))
91 for root
, subdirs
, files
in os
.walk(rootdir
):
92 for subdir
in subdirs
:
93 if any(sd
== subdir
for sd
in skipped_dirs
):
94 subdirs
.remove(subdir
)
96 act_sub_dir
= os
.path
.join(root
, subdir
)
97 # Check the git index to see if the directory contains tracked
98 # files. Reditect the output to a null descriptor as we aren't
99 # interested in it, just the return code.
100 git_check
= subprocess
.Popen(
101 ["git", "ls-files", "--error-unmatch", act_sub_dir
],
102 stdout
=subprocess
.DEVNULL
,
103 stderr
=subprocess
.DEVNULL
,
105 if git_check
.wait() != 0:
106 print("Skipping directory: ", act_sub_dir
)
107 subdirs
.remove(subdir
)
109 path
= os
.path
.relpath(root
, TOP_DIR
)
110 path
= path
.replace("\\", "/")
115 for filename
in files
:
116 file_path
= os
.path
.join(root
, filename
)
117 ext
= os
.path
.splitext(file_path
)[-1].lower()
118 if not ext
.endswith(suffixes
):
123 args
= ["clang-format", "-n", file_path
]
124 cmd
= subprocess
.Popen(args
, stderr
=subprocess
.PIPE
)
125 stdout
, err
= cmd
.communicate()
127 relpath
= os
.path
.relpath(file_path
, TOP_DIR
)
128 relpath
= relpath
.replace("\\", "/")
129 if err
.decode(sys
.stdout
.encoding
).find(": warning:") > 0:
130 print(relpath
, ":", "FAIL")
133 print(relpath
, ":", "PASS")
135 cleanfiles
.write(bytes(relpath
+ "\n"))
138 total_files_count
+= file_count
139 total_files_pass
+= file_pass
140 total_files_fail
+= file_fail
143 percent
= int(100.0 * (float(file_pass
) / float(file_count
)))
144 style
= get_style(file_count
, file_pass
)
152 percent
=str(percent
),
161 print(path
, file_count
, file_pass
, file_fail
, percent
)
164 total_percent
= float(total_files_pass
) / float(total_files_count
)
165 percent_str
= str(int(100.0 * total_percent
))
170 count
=total_files_count
,
171 passes
=total_files_pass
,
172 fails
=total_files_fail
,