// Copyright 2012 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 error reporting.

package types2

import (
	"cmd/compile/internal/syntax"
	"fmt"
	. "internal/types/errors"
	"runtime"
	"strings"
)

func assert(p bool) {
	if !p {
		msg := "assertion failed"
		// Include information about the assertion location. Due to panic recovery,
		// this location is otherwise buried in the middle of the panicking stack.
		if _, file, line, ok := runtime.Caller(1); ok {
			msg = fmt.Sprintf("%s:%d: %s", file, line, msg)
		}
		panic(msg)
	}
}

// An errorDesc describes part of a type-checking error.
type errorDesc struct {
	pos syntax.Pos
	msg string
}

// An error_ represents a type-checking error.
// A new error_ is created with Checker.newError.
// To report an error_, call error_.report.
type error_ struct {
	check *Checker
	desc  []errorDesc
	code  Code
	soft  bool // TODO(gri) eventually determine this from an error code
}

// newError returns a new error_ with the given error code.
func (check *Checker) newError(code Code) *error_ {
	if code == 0 {
		panic("error code must not be 0")
	}
	return &error_{check: check, code: code}
}

// addf adds formatted error information to err.
// It may be called multiple times to provide additional information.
// The position of the first call to addf determines the position of the reported Error.
// Subsequent calls to addf provide additional information in the form of additional lines
// in the error message (types2) or continuation errors identified by a tab-indented error
// message (go/types).
func (err *error_) addf(at poser, format string, args ...interface{}) {
	err.desc = append(err.desc, errorDesc{atPos(at), err.check.sprintf(format, args...)})
}

// addAltDecl is a specialized form of addf reporting another declaration of obj.
func (err *error_) addAltDecl(obj Object) {
	if pos := obj.Pos(); pos.IsKnown() {
		// We use "other" rather than "previous" here because
		// the first declaration seen may not be textually
		// earlier in the source.
		err.addf(obj, "other declaration of %s", obj.Name())
	}
}

func (err *error_) empty() bool {
	return err.desc == nil
}

func (err *error_) pos() syntax.Pos {
	if err.empty() {
		return nopos
	}
	return err.desc[0].pos
}

// msg returns the formatted error message without the primary error position pos().
func (err *error_) msg() string {
	if err.empty() {
		return "no error"
	}

	var buf strings.Builder
	for i := range err.desc {
		p := &err.desc[i]
		if i > 0 {
			fmt.Fprint(&buf, "\n\t")
			if p.pos.IsKnown() {
				fmt.Fprintf(&buf, "%s: ", p.pos)
			}
		}
		buf.WriteString(p.msg)
	}
	return buf.String()
}

// report reports the error err, setting check.firstError if necessary.
func (err *error_) report() {
	if err.empty() {
		panic("no error")
	}

	// Cheap trick: Don't report errors with messages containing
	// "invalid operand" or "invalid type" as those tend to be
	// follow-on errors which don't add useful information. Only
	// exclude them if these strings are not at the beginning,
	// and only if we have at least one error already reported.
	check := err.check
	if check.firstErr != nil {
		// It is sufficient to look at the first sub-error only.
		msg := err.desc[0].msg
		if strings.Index(msg, "invalid operand") > 0 || strings.Index(msg, "invalid type") > 0 {
			return
		}
	}

	if check.conf.Trace {
		check.trace(err.pos(), "ERROR: %s (code = %d)", err.desc[0].msg, err.code)
	}

	// In go/types, if there is a sub-error with a valid position,
	// call the typechecker error handler for each sub-error.
	// Otherwise, call it once, with a single combined message.
	multiError := false
	if !isTypes2 {
		for i := 1; i < len(err.desc); i++ {
			if err.desc[i].pos.IsKnown() {
				multiError = true
				break
			}
		}
	}

	if multiError {
		for i := range err.desc {
			p := &err.desc[i]
			check.handleError(i, p.pos, err.code, p.msg, err.soft)
		}
	} else {
		check.handleError(0, err.pos(), err.code, err.msg(), err.soft)
	}

	// make sure the error is not reported twice
	err.desc = nil
}

// handleError should only be called by error_.report.
func (check *Checker) handleError(index int, pos syntax.Pos, code Code, msg string, soft bool) {
	assert(code != 0)

	if index == 0 {
		// If we are encountering an error while evaluating an inherited
		// constant initialization expression, pos is the position of
		// the original expression, and not of the currently declared
		// constant identifier. Use the provided errpos instead.
		// TODO(gri) We may also want to augment the error message and
		// refer to the position (pos) in the original expression.
		if check.errpos.Pos().IsKnown() {
			assert(check.iota != nil)
			pos = check.errpos
		}

		// Report invalid syntax trees explicitly.
		if code == InvalidSyntaxTree {
			msg = "invalid syntax tree: " + msg
		}

		// If we have a URL for error codes, add a link to the first line.
		if check.conf.ErrorURL != "" {
			url := fmt.Sprintf(check.conf.ErrorURL, code)
			if i := strings.Index(msg, "\n"); i >= 0 {
				msg = msg[:i] + url + msg[i:]
			} else {
				msg += url
			}
		}
	} else {
		// Indent sub-error.
		// Position information is passed explicitly to Error, below.
		msg = "\t" + msg
	}

	e := Error{
		Pos:  pos,
		Msg:  stripAnnotations(msg),
		Full: msg,
		Soft: soft,
		Code: code,
	}

	if check.firstErr == nil {
		check.firstErr = e
	}

	f := check.conf.Error
	if f == nil {
		panic(bailout{}) // record first error and exit
	}
	f(e)
}

const (
	invalidArg = "invalid argument: "
	invalidOp  = "invalid operation: "
)

// The poser interface is used to extract the position of type-checker errors.
type poser interface {
	Pos() syntax.Pos
}

func (check *Checker) error(at poser, code Code, msg string) {
	err := check.newError(code)
	err.addf(at, "%s", msg)
	err.report()
}

func (check *Checker) errorf(at poser, code Code, format string, args ...any) {
	err := check.newError(code)
	err.addf(at, format, args...)
	err.report()
}

func (check *Checker) softErrorf(at poser, code Code, format string, args ...any) {
	err := check.newError(code)
	err.addf(at, format, args...)
	err.soft = true
	err.report()
}

func (check *Checker) versionErrorf(at poser, v goVersion, format string, args ...any) {
	msg := check.sprintf(format, args...)
	err := check.newError(UnsupportedFeature)
	err.addf(at, "%s requires %s or later", msg, v)
	err.report()
}

// atPos reports the left (= start) position of at.
func atPos(at poser) syntax.Pos {
	switch x := at.(type) {
	case *operand:
		if x.expr != nil {
			return syntax.StartPos(x.expr)
		}
	case syntax.Node:
		return syntax.StartPos(x)
	}
	return at.Pos()
}
