mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
124 lines
4.9 KiB
Python
124 lines
4.9 KiB
Python
#!/usr/bin/python
|
|
|
|
import os
|
|
|
|
|
|
def process_single_file(filename):
|
|
if not filename.endswith(".qll"):
|
|
return
|
|
|
|
with open(filename, 'r') as file_in:
|
|
lines = [line for line in file_in]
|
|
|
|
configuresDataflow = any(
|
|
"implements DataFlow::ConfigSig" in line for line in lines)
|
|
|
|
moduleAnnotations = ""
|
|
if any(line for line in lines if line.rstrip().endswith("module;")):
|
|
for line in lines:
|
|
moduleAnnotations += line
|
|
if line.rstrip().endswith("module;"):
|
|
break
|
|
|
|
moduleAnnotations = strip_comments(moduleAnnotations)
|
|
|
|
isFileLevelAnnotated = ("overlay[local]" in moduleAnnotations or
|
|
"overlay[local?]" in moduleAnnotations)
|
|
|
|
if configuresDataflow or isFileLevelAnnotated or filename.endswith("Query.qll"):
|
|
if isFileLevelAnnotated and configuresDataflow:
|
|
print("WARNING: file \""+filename +
|
|
"\" configures dataflow, but is annotated local")
|
|
elif configuresDataflow and not filename.endswith("Query.qll"):
|
|
print("WARNING: file \""+filename +
|
|
"\" configures dataflow but is not a [...]Query.qll file")
|
|
elif filename.endswith("Query.qll") and not configuresDataflow:
|
|
print("WARNING: file \""+filename +
|
|
"\" is a [...]Query.qll file that does not configure dataflow")
|
|
elif isFileLevelAnnotated and filename.endswith("Query.qll"):
|
|
print("WARNING: file \""+filename +
|
|
"\" is a [...]Query.qll file, but is annotated local")
|
|
elif any(line for line in lines if line.rstrip().endswith("module;")):
|
|
print("file \""+filename +
|
|
" was annotated using an existing file-level module statment")
|
|
with open(filename, "w") as file_out:
|
|
for line in lines:
|
|
if line.rstrip().endswith("module;"):
|
|
file_out.write("overlay[local?]\n")
|
|
file_out.write(line)
|
|
elif (lines[0].startswith("import ") or lines[0].startswith("private ") or
|
|
lines[0].startswith("newtype ") or lines[0].startswith("module ") or
|
|
lines[0].startswith("signature ")):
|
|
print("file \""+filename+" was annotated at the very start of the file")
|
|
with open(filename, "w") as file_out:
|
|
file_out.write("overlay[local?]\nmodule;\n\n")
|
|
for line in lines:
|
|
file_out.write(line)
|
|
elif (strip_comments("".join(lines)).lstrip().startswith("import") or
|
|
strip_comments("".join(lines)).lstrip().startswith("private import")):
|
|
print("file \""+filename+" was annotated at the first import statement")
|
|
with open(filename, "w") as file_out:
|
|
firstImport = True
|
|
addEmptyLine = ""
|
|
for line in lines:
|
|
if not line.strip():
|
|
if addEmptyLine:
|
|
file_out.write(addEmptyLine)
|
|
addEmptyLine = line
|
|
else:
|
|
if firstImport and (line.startswith("import") or line.startswith("private")):
|
|
file_out.write("overlay[local?]\nmodule;\n")
|
|
firstImport = False
|
|
|
|
if addEmptyLine:
|
|
file_out.write(addEmptyLine)
|
|
addEmptyLine = ""
|
|
file_out.write(line)
|
|
elif (len(lines) > 2 and lines[0].startswith("/** ") and lines[0].endswith(" */\n") and
|
|
not lines[1].strip() and lines[2].startswith("/**")):
|
|
print("file \""+filename+" was annotated after single-line file module qldoc")
|
|
with open(filename, "w") as file_out:
|
|
file_out.write(lines[0])
|
|
file_out.write("overlay[local?]\nmodule;\n")
|
|
for line in lines[1:]:
|
|
file_out.write(line)
|
|
else:
|
|
print("ERROR: failure to annotate file \""+filename+"\"")
|
|
|
|
|
|
def strip_comments(str):
|
|
prev = ""
|
|
in_multiline = False
|
|
in_singleline = False
|
|
|
|
result = ""
|
|
for c in str:
|
|
if c == '*' and prev == '/':
|
|
in_multiline = True
|
|
prev = ""
|
|
elif c == '/' and prev == '/':
|
|
in_singleline = True
|
|
prev = ""
|
|
elif in_multiline and c == '/' and prev == '*':
|
|
in_multiline = False
|
|
prev = ""
|
|
elif in_singleline and c == '\n':
|
|
in_singleline = False
|
|
result += '\n'
|
|
prev = ""
|
|
else:
|
|
if not in_multiline and not in_singleline:
|
|
if prev == '/':
|
|
result += '/'
|
|
if c != '/':
|
|
result += c
|
|
prev = c
|
|
return result
|
|
|
|
|
|
for roots in ["java/ql/lib/semmle/code", "shared"]:
|
|
for dirpath, dirnames, filenames in os.walk(roots):
|
|
for filename in filenames:
|
|
if filename.endswith(".qll"):
|
|
process_single_file(os.path.join(dirpath, filename))
|