diff --git a/hcl/hclsyntax/parser.go b/hcl/hclsyntax/parser.go index c35f944..0e4052b 100644 --- a/hcl/hclsyntax/parser.go +++ b/hcl/hclsyntax/parser.go @@ -167,25 +167,15 @@ func (p *parser) finishParsingBodyAttribute(ident Token) (Node, hcl.Diagnostics) p.recoverAfterBodyItem() } else { end := p.Peek() - if end.Type != TokenNewline { + if end.Type != TokenNewline && end.Type != TokenEOF { if !p.recovery { - if end.Type == TokenEOF { - diags = append(diags, &hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Missing newline after attribute definition", - Detail: "A newline is required after an attribute definition at the end of a file.", - Subject: &end.Range, - Context: hcl.RangeBetween(ident.Range, end.Range).Ptr(), - }) - } else { - diags = append(diags, &hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Missing newline after attribute definition", - Detail: "An attribute definition must end with a newline.", - Subject: &end.Range, - Context: hcl.RangeBetween(ident.Range, end.Range).Ptr(), - }) - } + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Missing newline after attribute definition", + Detail: "An attribute definition must end with a newline.", + Subject: &end.Range, + Context: hcl.RangeBetween(ident.Range, end.Range).Ptr(), + }) } endRange = p.PrevRange() p.recoverAfterBodyItem() @@ -294,27 +284,17 @@ Token: cBraceRange := p.PrevRange() eol := p.Peek() - if eol.Type == TokenNewline { + if eol.Type == TokenNewline || eol.Type == TokenEOF { p.Read() // eat newline } else { if !p.recovery { - if eol.Type == TokenEOF { - diags = append(diags, &hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Missing newline after block definition", - Detail: "A newline is required after a block definition at the end of a file.", - Subject: &eol.Range, - Context: hcl.RangeBetween(ident.Range, eol.Range).Ptr(), - }) - } else { - diags = append(diags, &hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Missing newline after block definition", - Detail: "A block definition must end with a newline.", - Subject: &eol.Range, - Context: hcl.RangeBetween(ident.Range, eol.Range).Ptr(), - }) - } + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Missing newline after block definition", + Detail: "A block definition must end with a newline.", + Subject: &eol.Range, + Context: hcl.RangeBetween(ident.Range, eol.Range).Ptr(), + }) } p.recoverAfterBodyItem() } diff --git a/hcl/hclsyntax/parser_test.go b/hcl/hclsyntax/parser_test.go index 5546977..d007c52 100644 --- a/hcl/hclsyntax/parser_test.go +++ b/hcl/hclsyntax/parser_test.go @@ -79,6 +79,54 @@ func TestParseConfig(t *testing.T) { }, }, }, + { + "block {}", + 0, + &Body{ + Attributes: Attributes{}, + Blocks: Blocks{ + &Block{ + Type: "block", + Labels: nil, + Body: &Body{ + Attributes: Attributes{}, + Blocks: Blocks{}, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, + End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, + }, + EndRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 9, Byte: 8}, + End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, + }, + }, + + TypeRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + }, + LabelRanges: nil, + OpenBraceRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, + End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, + }, + CloseBraceRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, + End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, + }, + }, + }, + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, + }, + EndRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 9, Byte: 8}, + End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, + }, + }, + }, { "block {}block {}\n", 1, // missing newline after block definition @@ -405,6 +453,47 @@ block "valid" {} }, }, }, + { + "a = 1", + 0, + &Body{ + Attributes: Attributes{ + "a": { + Name: "a", + Expr: &LiteralValueExpr{ + Val: cty.NumberIntVal(1), + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, + End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + }, + }, + + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + }, + NameRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, + }, + EqualsRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, + End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, + }, + }, + }, + Blocks: Blocks{}, + SrcRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, + End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + }, + EndRange: hcl.Range{ + Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, + }, + }, + }, { "a = \"hello ${true}\"\n", 0,