Skip to content

Commit

Permalink
Fix "attribute" vs "argument" terminology in diagnostics
Browse files Browse the repository at this point in the history
During implementation of HCL in other applications, it became clear that
the overloading of the word "attribute" to mean both a key/value pair in
a body and an element within an object value creates confusion.

It's too late to change that in the HCL Go API now, but here we at least
update the diagnostic messages. The new convention is that a key/value
pair within a block is now called an "argument", while an element of an
object is still called an "attribute".

It is unfortunate that the Go-facing API still uses the word "attribute"
for both, but the user experience is the most important thing and in
practice many applications will treat block arguments as one way to set
the attributes of some object anyway, and in that case arguments can be
thought of as the subset of attributes of an object whose values come
from that object's associated block.

This also includes a few other minor terminology tweaks in the diagnostic
messages the reflect how our lexicon has evolved during development and
authoring of user-facing documentation.
  • Loading branch information
apparentlymart committed Jul 18, 2018
1 parent 966851f commit 41cff85
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 49 deletions.
40 changes: 20 additions & 20 deletions hcl/hclsyntax/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Token:
Severity: hcl.DiagError,
Summary: "Attribute redefined",
Detail: fmt.Sprintf(
"The attribute %q was already defined at %s. Each attribute may be defined only once.",
"The argument %q was already set at %s. Each argument may be set only once.",
titem.Name, existing.NameRange.String(),
),
Subject: &titem.NameRange,
Expand All @@ -80,15 +80,15 @@ Token:
if bad.Type == TokenOQuote {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid attribute name",
Detail: "Attribute names must not be quoted.",
Summary: "Invalid argument name",
Detail: "Argument names must not be quoted.",
Subject: &bad.Range,
})
} else {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Attribute or block definition required",
Detail: "An attribute or block definition is required here.",
Summary: "Argument or block definition required",
Detail: "An argument or block definition is required here.",
Subject: &bad.Range,
})
}
Expand Down Expand Up @@ -120,8 +120,8 @@ func (p *parser) ParseBodyItem() (Node, hcl.Diagnostics) {
return nil, hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "Attribute or block definition required",
Detail: "An attribute or block definition is required here.",
Summary: "Argument or block definition required",
Detail: "An argument or block definition is required here.",
Subject: &ident.Range,
},
}
Expand All @@ -139,8 +139,8 @@ func (p *parser) ParseBodyItem() (Node, hcl.Diagnostics) {
return nil, hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "Attribute or block definition required",
Detail: "An attribute or block definition is required here. To define an attribute, use the equals sign \"=\" to introduce the attribute value.",
Summary: "Argument or block definition required",
Detail: "An argument or block definition is required here. To set an argument, use the equals sign \"=\" to introduce the argument value.",
Subject: &ident.Range,
},
}
Expand Down Expand Up @@ -171,8 +171,8 @@ func (p *parser) finishParsingBodyAttribute(ident Token) (Node, hcl.Diagnostics)
if !p.recovery {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing newline after attribute definition",
Detail: "An attribute definition must end with a newline.",
Summary: "Missing newline after argument",
Detail: "An argument definition must end with a newline.",
Subject: &end.Range,
Context: hcl.RangeBetween(ident.Range, end.Range).Ptr(),
})
Expand Down Expand Up @@ -244,7 +244,7 @@ Token:
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid block definition",
Detail: "The equals sign \"=\" indicates an attribute definition, and must not be used when defining a block.",
Detail: "The equals sign \"=\" indicates an argument definition, and must not be used when defining a block.",
Subject: &tok.Range,
Context: hcl.RangeBetween(ident.Range, tok.Range).Ptr(),
})
Expand Down Expand Up @@ -1135,16 +1135,16 @@ func (p *parser) parseObjectCons() (Expression, hcl.Diagnostics) {
if next.Type == TokenNewline || next.Type == TokenComma {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing item value",
Detail: "Expected an item value, introduced by an equals sign (\"=\").",
Summary: "Missing attribute value",
Detail: "Expected an attribute value, introduced by an equals sign (\"=\").",
Subject: &next.Range,
Context: hcl.RangeBetween(open.Range, next.Range).Ptr(),
})
} else {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing key/value separator",
Detail: "Expected an equals sign (\"=\") to mark the beginning of the item value.",
Detail: "Expected an equals sign (\"=\") to mark the beginning of the attribute value.",
Subject: &next.Range,
Context: hcl.RangeBetween(open.Range, next.Range).Ptr(),
})
Expand Down Expand Up @@ -1182,8 +1182,8 @@ func (p *parser) parseObjectCons() (Expression, hcl.Diagnostics) {
if !p.recovery {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing item separator",
Detail: "Expected a newline or comma to mark the beginning of the next item.",
Summary: "Missing attribute separator",
Detail: "Expected a newline or comma to mark the beginning of the next attribute.",
Subject: &next.Range,
Context: hcl.RangeBetween(open.Range, next.Range).Ptr(),
})
Expand Down Expand Up @@ -1277,7 +1277,7 @@ func (p *parser) finishParsingForExpr(open Token) (Expression, hcl.Diagnostics)
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid 'for' expression",
Detail: "For expression requires 'in' keyword after names.",
Detail: "For expression requires the 'in' keyword after its name declarations.",
Subject: p.Peek().Range.Ptr(),
Context: hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),
})
Expand Down Expand Up @@ -1305,7 +1305,7 @@ func (p *parser) finishParsingForExpr(open Token) (Expression, hcl.Diagnostics)
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid 'for' expression",
Detail: "For expression requires colon after collection expression.",
Detail: "For expression requires a colon after the collection expression.",
Subject: p.Peek().Range.Ptr(),
Context: hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),
})
Expand Down Expand Up @@ -1459,7 +1459,7 @@ Token:
case TokenTemplateControl, TokenTemplateInterp:
which := "$"
if tok.Type == TokenTemplateControl {
which = "!"
which = "%"
}

