From 8420a2f250cf467a06c0081cb47a8f73b70e7f3f Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Wed, 21 Aug 2019 15:23:00 -0600 Subject: [PATCH] Clean up Dispenser and filename handling a bit --- caddyconfig/caddyfile/dispenser.go | 47 +++++++++---------------- caddyconfig/caddyfile/dispenser_test.go | 4 +-- caddyconfig/caddyfile/parse.go | 21 +++++------ caddyconfig/caddyfile/parse_test.go | 2 +- caddyconfig/httpcaddyfile/httptype.go | 6 +++- 5 files changed, 33 insertions(+), 47 deletions(-) diff --git a/caddyconfig/caddyfile/dispenser.go b/caddyconfig/caddyfile/dispenser.go index 0d2c7899..66a3541c 100755 --- a/caddyconfig/caddyfile/dispenser.go +++ b/caddyconfig/caddyfile/dispenser.go @@ -24,19 +24,16 @@ import ( // except that it can do so with some notion of structure. An empty // Dispenser is invalid; call NewDispenser to make a proper instance. type Dispenser struct { - filename string - tokens []Token - cursor int - nesting int + tokens []Token + cursor int + nesting int } // NewDispenser returns a Dispenser filled with the given tokens. -// TODO: Get rid of the filename argument; it seems pointless here -func NewDispenser(filename string, tokens []Token) *Dispenser { +func NewDispenser(tokens []Token) *Dispenser { return &Dispenser{ - filename: filename, - tokens: tokens, - cursor: -1, + tokens: tokens, + cursor: -1, } } @@ -170,8 +167,8 @@ func (d *Dispenser) Val() string { return d.tokens[d.cursor].Text } -// Line gets the line number of the current token. If there is no token -// loaded, it returns 0. +// Line gets the line number of the current token. +// If there is no token loaded, it returns 0. func (d *Dispenser) Line() int { if d.cursor < 0 || d.cursor >= len(d.tokens) { return 0 @@ -179,16 +176,12 @@ func (d *Dispenser) Line() int { return d.tokens[d.cursor].Line } -// File gets the filename of the current token. If there is no token loaded, -// it returns the filename originally given when parsing started. +// File gets the filename where the current token originated. func (d *Dispenser) File() string { if d.cursor < 0 || d.cursor >= len(d.tokens) { - return d.filename + return "" } - if tokenFilename := d.tokens[d.cursor].File; tokenFilename != "" { - return tokenFilename - } - return d.filename + return d.tokens[d.cursor].File } // Args is a convenience function that loads the next arguments @@ -240,28 +233,22 @@ func (d *Dispenser) NewFromNextTokens() *Dispenser { } else { d.cursor-- } - return NewDispenser(d.filename, tkns) + return NewDispenser(tkns) } // Token returns the current token. func (d *Dispenser) Token() Token { - return d.TokenAt(d.cursor) -} - -func (d *Dispenser) TokenAt(cursor int) Token { - if cursor < 0 || cursor >= len(d.tokens) { + if d.cursor < 0 || d.cursor >= len(d.tokens) { return Token{} } - return d.tokens[cursor] -} - -// Cursor returns the current cursor (token index). -func (d *Dispenser) Cursor() int { - return d.cursor + return d.tokens[d.cursor] } +// Reset sets d's cursor to the beginning, as +// if this was a new and unused dispenser. func (d *Dispenser) Reset() { d.cursor = -1 + d.nesting = 0 } // ArgErr returns an argument error, meaning that another diff --git a/caddyconfig/caddyfile/dispenser_test.go b/caddyconfig/caddyfile/dispenser_test.go index 9860bedb..07fbbeee 100755 --- a/caddyconfig/caddyfile/dispenser_test.go +++ b/caddyconfig/caddyfile/dispenser_test.go @@ -308,9 +308,9 @@ func TestDispenser_ArgErr_Err(t *testing.T) { } func newTestDispenser(input string) *Dispenser { - tokens, err := allTokens(strings.NewReader(input)) + tokens, err := allTokens("Testfile", strings.NewReader(input)) if err != nil && err != io.EOF { log.Fatalf("getting all tokens from input: %v", err) } - return NewDispenser("Testfile", tokens) + return NewDispenser(tokens) } diff --git a/caddyconfig/caddyfile/parse.go b/caddyconfig/caddyfile/parse.go index cc7ed25d..3356f256 100755 --- a/caddyconfig/caddyfile/parse.go +++ b/caddyconfig/caddyfile/parse.go @@ -29,18 +29,18 @@ import ( // an error. If you do not want to check for valid directives, // pass in nil instead. func Parse(filename string, input io.Reader) ([]ServerBlock, error) { - tokens, err := allTokens(input) + tokens, err := allTokens(filename, input) if err != nil { return nil, err } - p := parser{Dispenser: NewDispenser(filename, tokens)} + p := parser{Dispenser: NewDispenser(tokens)} return p.parseAll() } // allTokens lexes the entire input, but does not parse it. // It returns all the tokens from the input, unstructured // and in order. -func allTokens(input io.Reader) ([]Token, error) { +func allTokens(filename string, input io.Reader) ([]Token, error) { l := new(lexer) err := l.load(input) if err != nil { @@ -48,6 +48,7 @@ func allTokens(input io.Reader) ([]Token, error) { } var tokens []Token for l.next() { + l.token.File = filename tokens = append(tokens, l.token) } return tokens, nil @@ -265,7 +266,7 @@ func (p *parser) doImport() error { // list of matching filenames absFile, err := filepath.Abs(p.Dispenser.File()) if err != nil { - return p.Errf("Failed to get absolute path of file: %s: %v", p.Dispenser.filename, err) + return p.Errf("Failed to get absolute path of file: %s: %v", p.Dispenser.File(), err) } var matches []string @@ -327,7 +328,7 @@ func (p *parser) doSingleImport(importFile string) ([]Token, error) { return nil, p.Errf("Could not import %s: is a directory", importFile) } - importedTokens, err := allTokens(file) + importedTokens, err := allTokens(importFile, file) if err != nil { return nil, p.Errf("Could not read tokens while importing %s: %v", importFile, err) } @@ -336,7 +337,7 @@ func (p *parser) doSingleImport(importFile string) ([]Token, error) { // (we use full, absolute path to avoid bugs: issue #1892) filename, err := filepath.Abs(importFile) if err != nil { - return nil, p.Errf("Failed to get absolute path of file: %s: %v", p.Dispenser.filename, err) + return nil, p.Errf("Failed to get absolute path of file: %s: %v", importFile, err) } for i := 0; i < len(importedTokens); i++ { importedTokens[i].File = filename @@ -497,7 +498,7 @@ func (sb ServerBlock) DispenseDirective(dir string) *Dispenser { tokens = append(tokens, seg...) } } - return NewDispenser("", tokens) + return NewDispenser(tokens) } // Segment is a list of tokens which begins with a directive @@ -513,9 +514,3 @@ func (s Segment) Directive() string { } return "" } - -// NewDispenser returns a dispenser for this -// segment's tokens. -func (s Segment) NewDispenser() *Dispenser { - return NewDispenser("", s) -} diff --git a/caddyconfig/caddyfile/parse_test.go b/caddyconfig/caddyfile/parse_test.go index 19959de8..d4e22cc4 100755 --- a/caddyconfig/caddyfile/parse_test.go +++ b/caddyconfig/caddyfile/parse_test.go @@ -27,7 +27,7 @@ import ( func TestAllTokens(t *testing.T) { input := strings.NewReader("a b c\nd e") expected := []string{"a", "b", "c", "d", "e"} - tokens, err := allTokens(input) + tokens, err := allTokens("TestAllTokens", input) if err != nil { t.Fatalf("Expected no error, got %v", err) diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go index 42c1be59..e7e7c87c 100644 --- a/caddyconfig/httpcaddyfile/httptype.go +++ b/caddyconfig/httpcaddyfile/httptype.go @@ -38,6 +38,10 @@ func init() { type ServerType struct { } +// TODO: customize directive ordering + +// TODO: hide caddyfile when serving static files + // Setup makes a config from the tokens. func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock, options map[string]string) (*caddy.Config, []caddyconfig.Warning, error) { @@ -88,7 +92,7 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock, } if dirFunc, ok := registeredDirectives[dir]; ok { results, err := dirFunc(Helper{ - Dispenser: segment.NewDispenser(), + Dispenser: caddyfile.NewDispenser(segment), warnings: &warnings, matcherDefs: matcherDefs, })