diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b3b2cef6832bd1a650415abae5e5c0ee4e10eef..ab40f1128c9399a6317c6630174559ac302428ec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -145,7 +145,7 @@ This tag is for boolean properties associated with the test. #### features **features**: [list] -Some tests require the use of language features that are not directly described by the test file's location in the directory structure. These features should be formally listed here. +Some tests require the use of language features that are not directly described by the test file's location in the directory structure. These features should be specified with this tag. See the `features.txt` file for a complete list of available values. ## Test Environment diff --git a/FEATURES.md b/FEATURES.md deleted file mode 100644 index 78d4e6694ff0e3bd1d211f5301ec5510c39046dc..0000000000000000000000000000000000000000 --- a/FEATURES.md +++ /dev/null @@ -1,16 +0,0 @@ -# Feature Flags - -Current, post-ES2015, flags used to identify new features: - -- `async-functions`: Async Functions -- `async-iteration`: [Async Iteration and Generators](https://github.com/tc39/proposal-async-iteration) -- `object-rest`: [Object rest/spread properties](https://github.com/tc39/proposal-object-rest-spread) -- `object-spread`: [Object rest/spread properties](https://github.com/tc39/proposal-object-rest-spread) -- `regexp-dotall`: [RegExp s (dotAll) flag](https://github.com/tc39/proposal-regexp-dotall-flag) -- `regexp-lookbehind`: [RegExp lookBehind](https://github.com/tc39/proposal-regexp-lookbehind) -- `regexp-named-groups`: [RegExp named groups capturing]() -- `regexp-unicode-property-escapes`: [RegExp Unicode Property Escapes](https://github.com/tc39/proposal-regexp-unicode-property-escapes) -- `SharedArrayBuffer` -- `Symbol.asyncIterator` - -While it's mostly optional when already in a current released specification, it's highly recommended to reuse the features flags for any matching case in new tests. diff --git a/features.txt b/features.txt new file mode 100644 index 0000000000000000000000000000000000000000..41323de4edf37433a32b660f70b4a3db4d1c93a0 --- /dev/null +++ b/features.txt @@ -0,0 +1,99 @@ +# Proposed language features +# +# This project accepts tests for language proposals that have reached stage 3 +# in TC39's standardization process. Those tests should be annotated with a +# dedicated feature flag so that consumers may more easily omit them as +# necessary. +# +# https://github.com/tc39/process-document + +# Async Iteration and Generators +# https://github.com/tc39/proposal-async-iteration +async-iteration +Symbol.asyncIterator + +# Object rest/spread properties +# https://github.com/tc39/proposal-object-rest-spread +object-rest +object-spread + +# RegExp s (dotAll) flag +# https://github.com/tc39/proposal-regexp-dotall-flag +regexp-dotall + +# RegExp lookBehind +# https://github.com/tc39/proposal-regexp-lookbehind +regexp-lookbehind + +# RegExp named groups capturing +# https://github.com/tc39/proposal-regexp-named-groups +regexp-named-groups + +# RegExp Unicode Property Escapes +# https://github.com/tc39/proposal-regexp-unicode-property-escapes +regexp-unicode-property-escapes + +# Shared Memory and atomics +# https://github.com/tc39/ecmascript_sharedmem +SharedArrayBuffer + +# Standard language features +# +# Language features that have been included in a published version of the +# ECMA-262 specification. These flags are largely maintained for historical +# reasons, though their use for relatively new features (i.e. prior to +# availability across major implementations) is appreciated. + +ArrayBuffer +Array.prototype.values +arrow-function +async-functions +caller +class +const +DataView +DataView.prototype.getFloat32 +DataView.prototype.getFloat64 +DataView.prototype.getInt16 +DataView.prototype.getInt32 +DataView.prototype.getInt8 +DataView.prototype.getUint16 +DataView.prototype.getUint32 +DataView.prototype.setUint8 +default-arg +default-parameters +destructuring-binding +Float64Array +generator +generators +Int8Array +let +Map +new.target +Proxy +Reflect +Reflect.construct +Reflect.set +Reflect.setPrototypeOf +Set +String#endsWith +String#includes +super +Symbol +Symbol.hasInstance +Symbol.isConcatSpreadable +Symbol.iterator +Symbol.match +Symbol.replace +Symbol.search +Symbol.species +Symbol.split +Symbol.toPrimitive +Symbol.toStringTag +Symbol.unscopables +tail-call-optimization +template +TypedArray +Uint8Array +WeakMap +WeakSet diff --git a/tools/lint/lib/checks/features.py b/tools/lint/lib/checks/features.py new file mode 100644 index 0000000000000000000000000000000000000000..f7cae4894f96e7f9d170fb38b1653149c6112141 --- /dev/null +++ b/tools/lint/lib/checks/features.py @@ -0,0 +1,38 @@ +from ..check import Check + +_REQUIRED_FIELDS = set(['description']) +_OPTIONAL_FIELDS = set([ + 'author', 'es5id', 'es6id', 'esid', 'features', 'flags', 'includes', + 'info', 'negative', 'timeout' +]) +_VALID_FIELDS = _REQUIRED_FIELDS | _OPTIONAL_FIELDS + +class CheckFeatures(Check): + '''Ensure tests specify only `features` from a list of valid values.''' + ID = 'FEATURES' + + def __init__(self, filename): + with open(filename, 'r') as f: + self.valid_features = self._parse(f.read()) + + @staticmethod + def _parse(content): + features = [] + for line in content.split(): + if not line or line.startswith('#'): + continue + features.append(line) + return features + + def run(self, name, meta, source): + if not meta or 'features' not in meta: + return + + features = meta['features'] + + if len(features) == 0: + return 'If present, the `features` tag must have at least one member' + + for feature in features: + if feature not in self.valid_features: + return 'Unrecognized feature: "%s"' % feature diff --git a/tools/lint/lint.py b/tools/lint/lint.py index b26569516dc1cc55639a69f9a3e30b446bdd8a64..9cdbca474a87062b4f2f3db416d14a3ea8ed0579 100755 --- a/tools/lint/lint.py +++ b/tools/lint/lint.py @@ -6,6 +6,7 @@ import argparse import sys from lib.collect_files import collect_files +from lib.checks.features import CheckFeatures from lib.checks.frontmatter import CheckFrontmatter from lib.checks.license import CheckLicense from lib.eprint import eprint @@ -20,7 +21,7 @@ parser.add_argument('path', nargs='+', help='file name or directory of files to lint') -checks = [CheckFrontmatter(), CheckLicense()] +checks = [CheckFrontmatter(), CheckFeatures('features.txt'), CheckLicense()] def lint(file_names): errors = dict() diff --git a/tools/lint/test/fixtures/features_empty.js b/tools/lint/test/fixtures/features_empty.js new file mode 100644 index 0000000000000000000000000000000000000000..47322aa5919c9342581dcadb96e61339d39be927 --- /dev/null +++ b/tools/lint/test/fixtures/features_empty.js @@ -0,0 +1,11 @@ +FEATURES +^ expected errors | v input +// Copyright (C) 2017 Mike Pennisi. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-assignment-operators-static-semantics-early-errors +description: Minimal test +features: [] +---*/ + +// empty diff --git a/tools/lint/test/fixtures/features_unrecognized.js b/tools/lint/test/fixtures/features_unrecognized.js new file mode 100644 index 0000000000000000000000000000000000000000..aec50a950c2d8263c1aa6933650360a96ea2012a --- /dev/null +++ b/tools/lint/test/fixtures/features_unrecognized.js @@ -0,0 +1,11 @@ +FEATURES +^ expected errors | v input +// Copyright (C) 2017 Mike Pennisi. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-assignment-operators-static-semantics-early-errors +description: Minimal test +features: [not-a-valid-feature] +---*/ + +// empty diff --git a/tools/lint/test/fixtures/features_valid.js b/tools/lint/test/fixtures/features_valid.js new file mode 100644 index 0000000000000000000000000000000000000000..1508f570abd174f125969a4a52dd6512899efbf6 --- /dev/null +++ b/tools/lint/test/fixtures/features_valid.js @@ -0,0 +1,10 @@ +^ expected errors | v input +// Copyright (C) 2017 Mike Pennisi. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-assignment-operators-static-semantics-early-errors +description: Minimal test +features: [async-functions, object-spread] +---*/ + +async function f({ ...a }) {}