mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
We were only keeping track of `RawSyntax` node IDs to incrementally transfer a syntax tree via JSON. However, AFAICT the incremental JSON transfer option has been superceeded by `SyntaxParseActions`, which are more efficient. So, let’s clean up and remove the `RawSyntax` node ID and JSON incremental transfer option. In places that still need a notion of `RawSyntax` identity (like determining the reused syntax regions), use the `RawSyntax`’s pointer instead of the manually created ID. In `incr_transfer_round_trip.py` always use the code path that uses the `SyntaxParseActions` and remove the transitional code that was still using the incremental JSON transfer but was never called.
151 lines
6.4 KiB
Python
Executable File
151 lines
6.4 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import difflib
|
|
import io
|
|
import os
|
|
import sys
|
|
|
|
from test_util import TestFailedError, serializeIncrParseMarkupFile
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
description='Utility for testing incremental syntax parsing',
|
|
epilog='''
|
|
Based of a single template the utility generates a pre-edit and a post-edit
|
|
file. It then verifies that incrementally parsing the post-edit file base
|
|
on the pre-edit file results in the same syntax tree as reparsing the
|
|
post-edit file from scratch.
|
|
|
|
To generate the pre-edit and the post-edit file from the template, it
|
|
operates on markers of the form:
|
|
|
|
<<test_case<pre|||post>>>
|
|
|
|
These placeholders are replaced by:
|
|
- 'pre' if a different test case than 'test_case' is run
|
|
- 'pre' for the pre-edit version of 'test_case'
|
|
- 'post' for the post-edit version of 'test_case'
|
|
''')
|
|
parser.add_argument(
|
|
'file', type=argparse.FileType(),
|
|
help='The template file to test')
|
|
parser.add_argument(
|
|
'--test-case', default='',
|
|
help='The test case to execute. If no test case is specified all \
|
|
unnamed substitutions are applied')
|
|
parser.add_argument(
|
|
'--temp-dir', required=True,
|
|
help='A temporary directory where pre-edit and post-edit files can be \
|
|
saved')
|
|
parser.add_argument(
|
|
'--swift-syntax-test', required=True,
|
|
help='The path to swift-syntax-test')
|
|
parser.add_argument(
|
|
'--print-visual-reuse-info', default=False, action='store_true',
|
|
help='Print visual reuse information about the incremental parse \
|
|
instead of diffing the syntax trees. This option is intended \
|
|
for debug purposes only.')
|
|
|
|
args = parser.parse_args(sys.argv[1:])
|
|
|
|
test_file = args.file.name
|
|
test_file_name = os.path.basename(test_file)
|
|
test_case = args.test_case
|
|
temp_dir = args.temp_dir
|
|
swift_syntax_test = args.swift_syntax_test
|
|
visual_reuse_info = args.print_visual_reuse_info
|
|
|
|
if not os.path.exists(temp_dir):
|
|
os.makedirs(temp_dir)
|
|
|
|
incremental_serialized_file = temp_dir + '/' + test_file_name + '.' \
|
|
+ test_case + '.postViaIncr.json'
|
|
post_edit_serialized_file = temp_dir + '/' + test_file_name + '.' \
|
|
+ test_case + '.post.json'
|
|
|
|
incremental_diags_file = temp_dir + '/' + test_file_name + '.' \
|
|
+ test_case + '.diagsViaIncr.txt'
|
|
post_edit_diags_file = temp_dir + '/' + test_file_name + '.' \
|
|
+ test_case + '.post.diags.txt'
|
|
|
|
# Generate the syntax tree once incrementally and once from scratch
|
|
try:
|
|
serializeIncrParseMarkupFile(test_file=test_file,
|
|
test_case=test_case,
|
|
mode='incremental',
|
|
omit_node_ids=True,
|
|
output_file=incremental_serialized_file,
|
|
diags_output_file=incremental_diags_file,
|
|
temp_dir=temp_dir + '/temp',
|
|
swift_syntax_test=swift_syntax_test,
|
|
print_visual_reuse_info=visual_reuse_info)
|
|
if visual_reuse_info:
|
|
# If we just want the reuse info, we don't need to parse the file
|
|
# from scratch or validate it
|
|
sys.exit(0)
|
|
|
|
serializeIncrParseMarkupFile(test_file=test_file,
|
|
test_case=test_case,
|
|
mode='post-edit',
|
|
omit_node_ids=True,
|
|
output_file=post_edit_serialized_file,
|
|
diags_output_file=post_edit_diags_file,
|
|
temp_dir=temp_dir + '/temp',
|
|
swift_syntax_test=swift_syntax_test,
|
|
print_visual_reuse_info=visual_reuse_info)
|
|
except TestFailedError as e:
|
|
print('Test case "%s" of %s FAILed' % (test_case, test_file),
|
|
file=sys.stderr)
|
|
print(e.message, file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
# Check if the two syntax trees are the same
|
|
lines = difflib.unified_diff(io.open(incremental_serialized_file, 'r',
|
|
encoding='utf-8', errors='ignore').readlines(),
|
|
io.open(post_edit_serialized_file, 'r',
|
|
encoding='utf-8', errors='ignore').readlines(),
|
|
fromfile=incremental_serialized_file,
|
|
tofile=post_edit_serialized_file)
|
|
diff = '\n'.join(line for line in lines)
|
|
if diff:
|
|
print('Test case "%s" of %s FAILed' % (test_case, test_file),
|
|
file=sys.stderr)
|
|
print('Syntax tree of incremental parsing does not match '
|
|
'from-scratch parsing of post-edit file:\n\n', file=sys.stderr)
|
|
print(diff, file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
# Verify that if the incremental parse resulted in parser diagnostics, those
|
|
# diagnostics were also emitted during the full parse.
|
|
# We can't just diff the outputs because the full parse includes diagnostics
|
|
# from the whole file, while the incremental parse includes only a subset.
|
|
# Each diagnostic is searched in the full parse diagnostics array but the
|
|
# search for each diagnostic continues from where the previous search
|
|
# stopped.
|
|
incremental_diags = open(incremental_diags_file).readlines()
|
|
post_edit_diags = open(post_edit_diags_file).readlines()
|
|
full_idx = 0
|
|
for diag in incremental_diags:
|
|
while full_idx < len(post_edit_diags):
|
|
if post_edit_diags[full_idx] == diag:
|
|
break
|
|
full_idx += 1
|
|
if full_idx == len(post_edit_diags):
|
|
print('Test case "%s" of %s FAILed' % (test_case, test_file),
|
|
file=sys.stderr)
|
|
print('Parser diagnostic of incremental parsing was not emitted '
|
|
'during from-scratch parsing of post-edit file:',
|
|
file=sys.stderr)
|
|
print(diag, file=sys.stderr)
|
|
sys.exit(1)
|
|
full_idx += 1 # continue searching from the next diagnostic line.
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|