mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
./utils/cmpcodesize/cmpcodesize/main.py:20:71: E231 missing whitespace after ',' ./utils/round-trip-syntax-test:20:20: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()` ./utils/round-trip-syntax-test:21:16: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()` I can't find any uses of round-trip-syntax-test, so I don't know if this fix is correct.
177 lines
6.5 KiB
Python
Executable File
177 lines
6.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import difflib
|
|
import logging
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from functools import reduce
|
|
|
|
logging.basicConfig(format='%(message)s', level=logging.INFO)
|
|
|
|
|
|
class RoundTripTask(object):
|
|
def __init__(self, input_filename, action, swift_syntax_test,
|
|
skip_bad_syntax):
|
|
assert action == '-round-trip-parse' or action == '-round-trip-lex'
|
|
if sys.version_info[0] < 3:
|
|
assert isinstance(input_filename, str)
|
|
assert isinstance(swift_syntax_test, str)
|
|
|
|
assert os.path.isfile(input_filename), \
|
|
"Input file {} is not accessible!".format(input_filename)
|
|
assert os.path.isfile(swift_syntax_test), \
|
|
"{} tool is not accessible!".format(swift_syntax_test)
|
|
self.input_filename = input_filename
|
|
self.action = action
|
|
self.swift_syntax_test = swift_syntax_test
|
|
self.skip_bad_syntax = skip_bad_syntax
|
|
self.returncode = None
|
|
self.stdout = None
|
|
self.stderr = None
|
|
|
|
@property
|
|
def test_command(self):
|
|
return [self.swift_syntax_test, self.action,
|
|
'-input-source-filename', self.input_filename]
|
|
|
|
def run(self):
|
|
command = self.test_command
|
|
logging.debug(' '.join(command))
|
|
self.output_file = tempfile.NamedTemporaryFile('w', delete=False)
|
|
self.stderr_file = tempfile.NamedTemporaryFile('w', delete=False)
|
|
|
|
process = subprocess.Popen(command, stdout=self.output_file,
|
|
stderr=self.stderr_file)
|
|
process.wait()
|
|
self.returncode = process.returncode
|
|
|
|
self.output_file.close()
|
|
self.stderr_file.close()
|
|
|
|
with open(self.output_file.name, 'rb') as stdout_in:
|
|
self.stdout = stdout_in.read()
|
|
with open(self.stderr_file.name, 'rb') as stderr_in:
|
|
self.stderr = stderr_in.read()
|
|
|
|
os.remove(self.output_file.name)
|
|
os.remove(self.stderr_file.name)
|
|
|
|
if self.returncode != 0:
|
|
if self.skip_bad_syntax:
|
|
logging.warning('---===WARNING===--- Lex/parse had error'
|
|
' diagnostics, so not diffing. Skipping'
|
|
' this file due to -skip-bad-syntax.')
|
|
logging.error(' '.join(command))
|
|
return None
|
|
else:
|
|
logging.error('---===ERROR===--- Lex/parse had error'
|
|
' diagnostics, so not diffing.')
|
|
logging.error(' '.join(command))
|
|
logging.error(self.stdout.decode('utf-8', errors='replace'))
|
|
logging.error(self.stderr.decode('utf-8', errors='replace'))
|
|
raise RuntimeError()
|
|
|
|
contents = ''.join(map(lambda _: _.decode('utf-8', errors='replace'),
|
|
open(self.input_filename, 'rb').readlines()))
|
|
stdout_contents = self.stdout.decode('utf-8', errors='replace')
|
|
|
|
if contents == stdout_contents:
|
|
return None
|
|
|
|
lines = difflib.unified_diff(contents, stdout_contents,
|
|
fromfile=self.input_filename,
|
|
tofile='-')
|
|
diff = '\n'.join(line for line in lines)
|
|
return diff if diff else None
|
|
|
|
|
|
def swift_files_in_dir(d):
|
|
swift_files = []
|
|
for root, dirs, files in os.walk(d):
|
|
for basename in files:
|
|
if not basename.endswith('.swift'):
|
|
continue
|
|
abs_file = os.path.abspath(os.path.join(root, basename))
|
|
swift_files.append(abs_file)
|
|
return swift_files
|
|
|
|
|
|
def run_task(task):
|
|
try:
|
|
diff = task.run()
|
|
if diff is not None:
|
|
logging.error('---===ERROR===--- Diff failed!')
|
|
logging.error(' '.join(task.test_command))
|
|
logging.error(diff)
|
|
logging.error('')
|
|
return True
|
|
except RuntimeError as e:
|
|
logging.error(e.message)
|
|
return True
|
|
return False
|
|
|
|
|
|
def main():
|
|
tool_description = '''
|
|
Checks for round-trip lex/parse/print compatibility.
|
|
|
|
Swift's syntax representation should be "full-fidelity", meaning that there is
|
|
a perfect representation of what is in the source. When printing a syntax tree
|
|
to a file, that file should be identical to the file that was
|
|
originally parsed.
|
|
|
|
This driver invokes swift-syntax-test using -round-trip-lex and
|
|
-round-trip-parse on .swift files and .swift files in directories.
|
|
'''
|
|
parser = argparse.ArgumentParser(description=tool_description)
|
|
parser.add_argument('--directory', '-d', action='append',
|
|
dest='input_directories', default=[],
|
|
help='Add a directory, searching for .swift files'
|
|
' within')
|
|
parser.add_argument('--file', '-f', action='append',
|
|
dest='individual_input_files', default=[],
|
|
help='Add an individual file to test')
|
|
parser.add_argument('--swift-syntax-test', '-t', required=True,
|
|
dest='tool_path',
|
|
help='Absolute path to the swift-syntax-test tool')
|
|
parser.add_argument('--skip-bad-syntax',
|
|
action='store_true',
|
|
default=False,
|
|
help="Skip files that caused lex or parse diagnostics"
|
|
" to be emitted")
|
|
|
|
args = parser.parse_args()
|
|
|
|
dir_listings = [swift_files_in_dir(d) for d in args.input_directories]
|
|
all_input_files = [filename for dir_listing in dir_listings
|
|
for filename in dir_listing]
|
|
all_input_files += args.individual_input_files
|
|
if sys.version_info[0] < 3:
|
|
all_input_files = [f.decode('utf-8') for f in all_input_files]
|
|
|
|
if len(all_input_files) == 0:
|
|
logging.error('No input files!')
|
|
sys.exit(1)
|
|
|
|
if not os.path.isfile(args.tool_path):
|
|
raise RuntimeError("Couldn't find swift-syntax-test at {}"
|
|
.format(args.tool_path))
|
|
|
|
lex_tasks = [RoundTripTask(filename, '-round-trip-lex', args.tool_path,
|
|
args.skip_bad_syntax)
|
|
for filename in all_input_files]
|
|
parse_tasks = [RoundTripTask(filename, '-round-trip-parse', args.tool_path,
|
|
args.skip_bad_syntax)
|
|
for filename in all_input_files]
|
|
|
|
failed = reduce(lambda a, b: a or b,
|
|
map(run_task, lex_tasks + parse_tasks))
|
|
sys.exit(1 if failed else 0)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|