From e81b73c111034097f9cfd566a0897fd26cbf0e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Thu, 14 Jan 2016 18:08:19 +0100 Subject: [PATCH] Rules: indentation: Rewrite algorithm --- tests/rules/test_colons.py | 8 ++--- tests/rules/test_indentation.py | 47 ++++++++++++++++++++++++---- yamllint/rules/indentation.py | 55 +++++++++++++++++++-------------- 3 files changed, 76 insertions(+), 34 deletions(-) diff --git a/tests/rules/test_colons.py b/tests/rules/test_colons.py index 9b45d32..a1e63d5 100644 --- a/tests/rules/test_colons.py +++ b/tests/rules/test_colons.py @@ -41,8 +41,8 @@ class ColonTestCase(RuleTestCase): ' - o: {k1: v1}\n' ' - p: kdjf\n' ' - q: val0\n' - ' q2:\n' - ' - val1\n' + ' - q2:\n' + ' - val1\n' '...\n', conf) self.check('---\n' 'object:\n' @@ -66,8 +66,8 @@ class ColonTestCase(RuleTestCase): ' val\n' ' - o: {k1: v1}\n' ' - o: {k1: v1}\n' - ' q2:\n' - ' - val1\n' + ' - q2:\n' + ' - val1\n' '...\n', conf) self.check('---\n' 'a: {b: {c: d, e : f}}\n', conf) diff --git a/tests/rules/test_indentation.py b/tests/rules/test_indentation.py index e7cdec9..cdebdf7 100644 --- a/tests/rules/test_indentation.py +++ b/tests/rules/test_indentation.py @@ -118,7 +118,7 @@ class IndentationTestCase(RuleTestCase): self.check('---\n' ' object:\n' ' val: 1\n' - '...\n', conf, problem=(2, 2)) + '...\n', conf, problem1=(2, 2), problem2=(3, 6)) self.check('---\n' '- el1\n' '- el2:\n' @@ -132,8 +132,9 @@ class IndentationTestCase(RuleTestCase): self.check('---\n' ' - el1\n' ' - el2:\n' - ' - subel\n' - '...\n', conf, problem1=(2, 3), problem2=(4, 7)) + ' - subel\n' + '...\n', conf, + problem1=(2, 3), problem2=(3, 3), problem3=(4, 5)) def test_multi_lines(self): self.check('---\n' @@ -154,18 +155,32 @@ class IndentationTestCase(RuleTestCase): '...\n', None) def test_nested_collections(self): + conf = 'indentation: {spaces: 2}' + self.check('---\n' + '- o:\n' + ' k1: v1\n' + '...\n', conf) + self.check('---\n' + '- o:\n' + ' k1: v1\n' + '...\n', conf, problem=(3, 2)) + self.check('---\n' + '- o:\n' + ' k1: v1\n' + '...\n', conf, problem=(3, 4)) + conf = 'indentation: {spaces: 4}' self.check('---\n' '- o:\n' ' k1: v1\n' - '...\n', None) + '...\n', conf) self.check('---\n' '- o:\n' ' k1: v1\n' - '...\n', None, problem=(3, 4)) + '...\n', conf, problem=(3, 4)) self.check('---\n' '- o:\n' ' k1: v1\n' - '...\n', None, problem=(3, 6)) + '...\n', conf, problem=(3, 6)) def test_return(self): self.check('---\n' @@ -189,3 +204,23 @@ class IndentationTestCase(RuleTestCase): # ' c:\n' # ' d:\n' # '...\n', None, problem=(5, 2)) + + def test_first_line(self): + conf = ('indentation: {spaces: 2}\n' + 'document-start: disable\n') + self.check(' a: 1\n', conf, problem=(1, 3)) + + def test_broken_inline_flows(self): + conf = 'indentation: {spaces: 2}' + self.check('---\n' + 'obj: {\n' + ' a: 1,\n' + ' b: 2,\n' + ' c: 3\n' + '}\n', conf, problem1=(4, 4), problem2=(5, 2)) + self.check('---\n' + 'list: [\n' + ' 1,\n' + ' 2,\n' + ' 3\n' + ']\n', conf, problem1=(4, 4), problem2=(5, 2)) diff --git a/yamllint/rules/indentation.py b/yamllint/rules/indentation.py index e31b095..06a731f 100644 --- a/yamllint/rules/indentation.py +++ b/yamllint/rules/indentation.py @@ -25,39 +25,46 @@ CONF = {'spaces': int} def check(conf, token, prev, next): - if isinstance(token, yaml.StreamEndToken): + if isinstance(token, (yaml.StreamStartToken, yaml.StreamEndToken)): return - if (prev is None or isinstance(prev, yaml.StreamStartToken) or - isinstance(prev, yaml.DirectiveToken) or - isinstance(prev, yaml.DocumentStartToken)): - if token.start_mark.column != 0: - yield LintProblem( - token.end_mark.line + 1, token.start_mark.column + 1, - 'found indentation of %d instead of %d' % - (token.start_mark.column, 0)) + # Check if first token in line + if (not isinstance(prev, (yaml.StreamStartToken, yaml.DirectiveToken)) and + token.start_mark.line == prev.end_mark.line): return - if token.start_mark.line > prev.end_mark.line: - buffer = prev.end_mark.buffer + if token.start_mark.column % conf['spaces'] != 0: + yield LintProblem( + token.end_mark.line + 1, token.start_mark.column + 1, + 'indentation is not a multiple of %d' % conf['spaces']) + return + if isinstance(prev, (yaml.StreamStartToken, + yaml.DirectiveToken, + yaml.DocumentStartToken, + yaml.DocumentEndToken)): + indent = 0 + else: + buffer = prev.end_mark.buffer start = buffer.rfind('\n', 0, prev.end_mark.pointer) + 1 - prev_indent = 0 - # YAML recognizes two white space characters: space and tab. - # http://yaml.org/spec/1.2/spec.html#id2775170 - while buffer[start + prev_indent] in ' \t': - prev_indent += 1 + indent = 0 + while buffer[start + indent] == ' ': + indent += 1 - # Discard any leading '- ' - if (buffer[start + prev_indent:start + prev_indent + 2] == '- '): - prev_indent += 2 - while buffer[start + prev_indent] in ' \t': - prev_indent += 1 + if token.start_mark.column > indent: + if not isinstance(prev, (yaml.BlockSequenceStartToken, + yaml.BlockMappingStartToken, + yaml.FlowSequenceStartToken, + yaml.FlowMappingStartToken, + yaml.KeyToken, + yaml.ValueToken)): + yield LintProblem( + token.end_mark.line + 1, token.start_mark.column + 1, + 'unexpected indentation') - if (token.start_mark.column > prev_indent and - token.start_mark.column != prev_indent + conf['spaces']): + elif token.start_mark.column != indent + conf['spaces']: yield LintProblem( token.end_mark.line + 1, token.start_mark.column + 1, 'found indentation of %d instead of %d' % - (token.start_mark.column, prev_indent + conf['spaces'])) + (token.start_mark.column, indent + conf['spaces']))