Add a new "deprecate" command.

This commit is contained in:
Qi Xiao 2021-01-24 15:32:24 +00:00
parent b87cc7b5de
commit ae98cc5272
5 changed files with 72 additions and 11 deletions

View File

@ -93,6 +93,8 @@ New features in the standard library:
- A new `path:` module has been introduced for manipulating and testing
filesystem paths.
- A new `deprecate` command.
New features in the interactive editor:
- The new commands `edit:add-var` and `edit:add-vars` provide an API for

View File

@ -13,6 +13,7 @@ import (
"time"
"unicode/utf8"
"github.com/elves/elvish/pkg/diag"
"github.com/elves/elvish/pkg/eval/vals"
"github.com/elves/elvish/pkg/parse"
)
@ -31,6 +32,8 @@ func init() {
"use-mod": useMod,
"-source": source,
"deprecate": deprecate,
// Time
"esleep": sleep,
"sleep": sleep,
@ -318,6 +321,49 @@ func readFileUTF8(fname string) (string, error) {
return string(bytes), nil
}
//elvdoc:fn deprecate
//
// ```elvish
// deprecate $msg
// ```
//
// Shows the given deprecation message to stderr. If called from a function
// or module, also shows the call site of the function or import site of the
// module. Does nothing if the combination of the call site and the message has
// been shown before.
//
// ```elvish-transcript
// ~> deprecate msg
// deprecation: msg
// ~> fn f { deprecate msg }
// ~> f
// deprecation: msg
// [tty 19], line 1: f
// ~> exec
// ~> deprecate msg
// deprecation: msg
// ~> fn f { deprecate msg }
// ~> f
// deprecation: msg
// [tty 3], line 1: f
// ~> f # a different call site; shows deprecate message
// deprecation: msg
// [tty 4], line 1: f
// ~> fn g { f }
// ~> g
// deprecation: msg
// [tty 5], line 1: fn g { f }
// ~> g # same call site, no more deprecation message
// ```
func deprecate(fm *Frame, msg string) {
var ctx *diag.Context
if fm.traceback.Next != nil {
ctx = fm.traceback.Next.Head
}
fm.Deprecate(msg, ctx, 0)
}
// TimeAfter is used by the sleep command to obtain a channel that is delivered
// a value after the specified time.
//

View File

@ -2,6 +2,7 @@ package eval_test
import (
"errors"
"os"
"testing"
"time"
@ -48,6 +49,18 @@ func TestEval(t *testing.T) {
)
}
func TestDeprecate(t *testing.T) {
Test(t,
That("deprecate msg").PrintsStderrWith("msg"),
// Different call sites trigger multiple deprecation messages
That("fn f { deprecate msg }", "f 2>"+os.DevNull, "f").
PrintsStderrWith("msg"),
// The same call site only triggers the message once
That("fn f { deprecate msg}", "fn g { f }", "g 2>"+os.DevNull, "g 2>&1").
DoesNothing(),
)
}
func TestTime(t *testing.T) {
Test(t,
// Since runtime duration is non-deterministic, we only have some sanity

View File

@ -248,7 +248,8 @@ func (op *indexingOp) exec(fm *Frame) ([]interface{}, Exception) {
// Check the legacy low:high slice syntax deprecated since 0.15.
deprecation := vals.CheckDeprecatedIndex(v, index)
if deprecation != "" {
fm.Deprecate(deprecation, indexOp, 15)
ctx := diag.NewContext(fm.srcMeta.Name, fm.srcMeta.Code, indexOp)
fm.Deprecate(deprecation, ctx, 15)
}
newvs = append(newvs, result)
}

View File

@ -225,17 +225,16 @@ func (fm *Frame) errorpf(r diag.Ranger, format string, args ...interface{}) Exce
// Deprecate shows a deprecation message. The message is not shown if the same
// deprecation message has been shown for the same location before.
func (fm *Frame) Deprecate(msg string, r diag.Ranger, minLevel int) {
var ctx *diag.Context
if r == nil {
ctx = fm.traceback.Head
} else {
ctx = diag.NewContext(fm.srcMeta.Name, fm.srcMeta.Code, r)
func (fm *Frame) Deprecate(msg string, ctx *diag.Context, minLevel int) {
if prog.DeprecationLevel < minLevel {
return
}
dep := deprecation{ctx.Name, ctx.Ranging, msg}
if prog.DeprecationLevel >= minLevel && fm.Evaler.registerDeprecation(dep) {
err := diag.Error{
Type: "deprecation", Message: dep.message, Context: *ctx}
if ctx == nil {
fmt.Fprintf(fm.ErrorFile(), "deprecation: \033[31;1m%s\033[m\n", msg)
return
}
if fm.Evaler.registerDeprecation(deprecation{ctx.Name, ctx.Ranging, msg}) {
err := diag.Error{Type: "deprecation", Message: msg, Context: *ctx}
fm.ErrorFile().WriteString(err.Show("") + "\n")
}
}