diags = append(diags, &hcl.Diagnostic{
Expand Down
2 changes: 1 addition & 1 deletion hcl/hclsyntax/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ func checkInvalidTokens(tokens Tokens) hcl.Diagnostics {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid character",
Detail: "The \";\" character is not valid. Use newlines to separate attributes and blocks, and commas to separate items in collection values.",
Detail: "The \";\" character is not valid. Use newlines to separate arguments and blocks, and commas to separate items in collection values.",
Subject: &tok.Range,
})

Expand Down
18 changes: 9 additions & 9 deletions hcl/json/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func parseValue(p *peeker) (node, hcl.Diagnostics) {
return wrapInvalid(nil, hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "Missing attribute value",
Summary: "Missing JSON value",
Detail: "A JSON value must start with a brace, a bracket, a number, a string, or a keyword.",
Subject: &tok.Range,
},
Expand Down Expand Up @@ -144,8 +144,8 @@ Token:
if !ok {
return nil, diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid object attribute name",
Detail: "A JSON object attribute name must be a string",
Summary: "Invalid object property name",
Detail: "A JSON object property name must be a string",
Subject: keyNode.StartRange().Ptr(),
})
}
Expand All @@ -171,16 +171,16 @@ Token:
// Possible confusion with native HCL syntax.
return nil, diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing attribute value colon",
Summary: "Missing property value colon",
Detail: "JSON uses a colon as its name/value delimiter, not an equals sign.",
Subject: &colon.Range,
})
}

