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 0000000000..24b2291aca --- /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 693d03160c..9a663d71c5 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 be13537550..1ecd300e4d 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 bb230c3ad4..546a46ff8d 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 a9fa0c268c..12dabf5012 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 b68f24df8c..b08c8cd636 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 609724b6f3..53bd03ba19 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 0000000000..41fa3c22d7 --- /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 0000000000..da98f99a3f --- /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 0000000000..504b9a6e64 --- /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 0000000000..ccfc7c71d1 --- /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 0000000000..a4719748e3 --- /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 0000000000..b40bd7578d --- /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 0000000000..e10f49a8df --- /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 0000000000..e22d9690c9 --- /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 0000000000..56daee9a14 --- /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 0000000000..0796dac5a0 --- /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 0000000000..87130571f5 --- /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 9fc9ee3a1b..c21efa1b83 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()