From 90676d47a0ce038f02596e2aa5894bf0c57fad56 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Mon, 24 Aug 2020 10:43:03 -0700 Subject: [PATCH] hclsyntax: Tailored error for "curly quotes" It seems to be somewhat common for someone to share HCL code via a forum or a document and have the well-meaning word processor or CMS replace the straight quotes with curly quotes, which then lead to confusing errors when someone copies the result and tries to use it as valid HCL configuration. Here we add a special hint for that, giving a tailored error message instead of the generic "This character is not used within the language" error message. HCL has always had some of these special hints implemented here, and they were originally implemented with special token types to allow the parser handle them. However, we later refactored to do the check all at once inside the Lex* family of functions, prior to parsing, so it's now relatively straightforward to handle it as a special case of TokenInvalid rather than an entirely new token type. Perhaps later we'll rework the existing ones to also just use TokenInvalid, but that's a decision for another day. --- hclsyntax/token.go | 23 +++++++++++----- hclsyntax/token_test.go | 60 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 hclsyntax/token_test.go diff --git a/hclsyntax/token.go b/hclsyntax/token.go index 5964475..59f4c43 100644 --- a/hclsyntax/token.go +++ b/hclsyntax/token.go @@ -294,12 +294,23 @@ func checkInvalidTokens(tokens Tokens) hcl.Diagnostics { Subject: &tok.Range, }) case TokenInvalid: - diags = append(diags, &hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Invalid character", - Detail: "This character is not used within the language.", - Subject: &tok.Range, - }) + chars := string(tok.Bytes) + switch chars { + case "“", "”": + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid character", + Detail: "\"Curly quotes\" are not valid here. These can sometimes be inadvertently introduced when sharing code via documents or discussion forums. It might help to replace the character with a \"straight quote\".", + Subject: &tok.Range, + }) + default: + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid character", + Detail: "This character is not used within the language.", + Subject: &tok.Range, + }) + } } } return diags diff --git a/hclsyntax/token_test.go b/hclsyntax/token_test.go new file mode 100644 index 0000000..a954d60 --- /dev/null +++ b/hclsyntax/token_test.go @@ -0,0 +1,60 @@ +package hclsyntax + +import ( + "testing" + + "github.com/hashicorp/hcl/v2" +) + +func TestCheckInvalidTokensTest(t *testing.T) { + tests := []struct { + Input string + WantSummary string + WantDetail string + }{ + { + `block “invalid” {}`, + `Invalid character`, + `"Curly quotes" are not valid here. These can sometimes be inadvertently introduced when sharing code via documents or discussion forums. It might help to replace the character with a "straight quote".`, + }, + { + `block 'invalid' {}`, + `Invalid character`, + `Single quotes are not valid. Use double quotes (") to enclose strings.`, + }, + { + "block `invalid` {}", + `Invalid character`, + "The \"`\" character is not valid. To create a multi-line string, use the \"heredoc\" syntax, like \"<