diff --git a/src/accessor-names/literal-string-line-continuation.case b/src/accessor-names/literal-string-line-continuation.case new file mode 100644 index 0000000000000000000000000000000000000000..24b2291aca1b4571f4839e79c7341fefa09820d3 --- /dev/null +++ b/src/accessor-names/literal-string-line-continuation.case @@ -0,0 +1,22 @@ +// Copyright (C) 2017 Mike Pennisi. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +desc: Computed values as accessor property names (string literal containing LineContinuation) +template: default +info: | + 12.2.6.7 Runtime Semantics: Evaluation + + [...] + + ComputedPropertyName : [ AssignmentExpression ] + + 1. Let exprValue be the result of evaluating AssignmentExpression. + 2. Let propName be ? GetValue(exprValue). + 3. Return ? ToPropertyKey(propName). +---*/ + +//- declareWith +'line\ +Continuation' +//- referenceWith +'lineContinuation' diff --git a/test/language/expressions/class/accessor-name-inst-literal-string-line-terminator.js b/test/language/expressions/class/accessor-name-inst-literal-string-line-continuation.js similarity index 61% rename from test/language/expressions/class/accessor-name-inst-literal-string-line-terminator.js rename to test/language/expressions/class/accessor-name-inst-literal-string-line-continuation.js index 693d03160c0140de225f6cb95390192b154a71bc..9a663d71c55a03eda66781b34c8572510399b4e2 100644 --- a/test/language/expressions/class/accessor-name-inst-literal-string-line-terminator.js +++ b/test/language/expressions/class/accessor-name-inst-literal-string-line-continuation.js @@ -1,9 +1,11 @@ -// Copyright (C) 2017 Mike Pennisi. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. +// This file was procedurally generated from the following sources: +// - src/accessor-names/literal-string-line-continuation.case +// - src/accessor-names/default/cls-expr-inst.template /*--- -description: Computed values as accessor property names (string literal containing a line terminator) (Class expression, instance method) +description: Computed values as accessor property names (string literal containing LineContinuation) (Class expression, instance method) esid: sec-runtime-semantics-classdefinitionevaluation es6id: 14.5.14 +flags: [generated] info: | [...] 21. For each ClassElement m in order from methods @@ -26,14 +28,12 @@ var stringSet; var C = class { get 'line\ -Terminator' -() { return 'get string'; } +Continuation'() { return 'get string'; } set 'line\ -Terminator' -(param) { stringSet = param; } +Continuation'(param) { stringSet = param; } }; -assert.sameValue(C.prototype['lineTerminator'], 'get string'); +assert.sameValue(C.prototype['lineContinuation'], 'get string'); -C.prototype['lineTerminator'] = 'set string'; +C.prototype['lineContinuation'] = 'set string'; assert.sameValue(stringSet, 'set string'); diff --git a/test/language/expressions/class/accessor-name-static-literal-string-line-terminator.js b/test/language/expressions/class/accessor-name-static-literal-string-line-continuation.js similarity index 64% rename from test/language/expressions/class/accessor-name-static-literal-string-line-terminator.js rename to test/language/expressions/class/accessor-name-static-literal-string-line-continuation.js index be1353755082eeb02d5b61504133ead5499afcbb..1ecd300e4da8dae8d47dc9228d5bc1c48eada4fb 100644 --- a/test/language/expressions/class/accessor-name-static-literal-string-line-terminator.js +++ b/test/language/expressions/class/accessor-name-static-literal-string-line-continuation.js @@ -1,9 +1,11 @@ -// Copyright (C) 2017 Mike Pennisi. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. +// This file was procedurally generated from the following sources: +// - src/accessor-names/literal-string-line-continuation.case +// - src/accessor-names/default/cls-expr-static.template /*--- -description: Computed values as accessor property names (string literal containing a line terminator) (Class expression, static method) +description: Computed values as accessor property names (string literal containing LineContinuation) (Class expression, static method) esid: sec-runtime-semantics-classdefinitionevaluation es6id: 14.5.14 +flags: [generated] info: | [...] 21. For each ClassElement m in order from methods @@ -28,14 +30,12 @@ var stringSet; var C = class { static get 'line\ -Terminator' -() { return 'get string'; } +Continuation'() { return 'get string'; } static set 'line\ -Terminator' -(param) { stringSet = param; } +Continuation'(param) { stringSet = param; } }; -assert.sameValue(C['lineTerminator'], 'get string'); +assert.sameValue(C['lineContinuation'], 'get string'); -C['lineTerminator'] = 'set string'; +C['lineContinuation'] = 'set string'; assert.sameValue(stringSet, 'set string'); diff --git a/test/language/expressions/object/accessor-name-literal-string-line-terminator.js b/test/language/expressions/object/accessor-name-literal-string-line-continuation.js similarity index 64% rename from test/language/expressions/object/accessor-name-literal-string-line-terminator.js rename to test/language/expressions/object/accessor-name-literal-string-line-continuation.js index bb230c3ad41db0e3c4bcd03c3eecadcc263a30f8..546a46ff8d833c27b70acc9a18c44c7f49ba8cf6 100644 --- a/test/language/expressions/object/accessor-name-literal-string-line-terminator.js +++ b/test/language/expressions/object/accessor-name-literal-string-line-continuation.js @@ -1,9 +1,11 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. +// This file was procedurally generated from the following sources: +// - src/accessor-names/literal-string-line-continuation.case +// - src/accessor-names/default/obj.template /*--- -description: Computed values as accessor property names (string literal containing a line terminator) (Object initializer) +description: Computed values as accessor property names (string literal containing LineContinuation) (Object initializer) esid: sec-object-initializer-runtime-semantics-evaluation es6id: 12.2.6.8 +flags: [generated] info: | ObjectLiteral : { PropertyDefinitionList } @@ -27,14 +29,12 @@ info: | var stringSet; var obj = { get ['line\ -Terminator' -]() { return 'get string'; }, +Continuation']() { return 'get string'; }, set ['line\ -Terminator' -](param) { stringSet = param; } +Continuation'](param) { stringSet = param; } }; -assert.sameValue(obj['lineTerminator'], 'get string'); +assert.sameValue(obj['lineContinuation'], 'get string'); -obj['lineTerminator'] = 'set string'; +obj['lineContinuation'] = 'set string'; assert.sameValue(stringSet, 'set string'); diff --git a/test/language/statements/class/accessor-name-inst-literal-string-line-terminator.js b/test/language/statements/class/accessor-name-inst-literal-string-line-continuation.js similarity index 61% rename from test/language/statements/class/accessor-name-inst-literal-string-line-terminator.js rename to test/language/statements/class/accessor-name-inst-literal-string-line-continuation.js index a9fa0c268c7d8fee46770add05dfbbbda84104aa..12dabf5012c5afa791e4f10b67d4c488c1d1c2fe 100644 --- a/test/language/statements/class/accessor-name-inst-literal-string-line-terminator.js +++ b/test/language/statements/class/accessor-name-inst-literal-string-line-continuation.js @@ -1,9 +1,11 @@ -// Copyright (C) 2017 Mike Pennisi. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. +// This file was procedurally generated from the following sources: +// - src/accessor-names/literal-string-line-continuation.case +// - src/accessor-names/default/cls-decl-inst.template /*--- -description: Computed values as accessor property names (string literal containing a line terminator) (Class declaration, instance method) +description: Computed values as accessor property names (string literal containing LineContinuation) (Class declaration, instance method) esid: sec-runtime-semantics-classdefinitionevaluation es6id: 14.5.14 +flags: [generated] info: | [...] 21. For each ClassElement m in order from methods @@ -26,14 +28,12 @@ var stringSet; class C { get 'line\ -Terminator' -() { return 'get string'; } +Continuation'() { return 'get string'; } set 'line\ -Terminator' -(param) { stringSet = param; } +Continuation'(param) { stringSet = param; } } -assert.sameValue(C.prototype['lineTerminator'], 'get string'); +assert.sameValue(C.prototype['lineContinuation'], 'get string'); -C.prototype['lineTerminator'] = 'set string'; +C.prototype['lineContinuation'] = 'set string'; assert.sameValue(stringSet, 'set string'); diff --git a/test/language/statements/class/accessor-name-static-literal-string-line-terminator.js b/test/language/statements/class/accessor-name-static-literal-string-line-continuation.js similarity index 63% rename from test/language/statements/class/accessor-name-static-literal-string-line-terminator.js rename to test/language/statements/class/accessor-name-static-literal-string-line-continuation.js index b68f24df8c95ccbdff4c4aeb610c2027e681094f..b08c8cd636aadeecc70806e1540e76500f2cfdca 100644 --- a/test/language/statements/class/accessor-name-static-literal-string-line-terminator.js +++ b/test/language/statements/class/accessor-name-static-literal-string-line-continuation.js @@ -1,9 +1,11 @@ -// Copyright (C) 2017 Mike Pennisi. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. +// This file was procedurally generated from the following sources: +// - src/accessor-names/literal-string-line-continuation.case +// - src/accessor-names/default/cls-decl-static.template /*--- -description: Computed values as accessor property names (string literal containing a line terminator) (Class declaration, static method) +description: Computed values as accessor property names (string literal containing LineContinuation) (Class declaration, static method) esid: sec-runtime-semantics-classdefinitionevaluation es6id: 14.5.14 +flags: [generated] info: | [...] 21. For each ClassElement m in order from methods @@ -28,14 +30,12 @@ var stringSet; class C { static get 'line\ -Terminator' -() { return 'get string'; } +Continuation'() { return 'get string'; } static set 'line\ -Terminator' -(param) { stringSet = param; } +Continuation'(param) { stringSet = param; } } -assert.sameValue(C['lineTerminator'], 'get string'); +assert.sameValue(C['lineContinuation'], 'get string'); -C['lineTerminator'] = 'set string'; +C['lineContinuation'] = 'set string'; assert.sameValue(stringSet, 'set string'); diff --git a/tools/generation/lib/template.py b/tools/generation/lib/template.py index 609724b6f30270837a751c3ee45262d01a17cbfe..53bd03ba1908b5882adb03c1c7ec19399d692bb1 100644 --- a/tools/generation/lib/template.py +++ b/tools/generation/lib/template.py @@ -11,18 +11,40 @@ from test import Test indentPattern = re.compile(r'^(\s*)') interpolatePattern = re.compile(r'\{\s*(\S+)\s*\}') -def indent(text, prefix = ' '): +def indent(text, prefix = ' ', js_value = False): '''Prefix a block of text (as defined by the "line break" control - character) with some character sequence.''' + character) with some character sequence. + + :param prefix: String value to insert before each line + :param js_value: If True, the text will be interpreted as a JavaScript + value, meaning that indentation will not occur for lines that would + effect the runtime value; defaults to False + ''' if isinstance(text, list): lines = text else: lines = text.split('\n') - indented = map( - lambda line: line if len(line) == 0 else prefix + line, - lines) + indented = [prefix + lines[0]] + str_char = None + + for line in lines[1:]: + # Determine if the beginning of the current line is part of some + # previously-opened literal value. + if js_value: + for char in indented[-1]: + if char == str_char: + str_char = None + elif str_char is None and char in '\'"`': + str_char = char + + # Do not indent the current line if it is a continuation of a literal + # value or if it is empty. + if str_char or len(line) == 0: + indented.append(line) + else: + indented.append(prefix + line) return '\n'.join(indented) @@ -90,7 +112,7 @@ class Template: value = value.replace('\n', '\\\n') source = source[:region['firstchar']] + \ - indent(value, whitespace).lstrip() + \ + indent(value, whitespace, True).lstrip() + \ source[region['lastchar']:] setup = context['regions'].get('setup') diff --git a/tools/generation/test/expected/indentation/spaces-indent-code.js b/tools/generation/test/expected/indentation/spaces-indent-code.js new file mode 100644 index 0000000000000000000000000000000000000000..41fa3c22d7d6f9379afc4b6f17d035c8a7bead4a --- /dev/null +++ b/tools/generation/test/expected/indentation/spaces-indent-code.js @@ -0,0 +1,19 @@ +// This file was procedurally generated from the following sources: +// - tools/generation/test/fixtures/indent-code.case +// - tools/generation/test/fixtures/indentation/spaces.template +/*--- +description: Multiple lines of code (Preserving "soft" indentation across newlines) +flags: [generated] +---*/ + +(function() { + 'These literals are each contained on a single line...'; + "...which means they may be indented..."; + `...without effecting the semantics of the generated source code.`; + + if (true) { + 'These literals are each contained on a single line...'; + "...which means they may be indented..."; + `...without effecting the semantics of the generated source code.`; + } +}()); diff --git a/tools/generation/test/expected/indentation/spaces-indent-string-continuation.js b/tools/generation/test/expected/indentation/spaces-indent-string-continuation.js new file mode 100644 index 0000000000000000000000000000000000000000..da98f99a3fe48560c6504d917944c010a4466f77 --- /dev/null +++ b/tools/generation/test/expected/indentation/spaces-indent-string-continuation.js @@ -0,0 +1,19 @@ +// This file was procedurally generated from the following sources: +// - tools/generation/test/fixtures/indent-string-continuation.case +// - tools/generation/test/fixtures/indentation/spaces.template +/*--- +description: Multiline string via a line continuation character (Preserving "soft" indentation across newlines) +flags: [generated] +---*/ + +(function() { + 'this string is declared across multiple lines\ +\ +which disqualifies it as a candidate for indentation'; + + if (true) { + 'this string is declared across multiple lines\ +\ +which disqualifies it as a candidate for indentation'; + } +}()); diff --git a/tools/generation/test/expected/indentation/spaces-indent-string-template.js b/tools/generation/test/expected/indentation/spaces-indent-string-template.js new file mode 100644 index 0000000000000000000000000000000000000000..504b9a6e646e4e7a6820ec6dc2ee8f87d527692a --- /dev/null +++ b/tools/generation/test/expected/indentation/spaces-indent-string-template.js @@ -0,0 +1,21 @@ +// This file was procedurally generated from the following sources: +// - tools/generation/test/fixtures/indent-string-template.case +// - tools/generation/test/fixtures/indentation/spaces.template +/*--- +description: String template spanning multiple lines (Preserving "soft" indentation across newlines) +flags: [generated] +---*/ + +(function() { + `this string template is declared across multiple lines + +which disqualifies it as a candidate for indentation +it also happens to contain ' and ".`; + + if (true) { + `this string template is declared across multiple lines + +which disqualifies it as a candidate for indentation +it also happens to contain ' and ".`; + } +}()); diff --git a/tools/generation/test/expected/indentation/tabs-indent-code.js b/tools/generation/test/expected/indentation/tabs-indent-code.js new file mode 100644 index 0000000000000000000000000000000000000000..ccfc7c71d1bb119e3b7a031907b7ed34afebbc47 --- /dev/null +++ b/tools/generation/test/expected/indentation/tabs-indent-code.js @@ -0,0 +1,19 @@ +// This file was procedurally generated from the following sources: +// - tools/generation/test/fixtures/indent-code.case +// - tools/generation/test/fixtures/indentation/tabs.template +/*--- +description: Multiple lines of code (Preserving "hard" indentation across newlines) +flags: [generated] +---*/ + +(function() { + 'These literals are each contained on a single line...'; + "...which means they may be indented..."; + `...without effecting the semantics of the generated source code.`; + + if (true) { + 'These literals are each contained on a single line...'; + "...which means they may be indented..."; + `...without effecting the semantics of the generated source code.`; + } +}()); diff --git a/tools/generation/test/expected/indentation/tabs-indent-string-continuation.js b/tools/generation/test/expected/indentation/tabs-indent-string-continuation.js new file mode 100644 index 0000000000000000000000000000000000000000..a4719748e328cb90fb0b343f685b95a4af4bd84c --- /dev/null +++ b/tools/generation/test/expected/indentation/tabs-indent-string-continuation.js @@ -0,0 +1,19 @@ +// This file was procedurally generated from the following sources: +// - tools/generation/test/fixtures/indent-string-continuation.case +// - tools/generation/test/fixtures/indentation/tabs.template +/*--- +description: Multiline string via a line continuation character (Preserving "hard" indentation across newlines) +flags: [generated] +---*/ + +(function() { + 'this string is declared across multiple lines\ +\ +which disqualifies it as a candidate for indentation'; + + if (true) { + 'this string is declared across multiple lines\ +\ +which disqualifies it as a candidate for indentation'; + } +}()); diff --git a/tools/generation/test/expected/indentation/tabs-indent-string-template.js b/tools/generation/test/expected/indentation/tabs-indent-string-template.js new file mode 100644 index 0000000000000000000000000000000000000000..b40bd7578d7282c47c5ead3b1dec01a0e90b0d32 --- /dev/null +++ b/tools/generation/test/expected/indentation/tabs-indent-string-template.js @@ -0,0 +1,21 @@ +// This file was procedurally generated from the following sources: +// - tools/generation/test/fixtures/indent-string-template.case +// - tools/generation/test/fixtures/indentation/tabs.template +/*--- +description: String template spanning multiple lines (Preserving "hard" indentation across newlines) +flags: [generated] +---*/ + +(function() { + `this string template is declared across multiple lines + +which disqualifies it as a candidate for indentation +it also happens to contain ' and ".`; + + if (true) { + `this string template is declared across multiple lines + +which disqualifies it as a candidate for indentation +it also happens to contain ' and ".`; + } +}()); diff --git a/tools/generation/test/fixtures/indent-code.case b/tools/generation/test/fixtures/indent-code.case new file mode 100644 index 0000000000000000000000000000000000000000..e10f49a8df73b89a067bfa03208827f8af697f94 --- /dev/null +++ b/tools/generation/test/fixtures/indent-code.case @@ -0,0 +1,11 @@ +// Copyright (C) 2017 Mike Pennisi. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +template: indentation +desc: Multiple lines of code +---*/ + +//- value +'These literals are each contained on a single line...'; +"...which means they may be indented..."; +`...without effecting the semantics of the generated source code.`; diff --git a/tools/generation/test/fixtures/indent-string-continuation.case b/tools/generation/test/fixtures/indent-string-continuation.case new file mode 100644 index 0000000000000000000000000000000000000000..e22d9690c97f2bb71a0c71b3da322b730c24b556 --- /dev/null +++ b/tools/generation/test/fixtures/indent-string-continuation.case @@ -0,0 +1,11 @@ +// Copyright (C) 2017 Mike Pennisi. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +template: indentation +desc: Multiline string via a line continuation character +---*/ + +//- value +'this string is declared across multiple lines\ +\ +which disqualifies it as a candidate for indentation'; diff --git a/tools/generation/test/fixtures/indent-string-template.case b/tools/generation/test/fixtures/indent-string-template.case new file mode 100644 index 0000000000000000000000000000000000000000..56daee9a14f49009cac3063d12457f70976af9f5 --- /dev/null +++ b/tools/generation/test/fixtures/indent-string-template.case @@ -0,0 +1,12 @@ +// Copyright (C) 2017 Mike Pennisi. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +template: indentation +desc: String template spanning multiple lines +---*/ + +//- value +`this string template is declared across multiple lines + +which disqualifies it as a candidate for indentation +it also happens to contain ' and ".`; diff --git a/tools/generation/test/fixtures/indentation/spaces.template b/tools/generation/test/fixtures/indentation/spaces.template new file mode 100644 index 0000000000000000000000000000000000000000..0796dac5a00ef709f460c716ec0eb11600a46024 --- /dev/null +++ b/tools/generation/test/fixtures/indentation/spaces.template @@ -0,0 +1,14 @@ +// Copyright (C) 2017 Mike Pennisi. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +name: Preserving "soft" indentation across newlines +path: indentation/spaces- +---*/ + +(function() { + /*{ value }*/ + + if (true) { + /*{ value }*/ + } +}()); diff --git a/tools/generation/test/fixtures/indentation/tabs.template b/tools/generation/test/fixtures/indentation/tabs.template new file mode 100644 index 0000000000000000000000000000000000000000..87130571f538268aff50f5f4bbdaf88cc2e31c49 --- /dev/null +++ b/tools/generation/test/fixtures/indentation/tabs.template @@ -0,0 +1,14 @@ +// Copyright (C) 2017 Mike Pennisi. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +name: Preserving "hard" indentation across newlines +path: indentation/tabs- +---*/ + +(function() { + /*{ value }*/ + + if (true) { + /*{ value }*/ + } +}()); diff --git a/tools/generation/test/run.py b/tools/generation/test/run.py index 9fc9ee3a1b8c4d6fa83326bd233c8e667215f24a..c21efa1b83dab8f5ab8a21927d5c7107cbe48627 100755 --- a/tools/generation/test/run.py +++ b/tools/generation/test/run.py @@ -59,5 +59,14 @@ class TestGeneration(unittest.TestCase): self.assertEqual(result['returncode'], 0) self.compareTrees('negative') + def test_indentation(self): + result = self.fixture('indent-code.case') + self.assertEqual(result['returncode'], 0) + result = self.fixture('indent-string-continuation.case') + self.assertEqual(result['returncode'], 0) + result = self.fixture('indent-string-template.case') + self.assertEqual(result['returncode'], 0) + self.compareTrees('indentation') + if __name__ == '__main__': unittest.main()