tools/build-date
tools/info-plist
tools/bindata
+tools/vscode-tests/
*.hdr
GOARCH=$(shell go env GOHOSTARCH))
GOBIN ?= $(shell go env GOPATH)/bin
GOVARS = -X github.com/zyedidia/micro/internal/util.Version=$(VERSION) -X github.com/zyedidia/micro/internal/util.CommitHash=$(HASH) -X 'github.com/zyedidia/micro/internal/util.CompileDate=$(DATE)' -X github.com/zyedidia/micro/internal/util.Debug=OFF
+VSCODE_TESTS_BASE_URL = 'https://raw.githubusercontent.com/microsoft/vscode/e6a45f4242ebddb7aa9a229f85555e8a3bd987e2/src/vs/editor/test/common/model/'
# Builds micro after checking dependencies but without updating the runtime
build:
mv runtime.go internal/config
gofmt -w internal/config/runtime.go
+testgen:
+ mkdir -p tools/vscode-tests
+ cd tools/vscode-tests && \
+ curl --remote-name-all $(VSCODE_TESTS_BASE_URL){editableTextModelAuto,editableTextModel,model.line}.test.ts
+ tsc tools/vscode-tests/*.ts > /dev/null; true
+ go run tools/testgen.go tools/vscode-tests/*.js > buffer_generated_test.go
+ mv buffer_generated_test.go internal/buffer
+ gofmt -w internal/buffer/buffer_generated_test.go
+
test:
go test ./internal/...
+bench:
+ go test -bench=. ./internal/...
+
clean:
rm -f micro
github.com/mattn/go-isatty v0.0.11
github.com/mattn/go-runewidth v0.0.7
github.com/mitchellh/go-homedir v1.1.0
+ github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff
github.com/sergi/go-diff v1.1.0
github.com/stretchr/testify v1.4.0
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb
github.com/zyedidia/tcell v1.4.4
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415
golang.org/x/text v0.3.2
+ gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.2.7
layeh.com/gopher-luar v1.0.7
)
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff h1:+6NUiITWwE5q1KO6SAfUX918c+Tab0+tGAM/mtdlUyA=
+github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
+gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
--- /dev/null
+// This file is generated from VSCode model tests by the testgen tool.
+// DO NOT EDIT THIS FILE BY HAND; your changes will be overwritten!
+
+package buffer
+
+import "testing"
+
+func TestAuto1(t *testing.T) {
+ check(
+ t,
+ []string{
+ "ioe",
+ "",
+ "yjct",
+ "",
+ "",
+ },
+ []operation{
+ operation{
+ start: Loc{1, 0},
+ end: Loc{1, 0},
+ text: []string{
+ "b",
+ "r",
+ "fq",
+ },
+ },
+ operation{
+ start: Loc{3, 0},
+ end: Loc{0, 1},
+ text: []string{
+ "",
+ "",
+ },
+ },
+ },
+ []string{
+ "ib",
+ "r",
+ "fqoe",
+ "",
+ "yjct",
+ "",
+ "",
+ },
+ )
+}
+
+func TestAuto2(t *testing.T) {
+ check(
+ t,
+ []string{
+ "f",
+ "littnhskrq",
+ "utxvsizqnk",
+ "lslqz",
+ "jxn",
+ "gmm",
+ },
+ []operation{
+ operation{
+ start: Loc{1, 0},
+ end: Loc{1, 0},
+ text: []string{
+ "",
+ "o",
+ },
+ },
+ operation{
+ start: Loc{3, 1},
+ end: Loc{3, 1},
+ text: []string{
+ "zaq",
+ "avb",
+ },
+ },
+ operation{
+ start: Loc{4, 1},
+ end: Loc{1, 5},
+ text: []string{
+ "jlr",
+ "zl",
+ "j",
+ },
+ },
+ },
+ []string{
+ "f",
+ "o",
+ "litzaq",
+ "avbtjlr",
+ "zl",
+ "jmm",
+ },
+ )
+}
+
+func TestAuto3(t *testing.T) {
+ check(
+ t,
+ []string{
+ "ofw",
+ "qsxmziuvzw",
+ "rp",
+ "qsnymek",
+ "elth",
+ "wmgzbwudxz",
+ "iwsdkndh",
+ "bujlbwb",
+ "asuouxfv",
+ "xuccnb",
+ },
+ []operation{
+ operation{
+ start: Loc{2, 3},
+ end: Loc{2, 3},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "ofw",
+ "qsxmziuvzw",
+ "rp",
+ "qsnymek",
+ "elth",
+ "wmgzbwudxz",
+ "iwsdkndh",
+ "bujlbwb",
+ "asuouxfv",
+ "xuccnb",
+ },
+ )
+}
+
+func TestAuto4(t *testing.T) {
+ check(
+ t,
+ []string{
+ "fefymj",
+ "qum",
+ "vmiwxxaiqq",
+ "dz",
+ "lnqdgorosf",
+ },
+ []operation{
+ operation{
+ start: Loc{2, 0},
+ end: Loc{4, 0},
+ text: []string{
+ "hp",
+ },
+ },
+ operation{
+ start: Loc{6, 0},
+ end: Loc{0, 1},
+ text: []string{
+ "kcg",
+ "",
+ "mpx",
+ },
+ },
+ operation{
+ start: Loc{1, 1},
+ end: Loc{1, 1},
+ text: []string{
+ "",
+ "aw",
+ "",
+ },
+ },
+ operation{
+ start: Loc{1, 1},
+ end: Loc{1, 1},
+ text: []string{
+ "vqr",
+ "mo",
+ },
+ },
+ operation{
+ start: Loc{1, 3},
+ end: Loc{2, 4},
+ text: []string{
+ "xyc",
+ },
+ },
+ },
+ []string{
+ "fehpmjkcg",
+ "",
+ "mpxq",
+ "aw",
+ "vqr",
+ "moum",
+ "vmiwxxaiqq",
+ "dxycqdgorosf",
+ },
+ )
+}
+
+func TestBug19872UndoIsFunky(t *testing.T) {
+ check(
+ t,
+ []string{
+ "something",
+ " A",
+ "",
+ " B",
+ "something else",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 1},
+ end: Loc{1, 1},
+ text: []string{
+ "",
+ },
+ },
+ operation{
+ start: Loc{0, 2},
+ end: Loc{1, 3},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "something",
+ "A",
+ "B",
+ "something else",
+ },
+ )
+}
+
+func TestBug19872UndoIsFunky_2(t *testing.T) {
+ check(
+ t,
+ []string{
+ "something",
+ "A",
+ "B",
+ "something else",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 1},
+ end: Loc{0, 1},
+ text: []string{
+ " ",
+ },
+ },
+ operation{
+ start: Loc{0, 2},
+ end: Loc{0, 2},
+ text: []string{
+ "",
+ " ",
+ },
+ },
+ },
+ []string{
+ "something",
+ " A",
+ "",
+ " B",
+ "something else",
+ },
+ )
+}
+
+func TestInsertEmptyText(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 0},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestLastOpIsNoOp(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{1, 0},
+ text: []string{
+ "",
+ },
+ },
+ operation{
+ start: Loc{0, 3},
+ end: Loc{0, 3},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "y First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestInsertTextWithoutNewline1(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 0},
+ text: []string{
+ "foo ",
+ },
+ },
+ },
+ []string{
+ "foo My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestInsertTextWithoutNewline2(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{2, 0},
+ end: Loc{2, 0},
+ text: []string{
+ " foo",
+ },
+ },
+ },
+ []string{
+ "My foo First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestInsertOneNewline(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{3, 0},
+ end: Loc{3, 0},
+ text: []string{
+ "",
+ "",
+ },
+ },
+ },
+ []string{
+ "My ",
+ "First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestInsertTextWithOneNewline(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{2, 0},
+ end: Loc{2, 0},
+ text: []string{
+ " new line",
+ "No longer",
+ },
+ },
+ },
+ []string{
+ "My new line",
+ "No longer First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestInsertTextWithTwoNewlines(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{2, 0},
+ end: Loc{2, 0},
+ text: []string{
+ " new line",
+ "One more line in the middle",
+ "No longer",
+ },
+ },
+ },
+ []string{
+ "My new line",
+ "One more line in the middle",
+ "No longer First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestInsertTextWithManyNewlines(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{2, 0},
+ end: Loc{2, 0},
+ text: []string{
+ "",
+ "",
+ "",
+ "",
+ "",
+ },
+ },
+ },
+ []string{
+ "My",
+ "",
+ "",
+ "",
+ " First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestInsertMultipleNewlines(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{2, 0},
+ end: Loc{2, 0},
+ text: []string{
+ "",
+ "",
+ "",
+ "",
+ "",
+ },
+ },
+ operation{
+ start: Loc{14, 2},
+ end: Loc{14, 2},
+ text: []string{
+ "a",
+ "b",
+ },
+ },
+ },
+ []string{
+ "My",
+ "",
+ "",
+ "",
+ " First Line",
+ "\t\tMy Second Line",
+ " Third Linea",
+ "b",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestDeleteEmptyText(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 0},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestDeleteTextFromOneLine(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{1, 0},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "y First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestDeleteTextFromOneLine2(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{2, 0},
+ text: []string{
+ "a",
+ },
+ },
+ },
+ []string{
+ "a First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestDeleteAllTextFromALine(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{13, 0},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestDeleteTextFromTwoLines(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{3, 0},
+ end: Loc{5, 1},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "My Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestDeleteTextFromManyLines(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{3, 0},
+ end: Loc{4, 2},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "My Third Line",
+ "",
+ "1",
+ },
+ )
+}
+
+func TestDeleteEverything(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "1",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{1, 4},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "",
+ },
+ )
+}
+
+func TestTwoUnrelatedEdits(t *testing.T) {
+ check(
+ t,
+ []string{
+ "My First Line",
+ "\t\tMy Second Line",
+ " Third Line",
+ "",
+ "123",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 1},
+ end: Loc{2, 1},
+ text: []string{
+ "\t",
+ },
+ },
+ operation{
+ start: Loc{0, 2},
+ end: Loc{4, 2},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "My First Line",
+ "\tMy Second Line",
+ "Third Line",
+ "",
+ "123",
+ },
+ )
+}
+
+func TestTwoEditsOnOneLine(t *testing.T) {
+ check(
+ t,
+ []string{
+ "\t\tfirst\t ",
+ "\t\tsecond line",
+ "\tthird line",
+ "fourth line",
+ "\t\t<!@#fifth#@!>\t\t",
+ },
+ []operation{
+ operation{
+ start: Loc{2, 4},
+ end: Loc{6, 4},
+ text: []string{
+ "",
+ },
+ },
+ operation{
+ start: Loc{11, 4},
+ end: Loc{15, 4},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "\t\tfirst\t ",
+ "\t\tsecond line",
+ "\tthird line",
+ "fourth line",
+ "\t\tfifth\t\t",
+ },
+ )
+}
+
+func TestManyEdits(t *testing.T) {
+ check(
+ t,
+ []string{
+ "{\"x\" : 1}",
+ },
+ []operation{
+ operation{
+ start: Loc{1, 0},
+ end: Loc{1, 0},
+ text: []string{
+ "\n ",
+ },
+ },
+ operation{
+ start: Loc{4, 0},
+ end: Loc{5, 0},
+ text: []string{
+ "",
+ },
+ },
+ operation{
+ start: Loc{8, 0},
+ end: Loc{8, 0},
+ text: []string{
+ "\n",
+ },
+ },
+ },
+ []string{
+ "{",
+ " \"x\": 1",
+ "}",
+ },
+ )
+}
+
+func TestManyEditsReversed(t *testing.T) {
+ check(
+ t,
+ []string{
+ "{",
+ " \"x\": 1",
+ "}",
+ },
+ []operation{
+ operation{
+ start: Loc{1, 0},
+ end: Loc{2, 1},
+ text: []string{
+ "",
+ },
+ },
+ operation{
+ start: Loc{5, 1},
+ end: Loc{5, 1},
+ text: []string{
+ " ",
+ },
+ },
+ operation{
+ start: Loc{8, 1},
+ end: Loc{0, 2},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "{\"x\" : 1}",
+ },
+ )
+}
+
+func TestReplacingNewlines1(t *testing.T) {
+ check(
+ t,
+ []string{
+ "{",
+ "\"a\": true,",
+ "",
+ "\"b\": true",
+ "}",
+ },
+ []operation{
+ operation{
+ start: Loc{1, 0},
+ end: Loc{0, 1},
+ text: []string{
+ "",
+ "\t",
+ },
+ },
+ operation{
+ start: Loc{10, 1},
+ end: Loc{0, 3},
+ text: []string{
+ "",
+ "\t",
+ },
+ },
+ },
+ []string{
+ "{",
+ "\t\"a\": true,",
+ "\t\"b\": true",
+ "}",
+ },
+ )
+}
+
+func TestReplacingNewlines2(t *testing.T) {
+ check(
+ t,
+ []string{
+ "some text",
+ "some more text",
+ "now comes an empty line",
+ "",
+ "after empty line",
+ "and the last line",
+ },
+ []operation{
+ operation{
+ start: Loc{4, 0},
+ end: Loc{0, 2},
+ text: []string{
+ " text",
+ "some more text",
+ "some more text",
+ },
+ },
+ operation{
+ start: Loc{1, 2},
+ end: Loc{0, 3},
+ text: []string{
+ "o more lines",
+ "asd",
+ "asd",
+ "asd",
+ },
+ },
+ operation{
+ start: Loc{0, 4},
+ end: Loc{5, 4},
+ text: []string{
+ "zzzzzzzz",
+ },
+ },
+ operation{
+ start: Loc{10, 4},
+ end: Loc{15, 5},
+ text: []string{
+ "1",
+ "2",
+ "3",
+ "4",
+ },
+ },
+ },
+ []string{
+ "some text",
+ "some more text",
+ "some more textno more lines",
+ "asd",
+ "asd",
+ "asd",
+ "zzzzzzzz empt1",
+ "2",
+ "3",
+ "4ne",
+ },
+ )
+}
+
+func TestAdvanced1(t *testing.T) {
+ check(
+ t,
+ []string{
+ " { \"d\": [",
+ " null",
+ " ] /*comment*/",
+ " ,\"e\": /*comment*/ [null] }",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{1, 0},
+ text: []string{
+ "",
+ },
+ },
+ operation{
+ start: Loc{2, 0},
+ end: Loc{9, 0},
+ text: []string{
+ "",
+ " ",
+ },
+ },
+ operation{
+ start: Loc{15, 0},
+ end: Loc{13, 1},
+ text: []string{
+ "",
+ " ",
+ },
+ },
+ operation{
+ start: Loc{17, 1},
+ end: Loc{8, 2},
+ text: []string{
+ "",
+ " ",
+ },
+ },
+ operation{
+ start: Loc{21, 2},
+ end: Loc{8, 3},
+ text: []string{
+ "",
+ },
+ },
+ operation{
+ start: Loc{9, 3},
+ end: Loc{9, 3},
+ text: []string{
+ "",
+ " ",
+ },
+ },
+ operation{
+ start: Loc{27, 3},
+ end: Loc{27, 3},
+ text: []string{
+ "",
+ " ",
+ },
+ },
+ operation{
+ start: Loc{31, 3},
+ end: Loc{31, 3},
+ text: []string{
+ "",
+ " ",
+ },
+ },
+ operation{
+ start: Loc{32, 3},
+ end: Loc{33, 3},
+ text: []string{
+ "",
+ "",
+ },
+ },
+ },
+ []string{
+ "{",
+ " \"d\": [",
+ " null",
+ " ] /*comment*/,",
+ " \"e\": /*comment*/ [",
+ " null",
+ " ]",
+ "}",
+ },
+ )
+}
+
+func TestAdvancedSimplified(t *testing.T) {
+ check(
+ t,
+ []string{
+ " abc",
+ " ,def",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{3, 0},
+ text: []string{
+ "",
+ },
+ },
+ operation{
+ start: Loc{6, 0},
+ end: Loc{1, 1},
+ text: []string{
+ "",
+ },
+ },
+ operation{
+ start: Loc{2, 1},
+ end: Loc{2, 1},
+ text: []string{
+ "",
+ "",
+ },
+ },
+ },
+ []string{
+ "abc,",
+ "def",
+ },
+ )
+}
+
+func TestIssue144(t *testing.T) {
+ check(
+ t,
+ []string{
+ "package caddy",
+ "",
+ "func main() {",
+ "\tfmt.Println(\"Hello World! :)\")",
+ "}",
+ "",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 5},
+ text: []string{
+ "package caddy",
+ "",
+ "import \"fmt\"",
+ "",
+ "func main() {",
+ "\tfmt.Println(\"Hello World! :)\")",
+ "}",
+ "",
+ },
+ },
+ },
+ []string{
+ "package caddy",
+ "",
+ "import \"fmt\"",
+ "",
+ "func main() {",
+ "\tfmt.Println(\"Hello World! :)\")",
+ "}",
+ "",
+ },
+ )
+}
+
+func TestIssue2586ReplacingSelectedEndOfLineWithNewlineLocksUpTheDocument(t *testing.T) {
+ check(
+ t,
+ []string{
+ "something",
+ "interesting",
+ },
+ []operation{
+ operation{
+ start: Loc{9, 0},
+ end: Loc{0, 1},
+ text: []string{
+ "",
+ "",
+ },
+ },
+ },
+ []string{
+ "something",
+ "interesting",
+ },
+ )
+}
+
+func TestIssue3980(t *testing.T) {
+ check(
+ t,
+ []string{
+ "class A {",
+ " someProperty = false;",
+ " someMethod() {",
+ " this.someMethod();",
+ " }",
+ "}",
+ },
+ []operation{
+ operation{
+ start: Loc{7, 0},
+ end: Loc{8, 0},
+ text: []string{
+ "",
+ "",
+ },
+ },
+ operation{
+ start: Loc{16, 2},
+ end: Loc{17, 2},
+ text: []string{
+ "",
+ "",
+ },
+ },
+ operation{
+ start: Loc{17, 2},
+ end: Loc{17, 2},
+ text: []string{
+ " ",
+ },
+ },
+ operation{
+ start: Loc{4, 3},
+ end: Loc{4, 3},
+ text: []string{
+ " ",
+ },
+ },
+ },
+ []string{
+ "class A",
+ "{",
+ " someProperty = false;",
+ " someMethod()",
+ " {",
+ " this.someMethod();",
+ " }",
+ "}",
+ },
+ )
+}
+
+func TestTouchingEditsTwoInsertsAtTheSamePosition(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 0},
+ text: []string{
+ "a",
+ },
+ },
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 0},
+ text: []string{
+ "b",
+ },
+ },
+ },
+ []string{
+ "abhello world",
+ },
+ )
+}
+
+func TestTouchingEditsInsertAndReplaceTouching(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 0},
+ text: []string{
+ "b",
+ },
+ },
+ operation{
+ start: Loc{0, 0},
+ end: Loc{2, 0},
+ text: []string{
+ "ab",
+ },
+ },
+ },
+ []string{
+ "babllo world",
+ },
+ )
+}
+
+func TestTouchingEditsTwoTouchingReplaces(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{1, 0},
+ text: []string{
+ "H",
+ },
+ },
+ operation{
+ start: Loc{1, 0},
+ end: Loc{2, 0},
+ text: []string{
+ "E",
+ },
+ },
+ },
+ []string{
+ "HEllo world",
+ },
+ )
+}
+
+func TestTouchingEditsTwoTouchingDeletes(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{1, 0},
+ text: []string{
+ "",
+ },
+ },
+ operation{
+ start: Loc{1, 0},
+ end: Loc{2, 0},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "llo world",
+ },
+ )
+}
+
+func TestTouchingEditsInsertAndReplace(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 0},
+ text: []string{
+ "H",
+ },
+ },
+ operation{
+ start: Loc{0, 0},
+ end: Loc{2, 0},
+ text: []string{
+ "e",
+ },
+ },
+ },
+ []string{
+ "Hello world",
+ },
+ )
+}
+
+func TestTouchingEditsReplaceAndInsert(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{2, 0},
+ text: []string{
+ "H",
+ },
+ },
+ operation{
+ start: Loc{2, 0},
+ end: Loc{2, 0},
+ text: []string{
+ "e",
+ },
+ },
+ },
+ []string{
+ "Hello world",
+ },
+ )
+}
+
+func TestSingleDelete1(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{1, 0},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "ello world",
+ },
+ )
+}
+
+func TestSingleDelete2(t *testing.T) {
+ check(
+ t,
+ []string{
+ "helloworld",
+ },
+ []operation{
+ operation{
+ start: Loc{2, 0},
+ end: Loc{7, 0},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "herld",
+ },
+ )
+}
+
+func TestSingleDelete3(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{5, 0},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ " world",
+ },
+ )
+}
+
+func TestSingleDelete4(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{1, 0},
+ end: Loc{6, 0},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "hworld",
+ },
+ )
+}
+
+func TestSingleDelete5(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{11, 0},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "",
+ },
+ )
+}
+
+func TestMultiDelete6(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ "hello world",
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{5, 0},
+ end: Loc{5, 2},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "hello world",
+ },
+ )
+}
+
+func TestMultiDelete7(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ "hello world",
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{11, 0},
+ end: Loc{11, 2},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "hello world",
+ },
+ )
+}
+
+func TestMultiDelete8(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ "hello world",
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 2},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "hello world",
+ },
+ )
+}
+
+func TestMultiDelete9(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ "hello world",
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{11, 0},
+ end: Loc{0, 2},
+ text: []string{
+ "",
+ },
+ },
+ },
+ []string{
+ "hello worldhello world",
+ },
+ )
+}
+
+func TestSingleInsert1(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 0},
+ text: []string{
+ "xx",
+ },
+ },
+ },
+ []string{
+ "xxhello world",
+ },
+ )
+}
+
+func TestSingleInsert2(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{1, 0},
+ end: Loc{1, 0},
+ text: []string{
+ "xx",
+ },
+ },
+ },
+ []string{
+ "hxxello world",
+ },
+ )
+}
+
+func TestSingleInsert3(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{5, 0},
+ end: Loc{5, 0},
+ text: []string{
+ "xx",
+ },
+ },
+ },
+ []string{
+ "helloxx world",
+ },
+ )
+}
+
+func TestSingleInsert4(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{6, 0},
+ end: Loc{6, 0},
+ text: []string{
+ "xx",
+ },
+ },
+ },
+ []string{
+ "hello xxworld",
+ },
+ )
+}
+
+func TestSingleInsert5(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{11, 0},
+ end: Loc{11, 0},
+ text: []string{
+ "xx",
+ },
+ },
+ },
+ []string{
+ "hello worldxx",
+ },
+ )
+}
+
+func TestMultiInsert6(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{0, 0},
+ end: Loc{0, 0},
+ text: []string{
+ "\n",
+ },
+ },
+ },
+ []string{
+ "",
+ "hello world",
+ },
+ )
+}
+
+func TestMultiInsert7(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{11, 0},
+ end: Loc{11, 0},
+ text: []string{
+ "\n",
+ },
+ },
+ },
+ []string{
+ "hello world",
+ "",
+ },
+ )
+}
+
+func TestMultiInsert8(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{6, 0},
+ end: Loc{6, 0},
+ text: []string{
+ "\n",
+ },
+ },
+ },
+ []string{
+ "hello ",
+ "world",
+ },
+ )
+}
+
+func TestMultiInsert9(t *testing.T) {
+ check(
+ t,
+ []string{
+ "hello world",
+ "hello world",
+ },
+ []operation{
+ operation{
+ start: Loc{6, 0},
+ end: Loc{6, 0},
+ text: []string{
+ "xx\nyy",
+ },
+ },
+ },
+ []string{
+ "hello xx",
+ "yyworld",
+ "hello world",
+ },
+ )
+}
+
+func BenchmarkBuffer(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ TestAuto1(nil)
+ TestAuto2(nil)
+ TestAuto3(nil)
+ TestAuto4(nil)
+ TestBug19872UndoIsFunky(nil)
+ TestBug19872UndoIsFunky_2(nil)
+ TestInsertEmptyText(nil)
+ TestLastOpIsNoOp(nil)
+ TestInsertTextWithoutNewline1(nil)
+ TestInsertTextWithoutNewline2(nil)
+ TestInsertOneNewline(nil)
+ TestInsertTextWithOneNewline(nil)
+ TestInsertTextWithTwoNewlines(nil)
+ TestInsertTextWithManyNewlines(nil)
+ TestInsertMultipleNewlines(nil)
+ TestDeleteEmptyText(nil)
+ TestDeleteTextFromOneLine(nil)
+ TestDeleteTextFromOneLine2(nil)
+ TestDeleteAllTextFromALine(nil)
+ TestDeleteTextFromTwoLines(nil)
+ TestDeleteTextFromManyLines(nil)
+ TestDeleteEverything(nil)
+ TestTwoUnrelatedEdits(nil)
+ TestTwoEditsOnOneLine(nil)
+ TestManyEdits(nil)
+ TestManyEditsReversed(nil)
+ TestReplacingNewlines1(nil)
+ TestReplacingNewlines2(nil)
+ TestAdvanced1(nil)
+ TestAdvancedSimplified(nil)
+ TestIssue144(nil)
+ TestIssue2586ReplacingSelectedEndOfLineWithNewlineLocksUpTheDocument(nil)
+ TestIssue3980(nil)
+ TestTouchingEditsTwoInsertsAtTheSamePosition(nil)
+ TestTouchingEditsInsertAndReplaceTouching(nil)
+ TestTouchingEditsTwoTouchingReplaces(nil)
+ TestTouchingEditsTwoTouchingDeletes(nil)
+ TestTouchingEditsInsertAndReplace(nil)
+ TestTouchingEditsReplaceAndInsert(nil)
+ TestSingleDelete1(nil)
+ TestSingleDelete2(nil)
+ TestSingleDelete3(nil)
+ TestSingleDelete4(nil)
+ TestSingleDelete5(nil)
+ TestMultiDelete6(nil)
+ TestMultiDelete7(nil)
+ TestMultiDelete8(nil)
+ TestMultiDelete9(nil)
+ TestSingleInsert1(nil)
+ TestSingleInsert2(nil)
+ TestSingleInsert3(nil)
+ TestSingleInsert4(nil)
+ TestSingleInsert5(nil)
+ TestMultiInsert6(nil)
+ TestMultiInsert7(nil)
+ TestMultiInsert8(nil)
+ TestMultiInsert9(nil)
+ }
+}
--- /dev/null
+package buffer
+
+import (
+ "strings"
+ "testing"
+
+ testifyAssert "github.com/stretchr/testify/assert"
+ lua "github.com/yuin/gopher-lua"
+
+ ulua "github.com/zyedidia/micro/internal/lua"
+)
+
+type operation struct {
+ start Loc
+ end Loc
+ text []string
+}
+
+type asserter interface {
+ Equal(interface{}, interface{}, ...interface{}) bool
+ NotEqual(interface{}, interface{}, ...interface{}) bool
+}
+
+type noOpAsserter struct {
+}
+
+func (a *noOpAsserter) Equal(interface{}, interface{}, ...interface{}) bool {
+ return true
+}
+
+func (a *noOpAsserter) NotEqual(interface{}, interface{}, ...interface{}) bool {
+ return true
+}
+
+func init() {
+ ulua.L = lua.NewState()
+}
+
+func check(t *testing.T, before []string, operations []operation, after []string) {
+ var assert asserter
+ if t == nil {
+ // Benchmark mode; don't perform assertions
+ assert = &noOpAsserter{}
+ } else {
+ assert = testifyAssert.New(t)
+ }
+
+ b := NewBufferFromString(strings.Join(before, "\n"), "", BTDefault)
+
+ assert.NotEqual(b.GetName(), "")
+ assert.Equal(b.ExternallyModified(), false)
+ assert.Equal(b.Modified(), false)
+ assert.Equal(b.NumCursors(), 1)
+
+ checkText := func(lines []string) {
+ assert.Equal(b.Bytes(), []byte(strings.Join(lines, "\n")))
+ assert.Equal(b.LinesNum(), len(lines))
+ for i, s := range lines {
+ assert.Equal(b.Line(i), s)
+ assert.Equal(b.LineBytes(i), []byte(s))
+ }
+ }
+
+ checkText(before)
+
+ var cursors []*Cursor
+
+ for _, op := range operations {
+ cursor := NewCursor(b, op.start)
+ cursor.SetSelectionStart(op.start)
+ cursor.SetSelectionEnd(op.end)
+ b.AddCursor(cursor)
+ cursors = append(cursors, cursor)
+ }
+
+ assert.Equal(b.NumCursors(), 1+len(operations))
+
+ for i, op := range operations {
+ cursor := cursors[i]
+ cursor.DeleteSelection()
+ b.Insert(cursor.Loc, strings.Join(op.text, "\n"))
+ }
+
+ checkText(after)
+
+ for _ = range operations {
+ b.UndoOneEvent()
+ b.UndoOneEvent()
+ }
+
+ checkText(before)
+
+ for i, op := range operations {
+ cursor := cursors[i]
+ assert.Equal(cursor.Loc, op.start)
+ assert.Equal(cursor.CurSelection[0], op.start)
+ assert.Equal(cursor.CurSelection[1], op.end)
+ }
+
+ for _ = range operations {
+ b.RedoOneEvent()
+ b.RedoOneEvent()
+ }
+
+ checkText(after)
+
+ b.Close()
+}
--- /dev/null
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "regexp"
+ "strings"
+
+ "github.com/robertkrimen/otto/ast"
+ "github.com/robertkrimen/otto/parser"
+)
+
+type walker struct {
+ nodes []ast.Node
+}
+
+func (w *walker) Enter(node ast.Node) ast.Visitor {
+ w.nodes = append(w.nodes, node)
+ return w
+}
+
+func (w *walker) Exit(node ast.Node) {
+}
+
+func getAllNodes(node ast.Node) []ast.Node {
+ w := &walker{}
+ ast.Walk(w, node)
+ return w.nodes
+}
+
+func getCalls(node ast.Node, name string) []*ast.CallExpression {
+ nodes := []*ast.CallExpression{}
+ for _, n := range getAllNodes(node) {
+ if ce, ok := n.(*ast.CallExpression); ok {
+ var calleeName string
+ switch callee := ce.Callee.(type) {
+ case *ast.Identifier:
+ calleeName = callee.Name
+ case *ast.DotExpression:
+ calleeName = callee.Identifier.Name
+ default:
+ continue
+ }
+ if calleeName == name {
+ nodes = append(nodes, ce)
+ }
+ }
+ }
+ return nodes
+}
+
+func getPropertyValue(node ast.Node, key string) ast.Expression {
+ for _, p := range node.(*ast.ObjectLiteral).Value {
+ if p.Key == key {
+ return p.Value
+ }
+ }
+ return nil
+}
+
+type operation struct {
+ startLine int
+ startColumn int
+ endLine int
+ endColumn int
+ text []string
+}
+
+type check struct {
+ before []string
+ operations []operation
+ after []string
+}
+
+type test struct {
+ description string
+ checks []check
+}
+
+func stringSliceToGoSource(slice []string) string {
+ var b strings.Builder
+ b.WriteString("[]string{\n")
+ for _, s := range slice {
+ b.WriteString(fmt.Sprintf("%#v,\n", s))
+ }
+ b.WriteString("}")
+ return b.String()
+}
+
+func testToGoTest(test test, name string) string {
+ var b strings.Builder
+
+ b.WriteString("func Test")
+ b.WriteString(name)
+ b.WriteString("(t *testing.T) {\n")
+
+ for _, c := range test.checks {
+ b.WriteString("check(\n")
+ b.WriteString("t,\n")
+ b.WriteString(fmt.Sprintf("%v,\n", stringSliceToGoSource(c.before)))
+ b.WriteString("[]operation{\n")
+ for _, op := range c.operations {
+ b.WriteString("operation{\n")
+ b.WriteString(fmt.Sprintf("start: Loc{%v, %v},\n", op.startColumn, op.startLine))
+ b.WriteString(fmt.Sprintf("end: Loc{%v, %v},\n", op.endColumn, op.endLine))
+ b.WriteString(fmt.Sprintf("text: %v,\n", stringSliceToGoSource(op.text)))
+ b.WriteString("},\n")
+ }
+ b.WriteString("},\n")
+ b.WriteString(fmt.Sprintf("%v,\n", stringSliceToGoSource(c.after)))
+ b.WriteString(")\n")
+ }
+
+ b.WriteString("}\n")
+
+ return b.String()
+}
+
+func nodeToStringSlice(node ast.Node) []string {
+ var result []string
+ for _, s := range node.(*ast.ArrayLiteral).Value {
+ result = append(result, s.(*ast.StringLiteral).Value)
+ }
+ return result
+}
+
+func nodeToStringSlice2(node ast.Node) []string {
+ var result []string
+ for _, o := range node.(*ast.ArrayLiteral).Value {
+ result = append(result, getPropertyValue(o, "text").(*ast.StringLiteral).Value)
+ }
+ return result
+}
+
+func nodeToInt(node ast.Node) int {
+ return int(node.(*ast.NumberLiteral).Value.(int64))
+}
+
+func getChecks(node ast.Node) []check {
+ checks := []check{}
+
+ for _, ce := range getCalls(node, "testApplyEdits") {
+ if len(ce.ArgumentList) != 3 {
+ // Wrong function
+ continue
+ }
+
+ before := nodeToStringSlice2(ce.ArgumentList[0])
+ after := nodeToStringSlice2(ce.ArgumentList[2])
+
+ var operations []operation
+ for _, op := range ce.ArgumentList[1].(*ast.ArrayLiteral).Value {
+ args := getPropertyValue(op, "range").(*ast.NewExpression).ArgumentList
+ operations = append(operations, operation{
+ startLine: nodeToInt(args[0]) - 1,
+ startColumn: nodeToInt(args[1]) - 1,
+ endLine: nodeToInt(args[2]) - 1,
+ endColumn: nodeToInt(args[3]) - 1,
+ text: []string{getPropertyValue(op, "text").(*ast.StringLiteral).Value},
+ })
+ }
+
+ checks = append(checks, check{before, operations, after})
+ }
+
+ for _, ce := range getCalls(node, "testApplyEditsWithSyncedModels") {
+ if len(ce.ArgumentList) > 3 && ce.ArgumentList[3].(*ast.BooleanLiteral).Value {
+ // inputEditsAreInvalid == true
+ continue
+ }
+
+ before := nodeToStringSlice(ce.ArgumentList[0])
+ after := nodeToStringSlice(ce.ArgumentList[2])
+
+ var operations []operation
+ for _, op := range getCalls(ce.ArgumentList[1], "editOp") {
+ operations = append(operations, operation{
+ startLine: nodeToInt(op.ArgumentList[0]) - 1,
+ startColumn: nodeToInt(op.ArgumentList[1]) - 1,
+ endLine: nodeToInt(op.ArgumentList[2]) - 1,
+ endColumn: nodeToInt(op.ArgumentList[3]) - 1,
+ text: nodeToStringSlice(op.ArgumentList[4]),
+ })
+ }
+
+ checks = append(checks, check{before, operations, after})
+ }
+
+ return checks
+}
+
+func getTests(node ast.Node) []test {
+ tests := []test{}
+ for _, ce := range getCalls(node, "test") {
+ description := ce.ArgumentList[0].(*ast.StringLiteral).Value
+ body := ce.ArgumentList[1].(*ast.FunctionLiteral).Body
+ checks := getChecks(body)
+ if len(checks) > 0 {
+ tests = append(tests, test{description, checks})
+ }
+ }
+ return tests
+}
+
+func main() {
+ var tests []test
+
+ for _, filename := range os.Args[1:] {
+ source, err := ioutil.ReadFile(filename)
+ if err != nil {
+ log.Fatalln(err)
+ }
+
+ program, err := parser.ParseFile(nil, "", source, parser.IgnoreRegExpErrors)
+ if err != nil {
+ log.Fatalln(err)
+ }
+
+ tests = append(tests, getTests(program)...)
+ }
+
+ if len(tests) == 0 {
+ log.Fatalln("no tests found!")
+ }
+
+ fmt.Println("// This file is generated from VSCode model tests by the testgen tool.")
+ fmt.Println("// DO NOT EDIT THIS FILE BY HAND; your changes will be overwritten!\n")
+ fmt.Println("package buffer")
+ fmt.Println(`import "testing"`)
+
+ re := regexp.MustCompile(`[^\w]`)
+ usedNames := map[string]bool{}
+
+ var b strings.Builder
+
+ for _, test := range tests {
+ name := strings.Title(strings.ToLower(test.description))
+ name = re.ReplaceAllLiteralString(name, "")
+ if name == "" {
+ name = "Unnamed"
+ }
+ if usedNames[name] {
+ for i := 2; ; i++ {
+ newName := fmt.Sprintf("%v_%v", name, i)
+ if !usedNames[newName] {
+ name = newName
+ break
+ }
+ }
+ }
+ usedNames[name] = true
+
+ fmt.Println(testToGoTest(test, name))
+
+ b.WriteString("Test")
+ b.WriteString(name)
+ b.WriteString("(nil)\n")
+ }
+
+ fmt.Println("func BenchmarkBuffer(b *testing.B) {")
+ fmt.Println("for i := 0; i < b.N; i++ {")
+ fmt.Print(b.String())
+ fmt.Println("}")
+ fmt.Println("}")
+}