// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements a regression test harness for syntax errors.
// The files in the testdata directory are parsed and the reported
// errors are compared against the errors declared in those files.
//
// Errors are declared in place in the form of "error comments",
// just before (or on the same line as) the offending token.
//
// Error comments must be of the form // ERROR rx or /* ERROR rx */
// where rx is a regular expression that matches the reported error
// message. The rx text comprises the comment text after "ERROR ",
// with any white space around it stripped.
//
// If the line comment form is used, the reported error's line must
// match the line of the error comment.
//
// If the regular comment form is used, the reported error's position
// must match the position of the token immediately following the
// error comment. Thus, /* ERROR ... */ comments should appear
// immediately before the position where the error is reported.
//
// Currently, the test harness only supports one error comment per
// token. If multiple error comments appear before a token, only
// the last one is considered.

package syntax

import (
	"flag"
	"fmt"
	"internal/testenv"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"testing"
)

const testdata = "testdata" // directory containing test files

var print = flag.Bool("print", false, "only print errors")

// A position represents a source position in the current file.
type position struct {
	line, col uint
}

func (pos position) String() string {
	return fmt.Sprintf("%d:%d", pos.line, pos.col)
}

func sortedPositions(m map[position]string) []position {
	list := make([]position, len(m))
	i := 0
	for pos := range m {
		list[i] = pos
		i++
	}
	sort.Slice(list, func(i, j int) bool {
		a, b := list[i], list[j]
		return a.line < b.line || a.line == b.line && a.col < b.col
	})
	return list
}

// declaredErrors returns a map of source positions to error
// patterns, extracted from error comments in the given file.
// Error comments in the form of line comments use col = 0
// in their position.
func declaredErrors(t *testing.T, filename string) map[position]string {
	f, err := os.Open(filename)
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()

	declared := make(map[position]string)

	var s scanner
	var pattern string
	s.init(f, func(line, col uint, msg string) {
		// errors never start with '/' so they are automatically excluded here
		switch {
		case strings.HasPrefix(msg, "// ERROR "):
			// we can't have another comment on the same line - just add it
			declared[position{s.line, 0}] = strings.TrimSpace(msg[9:])
		case strings.HasPrefix(msg, "/* ERROR "):
			// we may have more comments before the next token - collect them
			pattern = strings.TrimSpace(msg[9 : len(msg)-2])
		}
	}, comments)

	// consume file
	for {
		s.next()
		if pattern != "" {
			declared[position{s.line, s.col}] = pattern
			pattern = ""
		}
		if s.tok == _EOF {
			break
		}
	}

	return declared
}

func testSyntaxErrors(t *testing.T, filename string) {
	declared := declaredErrors(t, filename)
	if *print {
		fmt.Println("Declared errors:")
		for _, pos := range sortedPositions(declared) {
			fmt.Printf("%s:%s: %s\n", filename, pos, declared[pos])
		}

		fmt.Println()
		fmt.Println("Reported errors:")
	}

	f, err := os.Open(filename)
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()

	ParseFile(filename, func(err error) {
		e, ok := err.(Error)
		if !ok {
			return
		}

		if *print {
			fmt.Println(err)
			return
		}

		orig := position{e.Pos.Line(), e.Pos.Col()}
		pos := orig
		pattern, found := declared[pos]
		if !found {
			// try line comment (only line must match)
			pos = position{e.Pos.Line(), 0}
			pattern, found = declared[pos]
		}
		if found {
			rx, err := regexp.Compile(pattern)
			if err != nil {
				t.Errorf("%s: %v", pos, err)
				return
			}
			if match := rx.MatchString(e.Msg); !match {
				t.Errorf("%s: %q does not match %q", pos, e.Msg, pattern)
				return
			}
			// we have a match - eliminate this error
			delete(declared, pos)
		} else {
			t.Errorf("%s: unexpected error: %s", orig, e.Msg)
		}
	}, nil, 0)

	if *print {
		fmt.Println()
		return // we're done
	}

	// report expected but not reported errors
	for pos, pattern := range declared {
		t.Errorf("%s: missing error: %s", pos, pattern)
	}
}

func TestSyntaxErrors(t *testing.T) {
	testenv.MustHaveGoBuild(t) // we need access to source (testdata)

	list, err := ioutil.ReadDir(testdata)
	if err != nil {
		t.Fatal(err)
	}
	for _, fi := range list {
		name := fi.Name()
		if !fi.IsDir() && !strings.HasPrefix(name, ".") {
			testSyntaxErrors(t, filepath.Join(testdata, name))
		}
	}
}
