From 960150bb034dc9a549ee7289b1a4eb4abafeb30a Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Sat, 25 Feb 2023 19:34:27 -0500 Subject: caddyfile: Implement heredoc support (#5385) --- caddyconfig/caddyfile/dispenser.go | 58 +++++++++++++++----------------------- 1 file changed, 22 insertions(+), 36 deletions(-) (limited to 'caddyconfig/caddyfile/dispenser.go') diff --git a/caddyconfig/caddyfile/dispenser.go b/caddyconfig/caddyfile/dispenser.go index 91bd9a5..0daed3c 100644 --- a/caddyconfig/caddyfile/dispenser.go +++ b/caddyconfig/caddyfile/dispenser.go @@ -20,7 +20,6 @@ import ( "io" "log" "strconv" - "strings" ) // Dispenser is a type that dispenses tokens, similarly to a lexer, @@ -101,12 +100,12 @@ func (d *Dispenser) nextOnSameLine() bool { d.cursor++ return true } - if d.cursor >= len(d.tokens) { + if d.cursor >= len(d.tokens)-1 { return false } - if d.cursor < len(d.tokens)-1 && - d.tokens[d.cursor].File == d.tokens[d.cursor+1].File && - d.tokens[d.cursor].Line+d.numLineBreaks(d.cursor) == d.tokens[d.cursor+1].Line { + curr := d.tokens[d.cursor] + next := d.tokens[d.cursor+1] + if curr.File == next.File && curr.Line+curr.NumLineBreaks() == next.Line { d.cursor++ return true } @@ -122,12 +121,12 @@ func (d *Dispenser) NextLine() bool { d.cursor++ return true } - if d.cursor >= len(d.tokens) { + if d.cursor >= len(d.tokens)-1 { return false } - if d.cursor < len(d.tokens)-1 && - (d.tokens[d.cursor].File != d.tokens[d.cursor+1].File || - d.tokens[d.cursor].Line+d.numLineBreaks(d.cursor) < d.tokens[d.cursor+1].Line) { + curr := d.tokens[d.cursor] + next := d.tokens[d.cursor+1] + if curr.File != next.File || curr.Line+curr.NumLineBreaks() < next.Line { d.cursor++ return true } @@ -203,14 +202,17 @@ func (d *Dispenser) Val() string { } // ValRaw gets the raw text of the current token (including quotes). +// If the token was a heredoc, then the delimiter is not included, +// because that is not relevant to any unmarshaling logic at this time. // If there is no token loaded, it returns empty string. func (d *Dispenser) ValRaw() string { if d.cursor < 0 || d.cursor >= len(d.tokens) { return "" } quote := d.tokens[d.cursor].wasQuoted - if quote > 0 { - return string(quote) + d.tokens[d.cursor].Text + string(quote) // string literal + if quote > 0 && quote != '<' { + // string literal + return string(quote) + d.tokens[d.cursor].Text + string(quote) } return d.tokens[d.cursor].Text } @@ -438,14 +440,14 @@ func (d *Dispenser) Delete() []Token { return d.tokens } -// numLineBreaks counts how many line breaks are in the token -// value given by the token index tknIdx. It returns 0 if the -// token does not exist or there are no line breaks. -func (d *Dispenser) numLineBreaks(tknIdx int) int { - if tknIdx < 0 || tknIdx >= len(d.tokens) { - return 0 +// DeleteN is the same as Delete, but can delete many tokens at once. +// If there aren't N tokens available to delete, none are deleted. +func (d *Dispenser) DeleteN(amount int) []Token { + if amount > 0 && d.cursor >= (amount-1) && d.cursor <= len(d.tokens)-1 { + d.tokens = append(d.tokens[:d.cursor-(amount-1)], d.tokens[d.cursor+1:]...) + d.cursor -= amount } - return strings.Count(d.tokens[tknIdx].Text, "\n") + return d.tokens } // isNewLine determines whether the current token is on a different @@ -468,18 +470,10 @@ func (d *Dispenser) isNewLine() bool { return true } - // The previous token may contain line breaks if - // it was quoted and spanned multiple lines. e.g: - // - // dir "foo - // bar - // baz" - prevLineBreaks := d.numLineBreaks(d.cursor - 1) - // If the previous token (incl line breaks) ends // on a line earlier than the current token, // then the current token is on a new line - return prev.Line+prevLineBreaks < curr.Line + return prev.Line+prev.NumLineBreaks() < curr.Line } // isNextOnNewLine determines whether the current token is on a different @@ -502,16 +496,8 @@ func (d *Dispenser) isNextOnNewLine() bool { return true } - // The current token may contain line breaks if - // it was quoted and spanned multiple lines. e.g: - // - // dir "foo - // bar - // baz" - currLineBreaks := d.numLineBreaks(d.cursor) - // If the current token (incl line breaks) ends // on a line earlier than the next token, // then the next token is on a new line - return curr.Line+currLineBreaks < next.Line + return curr.Line+curr.NumLineBreaks() < next.Line } -- cgit v1.2.3 From 9cde71552576dcc724eff38dee42879c927b72ec Mon Sep 17 00:00:00 2001 From: WeidiDeng Date: Fri, 26 May 2023 03:05:00 +0800 Subject: caddyfile: Track import name instead of modifying filename (#5540) * Merge branch 'master' into import_file_stack * remove space in log key --- caddyconfig/caddyfile/dispenser.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'caddyconfig/caddyfile/dispenser.go') diff --git a/caddyconfig/caddyfile/dispenser.go b/caddyconfig/caddyfile/dispenser.go index 0daed3c..580de4a 100644 --- a/caddyconfig/caddyfile/dispenser.go +++ b/caddyconfig/caddyfile/dispenser.go @@ -20,6 +20,7 @@ import ( "io" "log" "strconv" + "strings" ) // Dispenser is a type that dispenses tokens, similarly to a lexer, @@ -398,7 +399,7 @@ func (d *Dispenser) ArgErr() error { // SyntaxErr creates a generic syntax error which explains what was // found and what was expected. func (d *Dispenser) SyntaxErr(expected string) error { - msg := fmt.Sprintf("%s:%d - Syntax error: Unexpected token '%s', expecting '%s'", d.File(), d.Line(), d.Val(), expected) + msg := fmt.Sprintf("%s:%d - Syntax error: Unexpected token '%s', expecting '%s', import chain: ['%s']", d.File(), d.Line(), d.Val(), expected, strings.Join(d.Token().imports, "','")) return errors.New(msg) } @@ -420,7 +421,7 @@ func (d *Dispenser) Errf(format string, args ...any) error { // WrapErr takes an existing error and adds the Caddyfile file and line number. func (d *Dispenser) WrapErr(err error) error { - return fmt.Errorf("%s:%d - Error during parsing: %w", d.File(), d.Line(), err) + return fmt.Errorf("%s:%d - Error during parsing: %w, import chain: ['%s']", d.File(), d.Line(), err, strings.Join(d.Token().imports, "','")) } // Delete deletes the current token and returns the updated slice -- cgit v1.2.3 From bbe1952a59a196b7598c6488beb770ec38a70dfc Mon Sep 17 00:00:00 2001 From: WeidiDeng Date: Thu, 13 Jul 2023 04:32:22 +0800 Subject: caddyfile: Fix comparing if two tokens are on the same line (#5626) * fix comparing if two tokens are on the same line * compare tokens from copies when importing --- caddyconfig/caddyfile/dispenser.go | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) (limited to 'caddyconfig/caddyfile/dispenser.go') diff --git a/caddyconfig/caddyfile/dispenser.go b/caddyconfig/caddyfile/dispenser.go index 580de4a..6c33f4f 100644 --- a/caddyconfig/caddyfile/dispenser.go +++ b/caddyconfig/caddyfile/dispenser.go @@ -106,7 +106,7 @@ func (d *Dispenser) nextOnSameLine() bool { } curr := d.tokens[d.cursor] next := d.tokens[d.cursor+1] - if curr.File == next.File && curr.Line+curr.NumLineBreaks() == next.Line { + if !isNextOnNewLine(curr, next) { d.cursor++ return true } @@ -127,7 +127,7 @@ func (d *Dispenser) NextLine() bool { } curr := d.tokens[d.cursor] next := d.tokens[d.cursor+1] - if curr.File != next.File || curr.Line+curr.NumLineBreaks() < next.Line { + if isNextOnNewLine(curr, next) { d.cursor++ return true } @@ -464,17 +464,7 @@ func (d *Dispenser) isNewLine() bool { prev := d.tokens[d.cursor-1] curr := d.tokens[d.cursor] - - // If the previous token is from a different file, - // we can assume it's from a different line - if prev.File != curr.File { - return true - } - - // If the previous token (incl line breaks) ends - // on a line earlier than the current token, - // then the current token is on a new line - return prev.Line+prev.NumLineBreaks() < curr.Line + return isNextOnNewLine(prev, curr) } // isNextOnNewLine determines whether the current token is on a different @@ -490,15 +480,5 @@ func (d *Dispenser) isNextOnNewLine() bool { curr := d.tokens[d.cursor] next := d.tokens[d.cursor+1] - - // If the next token is from a different file, - // we can assume it's from a different line - if curr.File != next.File { - return true - } - - // If the current token (incl line breaks) ends - // on a line earlier than the next token, - // then the next token is on a new line - return curr.Line+curr.NumLineBreaks() < next.Line + return isNextOnNewLine(curr, next) } -- cgit v1.2.3 From 38a7b6b3d0e1150bc22e2f5409b74821132f8741 Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Sun, 20 Aug 2023 10:51:03 -0400 Subject: caddyfile: Adjust error formatting (#5765) --- caddyconfig/caddyfile/dispenser.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'caddyconfig/caddyfile/dispenser.go') diff --git a/caddyconfig/caddyfile/dispenser.go b/caddyconfig/caddyfile/dispenser.go index 6c33f4f..215a164 100644 --- a/caddyconfig/caddyfile/dispenser.go +++ b/caddyconfig/caddyfile/dispenser.go @@ -391,22 +391,22 @@ func (d *Dispenser) Reset() { // an argument. func (d *Dispenser) ArgErr() error { if d.Val() == "{" { - return d.Err("Unexpected token '{', expecting argument") + return d.Err("unexpected token '{', expecting argument") } - return d.Errf("Wrong argument count or unexpected line ending after '%s'", d.Val()) + return d.Errf("wrong argument count or unexpected line ending after '%s'", d.Val()) } // SyntaxErr creates a generic syntax error which explains what was // found and what was expected. func (d *Dispenser) SyntaxErr(expected string) error { - msg := fmt.Sprintf("%s:%d - Syntax error: Unexpected token '%s', expecting '%s', import chain: ['%s']", d.File(), d.Line(), d.Val(), expected, strings.Join(d.Token().imports, "','")) + msg := fmt.Sprintf("syntax error: unexpected token '%s', expecting '%s', at %s:%d import chain: ['%s']", d.Val(), expected, d.File(), d.Line(), strings.Join(d.Token().imports, "','")) return errors.New(msg) } // EOFErr returns an error indicating that the dispenser reached // the end of the input when searching for the next token. func (d *Dispenser) EOFErr() error { - return d.Errf("Unexpected EOF") + return d.Errf("unexpected EOF") } // Err generates a custom parse-time error with a message of msg. @@ -421,7 +421,10 @@ func (d *Dispenser) Errf(format string, args ...any) error { // WrapErr takes an existing error and adds the Caddyfile file and line number. func (d *Dispenser) WrapErr(err error) error { - return fmt.Errorf("%s:%d - Error during parsing: %w, import chain: ['%s']", d.File(), d.Line(), err, strings.Join(d.Token().imports, "','")) + if len(d.Token().imports) > 0 { + return fmt.Errorf("%w, at %s:%d import chain ['%s']", err, d.File(), d.Line(), strings.Join(d.Token().imports, "','")) + } + return fmt.Errorf("%w, at %s:%d", err, d.File(), d.Line()) } // Delete deletes the current token and returns the updated slice -- cgit v1.2.3