ardupilot/Tools/scripts/run_lua_language_check.py

182 lines
5.6 KiB
Python
Executable File

#!/usr/bin/env python3
'''
Reads lua-language-sever check
It generates a json report that this then parses to make it look nicer
AP_FLAKE8_CLEAN
'''
import optparse
import sys
import os
import pathlib
import json
import shutil
import platform
from urllib.parse import unquote
import subprocess
import re
def print_failures(file_name, fails, original_name):
file_name = unquote(file_name)
file_path = pathlib.Path(file_name[5:])
if (original_name is not None) and (original_name.name == file_path.name):
file_path = original_name
for fail in fails:
start = fail['range']['start']
# These seem to be off by one, not sure why
line = start['line'] + 1
character = start['character'] + 1
print("%s:%i:%i" % (file_path, line, character))
print("\tCode: %s" % fail['code'])
message = fail['message'].split("\n")
for line in message:
print("\t%s" % line)
print()
return len(fails)
if __name__ == '__main__':
parser = optparse.OptionParser(__file__)
opts, args = parser.parse_args()
if len(args) > 1:
print('Usage: %s "check path"' % parser.usage)
sys.exit(0)
check_path = "./"
if len(args) > 0:
check_path = args[0]
check_path = pathlib.Path(check_path)
if not os.path.exists(check_path):
raise Exception("Path invalid: %s" % check_path)
# Work out full path to config file
ap_root = (pathlib.Path(__file__) / "../../../").resolve()
setup = (ap_root / "libraries/AP_Scripting/tests/check.json").resolve()
logs = (ap_root / "lualogs").resolve()
docs = (ap_root / "libraries/AP_Scripting/docs/docs.lua").resolve()
# Make sure the log directory is empty
if os.path.exists(logs) and len(os.listdir(logs)) != 0:
raise Exception("lualogs not empty")
install_path = (ap_root / "lua-language-server").resolve()
# See if there is a new version (only try on Linux)
if platform.system() == "Linux":
try:
from github_release_downloader import check_and_download_updates, GitHubRepo
except ImportError:
print("Import github-release-downloader failed")
print("Install with: python3 -m pip install github-release-downloader")
sys.exit(0)
asset_re = re.compile(r".*linux-x64\.tar\.gz")
check_and_download_updates(
GitHubRepo("LuaLS", "lua-language-server"),
assets_mask=asset_re,
downloads_dir=ap_root,
)
for filename in os.listdir(ap_root):
if asset_re.match(filename):
pack_path = (ap_root / filename).resolve()
shutil.unpack_archive(pack_path, install_path)
os.remove(pack_path)
run_path = (install_path / "bin/lua-language-server")
if not os.path.isfile(run_path):
# Try and use version from path
run_path = "lua-language-server"
# If the target is a single script copy it to a new directory
tmp_check_dir = None
original_name = None
if os.path.isfile(check_path):
tmp_check_dir = (check_path / "../tmp_llc").resolve()
os.mkdir(tmp_check_dir)
shutil.copyfile(check_path, (tmp_check_dir / check_path.name).resolve())
original_name = check_path
check_path = tmp_check_dir
# Can't get the lua-language-server to find docs outside of workspace, so just copy in and then delete
docs_check_path = (pathlib.Path(os.getcwd()) / check_path).resolve()
if os.path.isfile(docs_check_path):
docs_check_path = (docs_check_path / "../").resolve()
docs_copy = None
if not docs.is_relative_to(docs_check_path):
docs_copy = (docs_check_path / "docs.lua").resolve()
if docs_copy is not None:
# make copy of docs
shutil.copyfile(docs, docs_copy)
# Run check, print output in real time for user and capture so we can confirm it has found at least one file
command = "%s --configpath %s --logpath %s --check %s" % (run_path, setup, logs, check_path)
p = subprocess.Popen(command, shell=True, text=True, stdout=subprocess.PIPE)
result = []
while p.poll() is None:
line = p.stdout.readline()
result.append(line)
print(line, end="")
# Make sure we checked at least one file
file_count_re = re.compile(r"^>*=* \d+/(\d+)")
checked_files = None
for line in result:
match = file_count_re.search(line)
if match is not None:
count = int(match.group(1))
if checked_files is None:
checked_files = count
elif checked_files != count:
raise Exception("Checked files error expected: %i got: %i" % (checked_files, count))
if tmp_check_dir is not None:
# Remove test directory
shutil.rmtree(tmp_check_dir)
elif docs_copy is not None:
# remove copy of docs
os.remove(docs_copy)
# Read output
errors = 0
result = (logs / "check.json").resolve()
if os.path.exists(result):
# File only created if there are errors
f = open((logs / "check.json").resolve())
data = json.load(f)
f.close()
if len(data) > 0:
# Print output if there are any errors
for key, value in data.items():
errors += print_failures(key, value, original_name)
# Remove output
shutil.rmtree(logs)
# Rase error if detected
if errors != 0:
raise Exception("Detected %i errors" % errors)
# Warn if no files were checked
if (checked_files is None) or (checked_files < 1):
raise Exception("No lua files found in: %s" % check_path)
print("%i Files checked" % checked_files)