return nil, diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing attribute value colon",
Detail: "A colon must appear between an object attribute's name and its value.",
Summary: "Missing property value colon",
Detail: "A colon must appear between an object property's name and its value.",
Subject: &colon.Range,
})
}
Expand All @@ -205,7 +205,7 @@ Token:
return nil, diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Trailing comma in object",
Detail: "JSON does not permit a trailing comma after the final attribute in an object.",
Detail: "JSON does not permit a trailing comma after the final property in an object.",
Subject: &comma.Range,
})
}
Expand Down Expand Up @@ -234,7 +234,7 @@ Token:
return nil, diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing attribute seperator comma",
Detail: "A comma must appear between each attribute declaration in an object.",
Detail: "A comma must appear between each property definition in an object.",
Subject: p.Peek().Range.Ptr(),
})
}
Expand Down Expand Up @@ -301,7 +301,7 @@ Token:
return nil, diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Trailing comma in array",
Detail: "JSON does not permit a trailing comma after the final attribute in an array.",
Detail: "JSON does not permit a trailing comma after the final value in an array.",
Subject: &comma.Range,
})
}
Expand Down
18 changes: 9 additions & 9 deletions hcl/json/structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (b *body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostic
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Extraneous JSON object property",
Detail: fmt.Sprintf("No attribute or block type is named %q.%s", k, suggestion),
Detail: fmt.Sprintf("No argument or block type is named %q.%s", k, suggestion),
Subject: &attr.NameRange,
Context: attr.Range().Ptr(),
})
Expand Down Expand Up @@ -114,8 +114,8 @@ func (b *body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Bod
if existing, exists := content.Attributes[attrName]; exists {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Duplicate attribute definition",
Detail: fmt.Sprintf("The attribute %q was already defined at %s.", attrName, existing.Range),
Summary: "Duplicate argument",
Detail: fmt.Sprintf("The argument %q was already set at %s.", attrName, existing.Range),
Subject: &jsonAttr.NameRange,
Context: jsonAttr.Range().Ptr(),
})
Expand Down Expand Up @@ -149,8 +149,8 @@ func (b *body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Bod
if _, defined := content.Attributes[attrS.Name]; !defined {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing required attribute",
Detail: fmt.Sprintf("The attribute %q is required, but no definition was found.", attrS.Name),
Summary: "Missing required argument",
Detail: fmt.Sprintf("The argument %q is required, but no definition was found.", attrS.Name),
Subject: b.MissingItemRange().Ptr(),
})
}
Expand All @@ -175,7 +175,7 @@ func (b *body) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Incorrect JSON value type",
Detail: "A JSON object is required here, defining the attributes for this block.",
Detail: "A JSON object is required here, setting the arguments for this block.",
Subject: b.val.StartRange().Ptr(),
})
return attrs, diags
Expand All @@ -197,7 +197,7 @@ func (b *body) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Duplicate attribute definition",
Detail: fmt.Sprintf("The attribute %q was already defined at %s.", name, existing.Range),
Detail: fmt.Sprintf("The argument %q was already set at %s.", name, existing.Range),
Subject: &jsonAttr.NameRange,
})
continue
Expand Down Expand Up @@ -345,7 +345,7 @@ func (b *body) collectDeepAttrs(v node, labelName *string) ([]*objectAttr, hcl.D
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Incorrect JSON value type",
Detail: "A JSON object is required here, to define attributes and child blocks.",
Detail: "A JSON object is required here, to define arguments and child blocks.",
Subject: ev.StartRange().Ptr(),
})
}
Expand All @@ -364,7 +364,7 @@ func (b *body) collectDeepAttrs(v node, labelName *string) ([]*objectAttr, hcl.D
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Incorrect JSON value type",
Detail: "Either a JSON object or JSON array of objects is required here, to define attributes and child blocks.",
Detail: "Either a JSON object or JSON array of objects is required here, to define arguments and child blocks.",
Subject: v.StartRange().Ptr(),
})
}
Expand Down
12 changes: 6 additions & 6 deletions hcl/merged.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ func (mb mergedBodies) JustAttributes() (Attributes, Diagnostics) {
if existing := attrs[name]; existing != nil {
diags = diags.Append(&Diagnostic{
Severity: DiagError,
Summary: "Duplicate attribute",
Summary: "Duplicate argument",
Detail: fmt.Sprintf(
"Attribute %q was already assigned at %s",
"Argument %q was already set at %s",
name, existing.NameRange.String(),
),
Subject: &attr.NameRange,
Expand Down Expand Up @@ -182,9 +182,9 @@ func (mb mergedBodies) mergedContent(schema *BodySchema, partial bool) (*BodyCon
if existing := content.Attributes[name]; existing != nil {
diags = diags.Append(&Diagnostic{
Severity: DiagError,
Summary: "Duplicate attribute",
Summary: "Duplicate argument",
Detail: fmt.Sprintf(
"Attribute %q was already assigned at %s",
"Argument %q was already set at %s",
name, existing.NameRange.String(),
),
Subject: &attr.NameRange,
Expand Down Expand Up @@ -212,9 +212,9 @@ func (mb mergedBodies) mergedContent(schema *BodySchema, partial bool) (*BodyCon
// use of required attributes on merged bodies.
diags = diags.Append(&Diagnostic{
Severity: DiagError,
Summary: "Missing required attribute",
Summary: "Missing required argument",
Detail: fmt.Sprintf(
"The attribute %q is required, but was not assigned.",
"The argument %q is required, but was not set.",
attrS.Name,
),
})
Expand Down
8 changes: 4 additions & 4 deletions hcltest/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ func (b mockBody) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnos
for _, attr := range remain.C.Attributes {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Extraneous attribute in mock body",
Detail: fmt.Sprintf("Mock body has extraneous attribute %q.", attr.Name),
Summary: "Extraneous argument in mock body",
Detail: fmt.Sprintf("Mock body has extraneous argument %q.", attr.Name),
Subject: &attr.NameRange,
})
}
Expand Down Expand Up @@ -63,8 +63,8 @@ func (b mockBody) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.
if attrS.Required {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Missing required attribute",
Detail: fmt.Sprintf("Mock body doesn't have attribute %q", name),
Summary: "Missing required argument",
Detail: fmt.Sprintf("Mock body doesn't have argument %q", name),
Subject: b.C.MissingItemRange.Ptr(),
})
}
Expand Down

0 comments on commit 41cff85

Please sign in to comment.