• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2
3# Copyright 2011 by Google, Inc.  All rights reserved.
4# This code is governed by the BSD license found in the LICENSE file.
5
6# TODO: resolve differences with common.py and unify into one file.
7
8
9from __future__ import print_function
10
11import os
12import re
13import imp
14
15from _monkeyYaml import load as yamlLoad
16
17#def onerror(message):
18#    print(message)
19
20# Matches trailing whitespace and any following blank lines.
21_BLANK_LINES = r"([ \t]*[\r\n]{1,2})*"
22
23# Matches the YAML frontmatter block.
24_YAML_PATTERN = re.compile(r"/\*---(.*)---\*/" + _BLANK_LINES, re.DOTALL)
25
26# Matches all known variants for the license block.
27# https://github.com/tc39/test262/blob/705d78299cf786c84fa4df473eff98374de7135a/tools/lint/lib/checks/license.py
28_LICENSE_PATTERN = re.compile(
29   r'// Copyright( \([C]\))? (\w+) .+\. {1,2}All rights reserved\.[\r\n]{1,2}' +
30   r'(' +
31       r'// This code is governed by the( BSD)? license found in the LICENSE file\.' +
32       r'|' +
33       r'// See LICENSE for details.' +
34       r'|' +
35       r'// Use of this source code is governed by a BSD-style license that can be[\r\n]{1,2}' +
36       r'// found in the LICENSE file\.' +
37       r'|' +
38       r'// See LICENSE or https://github\.com/tc39/test262/blob/(master|HEAD)/LICENSE' +
39   r')' + _BLANK_LINES, re.IGNORECASE)
40
41def yamlAttrParser(testRecord, attrs, name, onerror = print):
42    parsed = yamlLoad(attrs)
43    if parsed is None:
44        onerror("Failed to parse yaml in name %s" % name)
45        return
46
47    for key in parsed:
48        value = parsed[key]
49        if key == "info":
50            key = "commentary"
51        testRecord[key] = value
52
53    if 'flags' in testRecord:
54        for flag in testRecord['flags']:
55            testRecord[flag] = ""
56
57def findLicense(src):
58    match = _LICENSE_PATTERN.search(src)
59    if not match:
60        return None
61
62    return match.group(0)
63
64def findAttrs(src):
65    match = _YAML_PATTERN.search(src)
66    if not match:
67        return (None, None)
68
69    return (match.group(0), match.group(1).strip())
70
71def parseTestRecord(src, name, onerror = print):
72    # Find the license block.
73    header = findLicense(src)
74
75    # Find the YAML frontmatter.
76    (frontmatter, attrs) = findAttrs(src)
77
78    # YAML frontmatter is required for all tests.
79    if frontmatter is None:
80        onerror("Missing frontmatter: %s" % name)
81
82    # The license shuold be placed before the frontmatter and there shouldn't be
83    # any extra content between the license and the frontmatter.
84    if header is not None and frontmatter is not None:
85        headerIdx = src.index(header)
86        frontmatterIdx = src.index(frontmatter)
87        if headerIdx > frontmatterIdx:
88            onerror("Unexpected license after frontmatter: %s" % name)
89
90        # Search for any extra test content, but ignore whitespace only or comment lines.
91        extra = src[headerIdx + len(header) : frontmatterIdx]
92        if extra and any(line.strip() and not line.lstrip().startswith("//") for line in extra.split("\n")):
93            onerror("Unexpected test content between license and frontmatter: %s" % name)
94
95    # Remove the license and YAML parts from the actual test content.
96    test = src
97    if frontmatter is not None:
98        test = test.replace(frontmatter, '')
99    if header is not None:
100        test = test.replace(header, '')
101
102    testRecord = {}
103    testRecord['header'] = header.strip() if header else ''
104    testRecord['test'] = test
105
106    if attrs:
107        yamlAttrParser(testRecord, attrs, name, onerror)
108
109    # Report if the license block is missing in non-generated tests.
110    if header is None and "generated" not in testRecord and "hashbang" not in name:
111        onerror("No license found in: %s" % name)
112
113    return testRecord
114