From c71a9149a68215c8768e21f4dee4700a8fd0539d Mon Sep 17 00:00:00 2001 From: "cluster-stack-bot[bot]" <143188378+cluster-stack-bot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 11:19:50 +0000 Subject: [PATCH] :seedling: Update Golang Dependencies group to v1.15.5 | datasource | package | from | to | | ---------- | ------------------------ | ------- | ------- | | go | github.com/goccy/go-yaml | v1.12.0 | v1.15.5 | --- go.mod | 10 +- go.sum | 31 +- vendor/github.com/fatih/color/LICENSE.md | 20 - vendor/github.com/fatih/color/README.md | 178 -- vendor/github.com/fatih/color/color.go | 618 ------- vendor/github.com/fatih/color/doc.go | 135 -- vendor/github.com/goccy/go-yaml/.gitignore | 2 + vendor/github.com/goccy/go-yaml/.golangci.yml | 42 + vendor/github.com/goccy/go-yaml/Makefile | 52 +- vendor/github.com/goccy/go-yaml/README.md | 54 +- vendor/github.com/goccy/go-yaml/ast/ast.go | 209 +-- vendor/github.com/goccy/go-yaml/decode.go | 724 +++++--- vendor/github.com/goccy/go-yaml/encode.go | 93 +- vendor/github.com/goccy/go-yaml/error.go | 47 +- .../goccy/go-yaml/internal/errors/error.go | 287 ++-- vendor/github.com/goccy/go-yaml/option.go | 7 +- .../github.com/goccy/go-yaml/parser/color.go | 28 + .../goccy/go-yaml/parser/context.go | 209 +-- .../github.com/goccy/go-yaml/parser/node.go | 248 +++ .../github.com/goccy/go-yaml/parser/option.go | 12 + .../github.com/goccy/go-yaml/parser/parser.go | 1451 ++++++++++------- .../github.com/goccy/go-yaml/parser/token.go | 668 ++++++++ vendor/github.com/goccy/go-yaml/path.go | 163 +- .../github.com/goccy/go-yaml/printer/color.go | 83 + .../goccy/go-yaml/printer/printer.go | 50 +- .../goccy/go-yaml/scanner/context.go | 251 ++- .../github.com/goccy/go-yaml/scanner/error.go | 17 + .../goccy/go-yaml/scanner/scanner.go | 1400 +++++++++++----- vendor/github.com/goccy/go-yaml/struct.go | 11 +- .../github.com/goccy/go-yaml/token/token.go | 254 +-- vendor/github.com/goccy/go-yaml/yaml.go | 33 +- vendor/github.com/mattn/go-colorable/LICENSE | 21 - .../github.com/mattn/go-colorable/README.md | 48 - .../mattn/go-colorable/colorable_appengine.go | 38 - .../mattn/go-colorable/colorable_others.go | 38 - .../mattn/go-colorable/colorable_windows.go | 1047 ------------ .../github.com/mattn/go-colorable/go.test.sh | 12 - .../mattn/go-colorable/noncolorable.go | 57 - vendor/github.com/mattn/go-isatty/LICENSE | 9 - vendor/github.com/mattn/go-isatty/README.md | 50 - vendor/github.com/mattn/go-isatty/doc.go | 2 - vendor/github.com/mattn/go-isatty/go.test.sh | 12 - .../github.com/mattn/go-isatty/isatty_bsd.go | 20 - .../mattn/go-isatty/isatty_others.go | 17 - .../mattn/go-isatty/isatty_plan9.go | 23 - .../mattn/go-isatty/isatty_solaris.go | 21 - .../mattn/go-isatty/isatty_tcgets.go | 20 - .../mattn/go-isatty/isatty_windows.go | 125 -- vendor/golang.org/x/xerrors/LICENSE | 27 - vendor/golang.org/x/xerrors/PATENTS | 22 - vendor/golang.org/x/xerrors/README | 2 - vendor/golang.org/x/xerrors/adaptor.go | 193 --- vendor/golang.org/x/xerrors/codereview.cfg | 1 - vendor/golang.org/x/xerrors/doc.go | 22 - vendor/golang.org/x/xerrors/errors.go | 33 - vendor/golang.org/x/xerrors/fmt.go | 187 --- vendor/golang.org/x/xerrors/format.go | 34 - vendor/golang.org/x/xerrors/frame.go | 56 - .../golang.org/x/xerrors/internal/internal.go | 8 - vendor/golang.org/x/xerrors/wrap.go | 106 -- vendor/modules.txt | 17 +- 61 files changed, 4405 insertions(+), 5250 deletions(-) delete mode 100644 vendor/github.com/fatih/color/LICENSE.md delete mode 100644 vendor/github.com/fatih/color/README.md delete mode 100644 vendor/github.com/fatih/color/color.go delete mode 100644 vendor/github.com/fatih/color/doc.go create mode 100644 vendor/github.com/goccy/go-yaml/.gitignore create mode 100644 vendor/github.com/goccy/go-yaml/.golangci.yml create mode 100644 vendor/github.com/goccy/go-yaml/parser/color.go create mode 100644 vendor/github.com/goccy/go-yaml/parser/node.go create mode 100644 vendor/github.com/goccy/go-yaml/parser/option.go create mode 100644 vendor/github.com/goccy/go-yaml/parser/token.go create mode 100644 vendor/github.com/goccy/go-yaml/printer/color.go create mode 100644 vendor/github.com/goccy/go-yaml/scanner/error.go delete mode 100644 vendor/github.com/mattn/go-colorable/LICENSE delete mode 100644 vendor/github.com/mattn/go-colorable/README.md delete mode 100644 vendor/github.com/mattn/go-colorable/colorable_appengine.go delete mode 100644 vendor/github.com/mattn/go-colorable/colorable_others.go delete mode 100644 vendor/github.com/mattn/go-colorable/colorable_windows.go delete mode 100644 vendor/github.com/mattn/go-colorable/go.test.sh delete mode 100644 vendor/github.com/mattn/go-colorable/noncolorable.go delete mode 100644 vendor/github.com/mattn/go-isatty/LICENSE delete mode 100644 vendor/github.com/mattn/go-isatty/README.md delete mode 100644 vendor/github.com/mattn/go-isatty/doc.go delete mode 100644 vendor/github.com/mattn/go-isatty/go.test.sh delete mode 100644 vendor/github.com/mattn/go-isatty/isatty_bsd.go delete mode 100644 vendor/github.com/mattn/go-isatty/isatty_others.go delete mode 100644 vendor/github.com/mattn/go-isatty/isatty_plan9.go delete mode 100644 vendor/github.com/mattn/go-isatty/isatty_solaris.go delete mode 100644 vendor/github.com/mattn/go-isatty/isatty_tcgets.go delete mode 100644 vendor/github.com/mattn/go-isatty/isatty_windows.go delete mode 100644 vendor/golang.org/x/xerrors/LICENSE delete mode 100644 vendor/golang.org/x/xerrors/PATENTS delete mode 100644 vendor/golang.org/x/xerrors/README delete mode 100644 vendor/golang.org/x/xerrors/adaptor.go delete mode 100644 vendor/golang.org/x/xerrors/codereview.cfg delete mode 100644 vendor/golang.org/x/xerrors/doc.go delete mode 100644 vendor/golang.org/x/xerrors/errors.go delete mode 100644 vendor/golang.org/x/xerrors/fmt.go delete mode 100644 vendor/golang.org/x/xerrors/format.go delete mode 100644 vendor/golang.org/x/xerrors/frame.go delete mode 100644 vendor/golang.org/x/xerrors/internal/internal.go delete mode 100644 vendor/golang.org/x/xerrors/wrap.go diff --git a/go.mod b/go.mod index c936466..69e5ecb 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,12 @@ module github.com/SovereignCloudStack/csctl-plugin-openstack -go 1.21 +go 1.21.0 + +toolchain go1.21.13 require ( github.com/SovereignCloudStack/csctl v0.0.3 - github.com/goccy/go-yaml v1.12.0 + github.com/goccy/go-yaml v1.15.5 github.com/gophercloud/gophercloud v1.14.0 github.com/minio/minio-go/v7 v7.0.76 github.com/spf13/cobra v1.8.1 @@ -13,7 +15,6 @@ require ( require ( github.com/SovereignCloudStack/cluster-stack-operator v0.1.0-alpha.5 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/fatih/color v1.13.0 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/goccy/go-json v0.10.3 // indirect github.com/google/uuid v1.6.0 // indirect @@ -21,8 +22,6 @@ require ( github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/kr/pretty v0.3.1 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/rs/xid v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect @@ -31,7 +30,6 @@ require ( golang.org/x/net v0.28.0 // indirect golang.org/x/sys v0.24.0 // indirect golang.org/x/text v0.17.0 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 435a47e..f78d6ce 100644 --- a/go.sum +++ b/go.sum @@ -8,22 +8,12 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= -github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/goccy/go-yaml v1.15.5 h1:3XvnIQra8CW/7TPV2zks7zR9zUCrPTtW17HSptwXWis= +github.com/goccy/go-yaml v1.15.5/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gophercloud/gophercloud v1.14.0 h1:Bt9zQDhPrbd4qX7EILGmy+i7GP35cc+AAL2+wIJpUE8= @@ -42,16 +32,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.76 h1:9nxHH2XDai61cT/EFhyIw/wW4vJfpPNvl7lSFpRt+Ng= @@ -78,15 +58,10 @@ golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -94,8 +69,6 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/vendor/github.com/fatih/color/LICENSE.md b/vendor/github.com/fatih/color/LICENSE.md deleted file mode 100644 index 25fdaf6..0000000 --- a/vendor/github.com/fatih/color/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Fatih Arslan - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md deleted file mode 100644 index 5152bf5..0000000 --- a/vendor/github.com/fatih/color/README.md +++ /dev/null @@ -1,178 +0,0 @@ -# color [![](https://github.com/fatih/color/workflows/build/badge.svg)](https://github.com/fatih/color/actions) [![PkgGoDev](https://pkg.go.dev/badge/github.com/fatih/color)](https://pkg.go.dev/github.com/fatih/color) - -Color lets you use colorized outputs in terms of [ANSI Escape -Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It -has support for Windows too! The API can be used in several ways, pick one that -suits you. - -![Color](https://user-images.githubusercontent.com/438920/96832689-03b3e000-13f4-11eb-9803-46f4c4de3406.jpg) - - -## Install - -```bash -go get github.com/fatih/color -``` - -## Examples - -### Standard colors - -```go -// Print with default helper functions -color.Cyan("Prints text in cyan.") - -// A newline will be appended automatically -color.Blue("Prints %s in blue.", "text") - -// These are using the default foreground colors -color.Red("We have red") -color.Magenta("And many others ..") - -``` - -### Mix and reuse colors - -```go -// Create a new color object -c := color.New(color.FgCyan).Add(color.Underline) -c.Println("Prints cyan text with an underline.") - -// Or just add them to New() -d := color.New(color.FgCyan, color.Bold) -d.Printf("This prints bold cyan %s\n", "too!.") - -// Mix up foreground and background colors, create new mixes! -red := color.New(color.FgRed) - -boldRed := red.Add(color.Bold) -boldRed.Println("This will print text in bold red.") - -whiteBackground := red.Add(color.BgWhite) -whiteBackground.Println("Red text with white background.") -``` - -### Use your own output (io.Writer) - -```go -// Use your own io.Writer output -color.New(color.FgBlue).Fprintln(myWriter, "blue color!") - -blue := color.New(color.FgBlue) -blue.Fprint(writer, "This will print text in blue.") -``` - -### Custom print functions (PrintFunc) - -```go -// Create a custom print function for convenience -red := color.New(color.FgRed).PrintfFunc() -red("Warning") -red("Error: %s", err) - -// Mix up multiple attributes -notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() -notice("Don't forget this...") -``` - -### Custom fprint functions (FprintFunc) - -```go -blue := color.New(color.FgBlue).FprintfFunc() -blue(myWriter, "important notice: %s", stars) - -// Mix up with multiple attributes -success := color.New(color.Bold, color.FgGreen).FprintlnFunc() -success(myWriter, "Don't forget this...") -``` - -### Insert into noncolor strings (SprintFunc) - -```go -// Create SprintXxx functions to mix strings with other non-colorized strings: -yellow := color.New(color.FgYellow).SprintFunc() -red := color.New(color.FgRed).SprintFunc() -fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error")) - -info := color.New(color.FgWhite, color.BgGreen).SprintFunc() -fmt.Printf("This %s rocks!\n", info("package")) - -// Use helper functions -fmt.Println("This", color.RedString("warning"), "should be not neglected.") -fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.") - -// Windows supported too! Just don't forget to change the output to color.Output -fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) -``` - -### Plug into existing code - -```go -// Use handy standard colors -color.Set(color.FgYellow) - -fmt.Println("Existing text will now be in yellow") -fmt.Printf("This one %s\n", "too") - -color.Unset() // Don't forget to unset - -// You can mix up parameters -color.Set(color.FgMagenta, color.Bold) -defer color.Unset() // Use it in your function - -fmt.Println("All text will now be bold magenta.") -``` - -### Disable/Enable color - -There might be a case where you want to explicitly disable/enable color output. the -`go-isatty` package will automatically disable color output for non-tty output streams -(for example if the output were piped directly to `less`). - -The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment -variable is set (regardless of its value). - -`Color` has support to disable/enable colors programatically both globally and -for single color definitions. For example suppose you have a CLI app and a -`--no-color` bool flag. You can easily disable the color output with: - -```go -var flagNoColor = flag.Bool("no-color", false, "Disable color output") - -if *flagNoColor { - color.NoColor = true // disables colorized output -} -``` - -It also has support for single color definitions (local). You can -disable/enable color output on the fly: - -```go -c := color.New(color.FgCyan) -c.Println("Prints cyan text") - -c.DisableColor() -c.Println("This is printed without any color") - -c.EnableColor() -c.Println("This prints again cyan...") -``` - -## GitHub Actions - -To output color in GitHub Actions (or other CI systems that support ANSI colors), make sure to set `color.NoColor = false` so that it bypasses the check for non-tty output streams. - -## Todo - -* Save/Return previous values -* Evaluate fmt.Formatter interface - - -## Credits - - * [Fatih Arslan](https://github.com/fatih) - * Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable) - -## License - -The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details diff --git a/vendor/github.com/fatih/color/color.go b/vendor/github.com/fatih/color/color.go deleted file mode 100644 index 98a60f3..0000000 --- a/vendor/github.com/fatih/color/color.go +++ /dev/null @@ -1,618 +0,0 @@ -package color - -import ( - "fmt" - "io" - "os" - "strconv" - "strings" - "sync" - - "github.com/mattn/go-colorable" - "github.com/mattn/go-isatty" -) - -var ( - // NoColor defines if the output is colorized or not. It's dynamically set to - // false or true based on the stdout's file descriptor referring to a terminal - // or not. It's also set to true if the NO_COLOR environment variable is - // set (regardless of its value). This is a global option and affects all - // colors. For more control over each color block use the methods - // DisableColor() individually. - NoColor = noColorExists() || os.Getenv("TERM") == "dumb" || - (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) - - // Output defines the standard output of the print functions. By default - // os.Stdout is used. - Output = colorable.NewColorableStdout() - - // Error defines a color supporting writer for os.Stderr. - Error = colorable.NewColorableStderr() - - // colorsCache is used to reduce the count of created Color objects and - // allows to reuse already created objects with required Attribute. - colorsCache = make(map[Attribute]*Color) - colorsCacheMu sync.Mutex // protects colorsCache -) - -// noColorExists returns true if the environment variable NO_COLOR exists. -func noColorExists() bool { - _, exists := os.LookupEnv("NO_COLOR") - return exists -} - -// Color defines a custom color object which is defined by SGR parameters. -type Color struct { - params []Attribute - noColor *bool -} - -// Attribute defines a single SGR Code -type Attribute int - -const escape = "\x1b" - -// Base attributes -const ( - Reset Attribute = iota - Bold - Faint - Italic - Underline - BlinkSlow - BlinkRapid - ReverseVideo - Concealed - CrossedOut -) - -// Foreground text colors -const ( - FgBlack Attribute = iota + 30 - FgRed - FgGreen - FgYellow - FgBlue - FgMagenta - FgCyan - FgWhite -) - -// Foreground Hi-Intensity text colors -const ( - FgHiBlack Attribute = iota + 90 - FgHiRed - FgHiGreen - FgHiYellow - FgHiBlue - FgHiMagenta - FgHiCyan - FgHiWhite -) - -// Background text colors -const ( - BgBlack Attribute = iota + 40 - BgRed - BgGreen - BgYellow - BgBlue - BgMagenta - BgCyan - BgWhite -) - -// Background Hi-Intensity text colors -const ( - BgHiBlack Attribute = iota + 100 - BgHiRed - BgHiGreen - BgHiYellow - BgHiBlue - BgHiMagenta - BgHiCyan - BgHiWhite -) - -// New returns a newly created color object. -func New(value ...Attribute) *Color { - c := &Color{ - params: make([]Attribute, 0), - } - - if noColorExists() { - c.noColor = boolPtr(true) - } - - c.Add(value...) - return c -} - -// Set sets the given parameters immediately. It will change the color of -// output with the given SGR parameters until color.Unset() is called. -func Set(p ...Attribute) *Color { - c := New(p...) - c.Set() - return c -} - -// Unset resets all escape attributes and clears the output. Usually should -// be called after Set(). -func Unset() { - if NoColor { - return - } - - fmt.Fprintf(Output, "%s[%dm", escape, Reset) -} - -// Set sets the SGR sequence. -func (c *Color) Set() *Color { - if c.isNoColorSet() { - return c - } - - fmt.Fprintf(Output, c.format()) - return c -} - -func (c *Color) unset() { - if c.isNoColorSet() { - return - } - - Unset() -} - -func (c *Color) setWriter(w io.Writer) *Color { - if c.isNoColorSet() { - return c - } - - fmt.Fprintf(w, c.format()) - return c -} - -func (c *Color) unsetWriter(w io.Writer) { - if c.isNoColorSet() { - return - } - - if NoColor { - return - } - - fmt.Fprintf(w, "%s[%dm", escape, Reset) -} - -// Add is used to chain SGR parameters. Use as many as parameters to combine -// and create custom color objects. Example: Add(color.FgRed, color.Underline). -func (c *Color) Add(value ...Attribute) *Color { - c.params = append(c.params, value...) - return c -} - -func (c *Color) prepend(value Attribute) { - c.params = append(c.params, 0) - copy(c.params[1:], c.params[0:]) - c.params[0] = value -} - -// Fprint formats using the default formats for its operands and writes to w. -// Spaces are added between operands when neither is a string. -// It returns the number of bytes written and any write error encountered. -// On Windows, users should wrap w with colorable.NewColorable() if w is of -// type *os.File. -func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) { - c.setWriter(w) - defer c.unsetWriter(w) - - return fmt.Fprint(w, a...) -} - -// Print formats using the default formats for its operands and writes to -// standard output. Spaces are added between operands when neither is a -// string. It returns the number of bytes written and any write error -// encountered. This is the standard fmt.Print() method wrapped with the given -// color. -func (c *Color) Print(a ...interface{}) (n int, err error) { - c.Set() - defer c.unset() - - return fmt.Fprint(Output, a...) -} - -// Fprintf formats according to a format specifier and writes to w. -// It returns the number of bytes written and any write error encountered. -// On Windows, users should wrap w with colorable.NewColorable() if w is of -// type *os.File. -func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { - c.setWriter(w) - defer c.unsetWriter(w) - - return fmt.Fprintf(w, format, a...) -} - -// Printf formats according to a format specifier and writes to standard output. -// It returns the number of bytes written and any write error encountered. -// This is the standard fmt.Printf() method wrapped with the given color. -func (c *Color) Printf(format string, a ...interface{}) (n int, err error) { - c.Set() - defer c.unset() - - return fmt.Fprintf(Output, format, a...) -} - -// Fprintln formats using the default formats for its operands and writes to w. -// Spaces are always added between operands and a newline is appended. -// On Windows, users should wrap w with colorable.NewColorable() if w is of -// type *os.File. -func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { - c.setWriter(w) - defer c.unsetWriter(w) - - return fmt.Fprintln(w, a...) -} - -// Println formats using the default formats for its operands and writes to -// standard output. Spaces are always added between operands and a newline is -// appended. It returns the number of bytes written and any write error -// encountered. This is the standard fmt.Print() method wrapped with the given -// color. -func (c *Color) Println(a ...interface{}) (n int, err error) { - c.Set() - defer c.unset() - - return fmt.Fprintln(Output, a...) -} - -// Sprint is just like Print, but returns a string instead of printing it. -func (c *Color) Sprint(a ...interface{}) string { - return c.wrap(fmt.Sprint(a...)) -} - -// Sprintln is just like Println, but returns a string instead of printing it. -func (c *Color) Sprintln(a ...interface{}) string { - return c.wrap(fmt.Sprintln(a...)) -} - -// Sprintf is just like Printf, but returns a string instead of printing it. -func (c *Color) Sprintf(format string, a ...interface{}) string { - return c.wrap(fmt.Sprintf(format, a...)) -} - -// FprintFunc returns a new function that prints the passed arguments as -// colorized with color.Fprint(). -func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) { - return func(w io.Writer, a ...interface{}) { - c.Fprint(w, a...) - } -} - -// PrintFunc returns a new function that prints the passed arguments as -// colorized with color.Print(). -func (c *Color) PrintFunc() func(a ...interface{}) { - return func(a ...interface{}) { - c.Print(a...) - } -} - -// FprintfFunc returns a new function that prints the passed arguments as -// colorized with color.Fprintf(). -func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) { - return func(w io.Writer, format string, a ...interface{}) { - c.Fprintf(w, format, a...) - } -} - -// PrintfFunc returns a new function that prints the passed arguments as -// colorized with color.Printf(). -func (c *Color) PrintfFunc() func(format string, a ...interface{}) { - return func(format string, a ...interface{}) { - c.Printf(format, a...) - } -} - -// FprintlnFunc returns a new function that prints the passed arguments as -// colorized with color.Fprintln(). -func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) { - return func(w io.Writer, a ...interface{}) { - c.Fprintln(w, a...) - } -} - -// PrintlnFunc returns a new function that prints the passed arguments as -// colorized with color.Println(). -func (c *Color) PrintlnFunc() func(a ...interface{}) { - return func(a ...interface{}) { - c.Println(a...) - } -} - -// SprintFunc returns a new function that returns colorized strings for the -// given arguments with fmt.Sprint(). Useful to put into or mix into other -// string. Windows users should use this in conjunction with color.Output, example: -// -// put := New(FgYellow).SprintFunc() -// fmt.Fprintf(color.Output, "This is a %s", put("warning")) -func (c *Color) SprintFunc() func(a ...interface{}) string { - return func(a ...interface{}) string { - return c.wrap(fmt.Sprint(a...)) - } -} - -// SprintfFunc returns a new function that returns colorized strings for the -// given arguments with fmt.Sprintf(). Useful to put into or mix into other -// string. Windows users should use this in conjunction with color.Output. -func (c *Color) SprintfFunc() func(format string, a ...interface{}) string { - return func(format string, a ...interface{}) string { - return c.wrap(fmt.Sprintf(format, a...)) - } -} - -// SprintlnFunc returns a new function that returns colorized strings for the -// given arguments with fmt.Sprintln(). Useful to put into or mix into other -// string. Windows users should use this in conjunction with color.Output. -func (c *Color) SprintlnFunc() func(a ...interface{}) string { - return func(a ...interface{}) string { - return c.wrap(fmt.Sprintln(a...)) - } -} - -// sequence returns a formatted SGR sequence to be plugged into a "\x1b[...m" -// an example output might be: "1;36" -> bold cyan -func (c *Color) sequence() string { - format := make([]string, len(c.params)) - for i, v := range c.params { - format[i] = strconv.Itoa(int(v)) - } - - return strings.Join(format, ";") -} - -// wrap wraps the s string with the colors attributes. The string is ready to -// be printed. -func (c *Color) wrap(s string) string { - if c.isNoColorSet() { - return s - } - - return c.format() + s + c.unformat() -} - -func (c *Color) format() string { - return fmt.Sprintf("%s[%sm", escape, c.sequence()) -} - -func (c *Color) unformat() string { - return fmt.Sprintf("%s[%dm", escape, Reset) -} - -// DisableColor disables the color output. Useful to not change any existing -// code and still being able to output. Can be used for flags like -// "--no-color". To enable back use EnableColor() method. -func (c *Color) DisableColor() { - c.noColor = boolPtr(true) -} - -// EnableColor enables the color output. Use it in conjunction with -// DisableColor(). Otherwise this method has no side effects. -func (c *Color) EnableColor() { - c.noColor = boolPtr(false) -} - -func (c *Color) isNoColorSet() bool { - // check first if we have user set action - if c.noColor != nil { - return *c.noColor - } - - // if not return the global option, which is disabled by default - return NoColor -} - -// Equals returns a boolean value indicating whether two colors are equal. -func (c *Color) Equals(c2 *Color) bool { - if len(c.params) != len(c2.params) { - return false - } - - for _, attr := range c.params { - if !c2.attrExists(attr) { - return false - } - } - - return true -} - -func (c *Color) attrExists(a Attribute) bool { - for _, attr := range c.params { - if attr == a { - return true - } - } - - return false -} - -func boolPtr(v bool) *bool { - return &v -} - -func getCachedColor(p Attribute) *Color { - colorsCacheMu.Lock() - defer colorsCacheMu.Unlock() - - c, ok := colorsCache[p] - if !ok { - c = New(p) - colorsCache[p] = c - } - - return c -} - -func colorPrint(format string, p Attribute, a ...interface{}) { - c := getCachedColor(p) - - if !strings.HasSuffix(format, "\n") { - format += "\n" - } - - if len(a) == 0 { - c.Print(format) - } else { - c.Printf(format, a...) - } -} - -func colorString(format string, p Attribute, a ...interface{}) string { - c := getCachedColor(p) - - if len(a) == 0 { - return c.SprintFunc()(format) - } - - return c.SprintfFunc()(format, a...) -} - -// Black is a convenient helper function to print with black foreground. A -// newline is appended to format by default. -func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) } - -// Red is a convenient helper function to print with red foreground. A -// newline is appended to format by default. -func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) } - -// Green is a convenient helper function to print with green foreground. A -// newline is appended to format by default. -func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) } - -// Yellow is a convenient helper function to print with yellow foreground. -// A newline is appended to format by default. -func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) } - -// Blue is a convenient helper function to print with blue foreground. A -// newline is appended to format by default. -func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) } - -// Magenta is a convenient helper function to print with magenta foreground. -// A newline is appended to format by default. -func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) } - -// Cyan is a convenient helper function to print with cyan foreground. A -// newline is appended to format by default. -func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) } - -// White is a convenient helper function to print with white foreground. A -// newline is appended to format by default. -func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) } - -// BlackString is a convenient helper function to return a string with black -// foreground. -func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) } - -// RedString is a convenient helper function to return a string with red -// foreground. -func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) } - -// GreenString is a convenient helper function to return a string with green -// foreground. -func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) } - -// YellowString is a convenient helper function to return a string with yellow -// foreground. -func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) } - -// BlueString is a convenient helper function to return a string with blue -// foreground. -func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) } - -// MagentaString is a convenient helper function to return a string with magenta -// foreground. -func MagentaString(format string, a ...interface{}) string { - return colorString(format, FgMagenta, a...) -} - -// CyanString is a convenient helper function to return a string with cyan -// foreground. -func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) } - -// WhiteString is a convenient helper function to return a string with white -// foreground. -func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) } - -// HiBlack is a convenient helper function to print with hi-intensity black foreground. A -// newline is appended to format by default. -func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) } - -// HiRed is a convenient helper function to print with hi-intensity red foreground. A -// newline is appended to format by default. -func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) } - -// HiGreen is a convenient helper function to print with hi-intensity green foreground. A -// newline is appended to format by default. -func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) } - -// HiYellow is a convenient helper function to print with hi-intensity yellow foreground. -// A newline is appended to format by default. -func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) } - -// HiBlue is a convenient helper function to print with hi-intensity blue foreground. A -// newline is appended to format by default. -func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) } - -// HiMagenta is a convenient helper function to print with hi-intensity magenta foreground. -// A newline is appended to format by default. -func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) } - -// HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A -// newline is appended to format by default. -func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) } - -// HiWhite is a convenient helper function to print with hi-intensity white foreground. A -// newline is appended to format by default. -func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) } - -// HiBlackString is a convenient helper function to return a string with hi-intensity black -// foreground. -func HiBlackString(format string, a ...interface{}) string { - return colorString(format, FgHiBlack, a...) -} - -// HiRedString is a convenient helper function to return a string with hi-intensity red -// foreground. -func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) } - -// HiGreenString is a convenient helper function to return a string with hi-intensity green -// foreground. -func HiGreenString(format string, a ...interface{}) string { - return colorString(format, FgHiGreen, a...) -} - -// HiYellowString is a convenient helper function to return a string with hi-intensity yellow -// foreground. -func HiYellowString(format string, a ...interface{}) string { - return colorString(format, FgHiYellow, a...) -} - -// HiBlueString is a convenient helper function to return a string with hi-intensity blue -// foreground. -func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) } - -// HiMagentaString is a convenient helper function to return a string with hi-intensity magenta -// foreground. -func HiMagentaString(format string, a ...interface{}) string { - return colorString(format, FgHiMagenta, a...) -} - -// HiCyanString is a convenient helper function to return a string with hi-intensity cyan -// foreground. -func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) } - -// HiWhiteString is a convenient helper function to return a string with hi-intensity white -// foreground. -func HiWhiteString(format string, a ...interface{}) string { - return colorString(format, FgHiWhite, a...) -} diff --git a/vendor/github.com/fatih/color/doc.go b/vendor/github.com/fatih/color/doc.go deleted file mode 100644 index 04541de..0000000 --- a/vendor/github.com/fatih/color/doc.go +++ /dev/null @@ -1,135 +0,0 @@ -/* -Package color is an ANSI color package to output colorized or SGR defined -output to the standard output. The API can be used in several way, pick one -that suits you. - -Use simple and default helper functions with predefined foreground colors: - - color.Cyan("Prints text in cyan.") - - // a newline will be appended automatically - color.Blue("Prints %s in blue.", "text") - - // More default foreground colors.. - color.Red("We have red") - color.Yellow("Yellow color too!") - color.Magenta("And many others ..") - - // Hi-intensity colors - color.HiGreen("Bright green color.") - color.HiBlack("Bright black means gray..") - color.HiWhite("Shiny white color!") - -However there are times where custom color mixes are required. Below are some -examples to create custom color objects and use the print functions of each -separate color object. - - // Create a new color object - c := color.New(color.FgCyan).Add(color.Underline) - c.Println("Prints cyan text with an underline.") - - // Or just add them to New() - d := color.New(color.FgCyan, color.Bold) - d.Printf("This prints bold cyan %s\n", "too!.") - - - // Mix up foreground and background colors, create new mixes! - red := color.New(color.FgRed) - - boldRed := red.Add(color.Bold) - boldRed.Println("This will print text in bold red.") - - whiteBackground := red.Add(color.BgWhite) - whiteBackground.Println("Red text with White background.") - - // Use your own io.Writer output - color.New(color.FgBlue).Fprintln(myWriter, "blue color!") - - blue := color.New(color.FgBlue) - blue.Fprint(myWriter, "This will print text in blue.") - -You can create PrintXxx functions to simplify even more: - - // Create a custom print function for convenient - red := color.New(color.FgRed).PrintfFunc() - red("warning") - red("error: %s", err) - - // Mix up multiple attributes - notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() - notice("don't forget this...") - -You can also FprintXxx functions to pass your own io.Writer: - - blue := color.New(FgBlue).FprintfFunc() - blue(myWriter, "important notice: %s", stars) - - // Mix up with multiple attributes - success := color.New(color.Bold, color.FgGreen).FprintlnFunc() - success(myWriter, don't forget this...") - - -Or create SprintXxx functions to mix strings with other non-colorized strings: - - yellow := New(FgYellow).SprintFunc() - red := New(FgRed).SprintFunc() - - fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error")) - - info := New(FgWhite, BgGreen).SprintFunc() - fmt.Printf("this %s rocks!\n", info("package")) - -Windows support is enabled by default. All Print functions work as intended. -However only for color.SprintXXX functions, user should use fmt.FprintXXX and -set the output to color.Output: - - fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) - - info := New(FgWhite, BgGreen).SprintFunc() - fmt.Fprintf(color.Output, "this %s rocks!\n", info("package")) - -Using with existing code is possible. Just use the Set() method to set the -standard output to the given parameters. That way a rewrite of an existing -code is not required. - - // Use handy standard colors. - color.Set(color.FgYellow) - - fmt.Println("Existing text will be now in Yellow") - fmt.Printf("This one %s\n", "too") - - color.Unset() // don't forget to unset - - // You can mix up parameters - color.Set(color.FgMagenta, color.Bold) - defer color.Unset() // use it in your function - - fmt.Println("All text will be now bold magenta.") - -There might be a case where you want to disable color output (for example to -pipe the standard output of your app to somewhere else). `Color` has support to -disable colors both globally and for single color definition. For example -suppose you have a CLI app and a `--no-color` bool flag. You can easily disable -the color output with: - - var flagNoColor = flag.Bool("no-color", false, "Disable color output") - - if *flagNoColor { - color.NoColor = true // disables colorized output - } - -You can also disable the color by setting the NO_COLOR environment variable to any value. - -It also has support for single color definitions (local). You can -disable/enable color output on the fly: - - c := color.New(color.FgCyan) - c.Println("Prints cyan text") - - c.DisableColor() - c.Println("This is printed without any color") - - c.EnableColor() - c.Println("This prints again cyan...") -*/ -package color diff --git a/vendor/github.com/goccy/go-yaml/.gitignore b/vendor/github.com/goccy/go-yaml/.gitignore new file mode 100644 index 0000000..869fe9f --- /dev/null +++ b/vendor/github.com/goccy/go-yaml/.gitignore @@ -0,0 +1,2 @@ +bin/ +cover.out diff --git a/vendor/github.com/goccy/go-yaml/.golangci.yml b/vendor/github.com/goccy/go-yaml/.golangci.yml new file mode 100644 index 0000000..ec8d731 --- /dev/null +++ b/vendor/github.com/goccy/go-yaml/.golangci.yml @@ -0,0 +1,42 @@ +run: + timeout: 5m + +linters-settings: + errcheck: + check-type-assertions: true + gci: + sections: + - "standard" + - "default" + - "prefix(github.com/goccy/go-yaml)" + - "blank" + - "dot" + gofmt: + simplify: true + govet: + disable: + - tests + misspell: + locale: US + staticcheck: + checks: ["all", "-ST1000", "-ST1005"] + +linters: + disable-all: true + enable: + - errcheck + - gci + - gofmt + - gosimple + - govet + - ineffassign + - misspell + - staticcheck + - typecheck + - unused + +issues: + exclude-rules: + - path: _test\.go + linters: + - staticcheck diff --git a/vendor/github.com/goccy/go-yaml/Makefile b/vendor/github.com/goccy/go-yaml/Makefile index 1b1d923..9166062 100644 --- a/vendor/github.com/goccy/go-yaml/Makefile +++ b/vendor/github.com/goccy/go-yaml/Makefile @@ -1,19 +1,59 @@ +## Location to install dependencies to +LOCALBIN ?= $(shell pwd)/bin +TESTMOD := testdata/go_test.mod + +$(LOCALBIN): + mkdir -p $(LOCALBIN) + +.PHONY: testmod + cp go.mod testdata/go_test.mod + go mod tidy -modfile=$(TESTMOD) + .PHONY: test -test: +test: testmod go test -v -race ./... + go test -v -race ./testdata -modfile=$(TESTMOD) .PHONY: simple-test -simple-test: +simple-test: testmod go test -v ./... + go test -v ./testdata -modfile=$(TESTMOD) + +.PHONY: fuzz +fuzz: + go test -fuzz=Fuzz -fuzztime 60s .PHONY: cover -cover: - go test -coverprofile=cover.out ./... +cover: testmod + go test -coverpkg=.,./ast,./lexer,./parser,./printer,./scanner,./token -coverprofile=cover.out -modfile=$(TESTMOD) ./... ./testdata .PHONY: cover-html cover-html: cover go tool cover -html=cover.out .PHONY: ycat/build -ycat/build: - go build -o ycat ./cmd/ycat +ycat/build: $(LOCALBIN) + cd ./cmd/ycat && go build -o $(LOCALBIN)/ycat . + +.PHONY: lint +lint: golangci-lint ## Run golangci-lint + @$(GOLANGCI_LINT) run + +.PHONY: fmt +fmt: golangci-lint ## Ensure consistent code style + @go mod tidy + @go fmt ./... + @$(GOLANGCI_LINT) run --fix + +## Tool Binaries +GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint + +## Tool Versions +GOLANGCI_VERSION := 1.61.0 + +.PHONY: golangci-lint +.PHONY: $(GOLANGCI_LINT) +golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. +$(GOLANGCI_LINT): $(LOCALBIN) + @test -s $(LOCALBIN)/golangci-lint && $(LOCALBIN)/golangci-lint version --format short | grep -q $(GOLANGCI_VERSION) || \ + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(LOCALBIN) v$(GOLANGCI_VERSION) diff --git a/vendor/github.com/goccy/go-yaml/README.md b/vendor/github.com/goccy/go-yaml/README.md index 9452349..afcc802 100644 --- a/vendor/github.com/goccy/go-yaml/README.md +++ b/vendor/github.com/goccy/go-yaml/README.md @@ -7,27 +7,54 @@ +## This library has **NO** relation to the go-yaml/yaml library + +> [!IMPORTANT] +> This library is developed from scratch to replace [`go-yaml/yaml`](https://github.com/go-yaml/yaml). +> If you're looking for a better YAML library, this one should be helpful. + # Why a new library? -As of this writing, there already exists a de facto standard library for YAML processing for Go: [https://github.com/go-yaml/yaml](https://github.com/go-yaml/yaml). However we feel that some features are lacking, namely: +As of this writing, there already exists a de facto standard library for YAML processing for Go: [https://github.com/go-yaml/yaml](https://github.com/go-yaml/yaml). However, we believe that a new YAML library is necessary for the following reasons: -- Pretty format for error notifications -- Direct manipulation of YAML abstract syntax tree -- Support for `Anchor` and `Alias` when marshaling -- Allow referencing elements declared in another file via anchors +- Not actively maintained +- `go-yaml/yaml` has ported the libyaml written in C to Go, so the source code is not written in Go style +- There is a lot of content that cannot be parsed +- YAML is often used for configuration, and it is common to include validation along with it. However, the errors in `go-yaml/yaml` are not intuitive, and it is difficult to provide meaningful validation errors +- When creating tools that use YAML, there are cases where reversible transformation of YAML is required. However, to perform reversible transformations of content that includes Comments or Anchors/Aliases, manipulating the AST is the only option +- Non-intuitive [Marshaler](https://pkg.go.dev/gopkg.in/yaml.v3#Marshaler) / [Unmarshaler](https://pkg.go.dev/gopkg.in/yaml.v3#Unmarshaler) + +By the way, libraries such as [ghodss/yaml](https://github.com/ghodss/yaml) and [sigs.k8s.io/yaml](https://github.com/kubernetes-sigs/yaml) also depend on go-yaml/yaml, so if you are using these libraries, the same issues apply: they cannot parse things that go-yaml/yaml cannot parse, and they inherit many of the problems that go-yaml/yaml has. # Features +- No dependencies +- A better parser than `go-yaml/yaml`. + - [Support recursive processing](https://github.com/apple/device-management/blob/release/docs/schema.yaml) + - Higher coverage in the [YAML Test Suite](https://github.com/yaml/yaml-test-suite?tab=readme-ov-file) +- Ease and sustainability of maintenance + - The main maintainer is [@goccy](https://github.com/goccy), but we are also building a system to develop as a team with trusted developers + - Since it is written from scratch, the code is easy to read for Gophers +- An API structure that allows the use of not only `Encoder`/`Decoder` but also `Tokenizer` and `Parser` functionalities. + - [lexer.Tokenize](https://pkg.go.dev/github.com/goccy/go-yaml@v1.15.4/lexer#Tokenize) + - [parser.Parse](https://pkg.go.dev/github.com/goccy/go-yaml@v1.15.4/parser#Parse) +- Filtering, replacing, and merging YAML content using YAML Path +- Reversible transformation without using the AST for YAML that includes Anchors, Aliases, and Comments +- Customize the Marshal/Unmarshal behavior for primitive types and third-party library types ([RegisterCustomMarshaler](https://pkg.go.dev/github.com/goccy/go-yaml#RegisterCustomMarshaler), [RegisterCustomUnmarshaler](https://pkg.go.dev/github.com/goccy/go-yaml#RegisterCustomUnmarshaler)) +- Respects `encoding/json` behavior + - Accept the `json` tag. Note that not all options from the `json` tag will have significance when parsing YAML documents. If both tags exist, `yaml` tag will take precedence. + - [json.Marshaler](https://pkg.go.dev/encoding/json#Marshaler) style [marshaler](https://pkg.go.dev/github.com/goccy/go-yaml#BytesMarshaler) + - [json.Unmarshaler](https://pkg.go.dev/encoding/json#Unmarshaler) style [unmarshaler](https://pkg.go.dev/github.com/goccy/go-yaml#BytesUnmarshaler) + - Options for using `MarshalJSON` and `UnmarshalJSON` ([UseJSONMarshaler](https://pkg.go.dev/github.com/goccy/go-yaml#UseJSONMarshaler), [UseJSONUnmarshaler](https://pkg.go.dev/github.com/goccy/go-yaml#UseJSONUnmarshaler)) - Pretty format for error notifications -- Supports `Scanner` or `Lexer` or `Parser` as public API -- Supports `Anchor` and `Alias` to Marshaler +- Smart validation processing combined with [go-playground/validator](https://github.com/go-playground/validator) + - [example test code is here](https://github.com/goccy/go-yaml/blob/45889c98b0a0967240eb595a1bd6896e2f575106/testdata/validate_test.go#L12) - Allow referencing elements declared in another file via anchors -- Extract value or AST by YAMLPath ( YAMLPath is like a JSONPath ) # Installation ```sh -go get -u github.com/goccy/go-yaml +go get github.com/goccy/go-yaml ``` # Synopsis @@ -358,9 +385,16 @@ print yaml file with color ### Installation ```sh -go install github.com/goccy/go-yaml/cmd/ycat@latest +git clone https://github.com/goccy/go-yaml.git +cd ./cmd/ycat && go insatll . ``` + +# For Developers + +> [!NOTE] +> In this project, we manage such test code under the `testdata` directory to avoid adding dependencies on libraries that are only needed for testing to the top `go.mod` file. Therefore, if you want to add test cases that use 3rd party libraries, please add the test code to the `testdata` directory. + # Looking for Sponsors I'm looking for sponsors this library. This library is being developed as a personal project in my spare time. If you want a quick response or problem resolution when using this library in your project, please register as a [sponsor](https://github.com/sponsors/goccy). I will cooperate as much as possible. Of course, this library is developed as an MIT license, so you can use it freely for free. diff --git a/vendor/github.com/goccy/go-yaml/ast/ast.go b/vendor/github.com/goccy/go-yaml/ast/ast.go index b4d5ec4..52edfdf 100644 --- a/vendor/github.com/goccy/go-yaml/ast/ast.go +++ b/vendor/github.com/goccy/go-yaml/ast/ast.go @@ -1,6 +1,7 @@ package ast import ( + "errors" "fmt" "io" "math" @@ -8,13 +9,12 @@ import ( "strings" "github.com/goccy/go-yaml/token" - "golang.org/x/xerrors" ) var ( - ErrInvalidTokenType = xerrors.New("invalid token type") - ErrInvalidAnchorName = xerrors.New("invalid anchor name") - ErrInvalidAliasName = xerrors.New("invalid alias name") + ErrInvalidTokenType = errors.New("invalid token type") + ErrInvalidAnchorName = errors.New("invalid anchor name") + ErrInvalidAliasName = errors.New("invalid alias name") ) // NodeType type identifier of node @@ -278,6 +278,49 @@ func readNode(p []byte, node Node) (int, error) { return size, nil } +func checkLineBreak(t *token.Token) bool { + if t.Prev != nil { + lbc := "\n" + prev := t.Prev + var adjustment int + // if the previous type is sequence entry use the previous type for that + if prev.Type == token.SequenceEntryType { + // as well as switching to previous type count any new lines in origin to account for: + // - + // b: c + adjustment = strings.Count(strings.TrimRight(t.Origin, lbc), lbc) + if prev.Prev != nil { + prev = prev.Prev + } + } + lineDiff := t.Position.Line - prev.Position.Line - 1 + if lineDiff > 0 { + if prev.Type == token.StringType { + // Remove any line breaks included in multiline string + adjustment += strings.Count(strings.TrimRight(strings.TrimSpace(prev.Origin), lbc), lbc) + } + // Due to the way that comment parsing works its assumed that when a null value does not have new line in origin + // it was squashed therefore difference is ignored. + //foo: + // bar: + // # comment + // baz: 1 + //becomes + //foo: + // bar: null # comment + // + // baz: 1 + if prev.Type == token.NullType { + return strings.Count(prev.Origin, lbc) > 0 + } + if lineDiff-adjustment > 0 { + return true + } + } + } + return false +} + // Null create node for null value func Null(tk *token.Token) *NullNode { return &NullNode{ @@ -298,105 +341,30 @@ func Bool(tk *token.Token) *BoolNode { // Integer create node for integer value func Integer(tk *token.Token) *IntegerNode { - value := removeUnderScoreFromNumber(tk.Value) - switch tk.Type { - case token.BinaryIntegerType: - // skip two characters because binary token starts with '0b' - skipCharacterNum := 2 - negativePrefix := "" - if value[0] == '-' { - skipCharacterNum++ - negativePrefix = "-" - } - if len(negativePrefix) > 0 { - i, _ := strconv.ParseInt(negativePrefix+value[skipCharacterNum:], 2, 64) - return &IntegerNode{ - BaseNode: &BaseNode{}, - Token: tk, - Value: i, - } - } - i, _ := strconv.ParseUint(negativePrefix+value[skipCharacterNum:], 2, 64) - return &IntegerNode{ - BaseNode: &BaseNode{}, - Token: tk, - Value: i, - } - case token.OctetIntegerType: - // octet token starts with '0o' or '-0o' or '0' or '-0' - skipCharacterNum := 1 - negativePrefix := "" - if value[0] == '-' { - skipCharacterNum++ - if len(value) > 2 && value[2] == 'o' { - skipCharacterNum++ - } - negativePrefix = "-" - } else { - if value[1] == 'o' { - skipCharacterNum++ - } - } - if len(negativePrefix) > 0 { - i, _ := strconv.ParseInt(negativePrefix+value[skipCharacterNum:], 8, 64) - return &IntegerNode{ - BaseNode: &BaseNode{}, - Token: tk, - Value: i, - } - } - i, _ := strconv.ParseUint(value[skipCharacterNum:], 8, 64) - return &IntegerNode{ - BaseNode: &BaseNode{}, - Token: tk, - Value: i, - } - case token.HexIntegerType: - // hex token starts with '0x' or '-0x' - skipCharacterNum := 2 - negativePrefix := "" - if value[0] == '-' { - skipCharacterNum++ - negativePrefix = "-" - } - if len(negativePrefix) > 0 { - i, _ := strconv.ParseInt(negativePrefix+value[skipCharacterNum:], 16, 64) - return &IntegerNode{ - BaseNode: &BaseNode{}, - Token: tk, - Value: i, - } - } - i, _ := strconv.ParseUint(value[skipCharacterNum:], 16, 64) - return &IntegerNode{ - BaseNode: &BaseNode{}, - Token: tk, - Value: i, - } + var v any + if num := token.ToNumber(tk.Value); num != nil { + v = num.Value } - if value[0] == '-' || value[0] == '+' { - i, _ := strconv.ParseInt(value, 10, 64) - return &IntegerNode{ - BaseNode: &BaseNode{}, - Token: tk, - Value: i, - } - } - i, _ := strconv.ParseUint(value, 10, 64) return &IntegerNode{ BaseNode: &BaseNode{}, Token: tk, - Value: i, + Value: v, } } // Float create node for float value func Float(tk *token.Token) *FloatNode { - f, _ := strconv.ParseFloat(removeUnderScoreFromNumber(tk.Value), 64) + var v float64 + if num := token.ToNumber(tk.Value); num != nil && num.Type == token.NumberTypeFloat { + value, ok := num.Value.(float64) + if ok { + v = value + } + } return &FloatNode{ BaseNode: &BaseNode{}, Token: tk, - Value: f, + Value: v, } } @@ -619,10 +587,6 @@ func (d *DocumentNode) MarshalYAML() ([]byte, error) { return []byte(d.String()), nil } -func removeUnderScoreFromNumber(num string) string { - return strings.ReplaceAll(num, "_", "") -} - // NullNode type of null node type NullNode struct { *BaseNode @@ -1323,6 +1287,7 @@ type MappingValueNode struct { Start *token.Token Key MapKeyNode Value Node + Anchor *AnchorNode FootComment *CommentGroupNode } @@ -1390,6 +1355,9 @@ func (n *MappingValueNode) String() string { func (n *MappingValueNode) toString() string { space := strings.Repeat(" ", n.Key.GetToken().Position.Column-1) + if checkLineBreak(n.Key.GetToken()) { + space = fmt.Sprintf("%s%s", "\n", space) + } keyIndentLevel := n.Key.GetToken().Position.IndentLevel valueIndentLevel := n.Value.GetToken().Position.IndentLevel keyComment := n.Key.GetComment() @@ -1491,7 +1459,7 @@ type SequenceNode struct { // Replace replace value node. func (n *SequenceNode) Replace(idx int, value Node) error { if len(n.Values) <= idx { - return xerrors.Errorf( + return fmt.Errorf( "invalid index for sequence: sequence length is %d, but specified %d index", len(n.Values), idx, ) @@ -1563,6 +1531,11 @@ func (n *SequenceNode) blockStyleString() string { for idx, value := range n.Values { valueStr := value.String() + newLinePrefix := "" + if strings.HasPrefix(valueStr, "\n") { + valueStr = valueStr[1:] + newLinePrefix = "\n" + } splittedValues := strings.Split(valueStr, "\n") trimmedFirstValue := strings.TrimLeft(splittedValues[0], " ") diffLength := len(splittedValues[0]) - len(trimmedFirstValue) @@ -1585,9 +1558,10 @@ func (n *SequenceNode) blockStyleString() string { } newValue := strings.Join(newValues, "\n") if len(n.ValueHeadComments) == len(n.Values) && n.ValueHeadComments[idx] != nil { - values = append(values, n.ValueHeadComments[idx].StringWithSpace(n.Start.Position.Column-1)) + values = append(values, fmt.Sprintf("%s%s", newLinePrefix, n.ValueHeadComments[idx].StringWithSpace(n.Start.Position.Column-1))) + newLinePrefix = "" } - values = append(values, fmt.Sprintf("%s- %s", space, newValue)) + values = append(values, fmt.Sprintf("%s%s- %s", newLinePrefix, space, newValue)) } if n.FootComment != nil { values = append(values, n.FootComment.StringWithSpace(n.Start.Position.Column-1)) @@ -1624,6 +1598,10 @@ type AnchorNode struct { Value Node } +func (n *AnchorNode) stringWithoutComment() string { + return n.Value.String() +} + func (n *AnchorNode) SetName(name string) error { if n.Name == nil { return ErrInvalidAnchorName @@ -1649,6 +1627,10 @@ func (n *AnchorNode) GetToken() *token.Token { return n.Start } +func (n *AnchorNode) GetValue() any { + return n.Value.GetToken().Value +} + // AddColumn add column number to child nodes recursively func (n *AnchorNode) AddColumn(col int) { n.Start.AddColumn(col) @@ -1685,6 +1667,10 @@ type AliasNode struct { Value Node } +func (n *AliasNode) stringWithoutComment() string { + return n.Value.String() +} + func (n *AliasNode) SetName(name string) error { if n.Value == nil { return ErrInvalidAliasName @@ -1710,6 +1696,10 @@ func (n *AliasNode) GetToken() *token.Token { return n.Start } +func (n *AliasNode) GetValue() any { + return n.Value.GetToken().Value +} + // AddColumn add column number to child nodes recursively func (n *AliasNode) AddColumn(col int) { n.Start.AddColumn(col) @@ -1772,6 +1762,18 @@ type TagNode struct { Value Node } +func (n *TagNode) GetValue() any { + scalar, ok := n.Value.(ScalarNode) + if !ok { + return nil + } + return scalar.GetValue() +} + +func (n *TagNode) stringWithoutComment() string { + return n.Value.String() +} + // Read implements (io.Reader).Read func (n *TagNode) Read(p []byte) (int, error) { return readNode(p, n) @@ -1880,10 +1882,13 @@ func (n *CommentGroupNode) StringWithSpace(col int) string { values := []string{} space := strings.Repeat(" ", col) for _, comment := range n.Comments { + space := space + if checkLineBreak(comment.Token) { + space = fmt.Sprintf("%s%s", "\n", space) + } values = append(values, space+comment.String()) } return strings.Join(values, "\n") - } // MarshalYAML encodes to a YAML text @@ -2092,10 +2097,10 @@ func Merge(dst Node, src Node) error { err := &ErrInvalidMergeType{dst: dst, src: src} switch dst.Type() { case DocumentType: - node := dst.(*DocumentNode) + node, _ := dst.(*DocumentNode) return Merge(node.Body, src) case MappingType: - node := dst.(*MappingNode) + node, _ := dst.(*MappingNode) target, ok := src.(*MappingNode) if !ok { return err @@ -2103,7 +2108,7 @@ func Merge(dst Node, src Node) error { node.Merge(target) return nil case SequenceType: - node := dst.(*SequenceNode) + node, _ := dst.(*SequenceNode) target, ok := src.(*SequenceNode) if !ok { return err diff --git a/vendor/github.com/goccy/go-yaml/decode.go b/vendor/github.com/goccy/go-yaml/decode.go index 72af5e2..faac222 100644 --- a/vendor/github.com/goccy/go-yaml/decode.go +++ b/vendor/github.com/goccy/go-yaml/decode.go @@ -13,10 +13,9 @@ import ( "reflect" "sort" "strconv" + "strings" "time" - "golang.org/x/xerrors" - "github.com/goccy/go-yaml/ast" "github.com/goccy/go-yaml/internal/errors" "github.com/goccy/go-yaml/parser" @@ -28,6 +27,7 @@ type Decoder struct { reader io.Reader referenceReaders []io.Reader anchorNodeMap map[string]ast.Node + aliasValueMap map[*ast.AliasNode]any anchorValueMap map[string]reflect.Value customUnmarshalerMap map[reflect.Type]func(interface{}, []byte) error toCommentMap CommentMap @@ -38,11 +38,12 @@ type Decoder struct { isResolvedReference bool validator StructValidator disallowUnknownField bool - disallowDuplicateKey bool + allowDuplicateMapKey bool useOrderedMap bool useJSONUnmarshaler bool parsedFile *ast.File streamIndex int + decodeDepth int } // NewDecoder returns a new decoder that reads from r. @@ -50,6 +51,7 @@ func NewDecoder(r io.Reader, opts ...DecodeOption) *Decoder { return &Decoder{ reader: r, anchorNodeMap: map[string]ast.Node{}, + aliasValueMap: make(map[*ast.AliasNode]any), anchorValueMap: map[string]reflect.Value{}, customUnmarshalerMap: map[reflect.Type]func(interface{}, []byte) error{}, opts: opts, @@ -59,11 +61,25 @@ func NewDecoder(r io.Reader, opts ...DecodeOption) *Decoder { isRecursiveDir: false, isResolvedReference: false, disallowUnknownField: false, - disallowDuplicateKey: false, + allowDuplicateMapKey: false, useOrderedMap: false, } } +const maxDecodeDepth = 10000 + +func (d *Decoder) stepIn() { + d.decodeDepth++ +} + +func (d *Decoder) stepOut() { + d.decodeDepth-- +} + +func (d *Decoder) isExceededMaxDepth() bool { + return d.decodeDepth > maxDecodeDepth +} + func (d *Decoder) castToFloat(v interface{}) interface{} { switch vv := v.(type) { case int: @@ -100,58 +116,98 @@ func (d *Decoder) castToFloat(v interface{}) interface{} { func (d *Decoder) mergeValueNode(value ast.Node) ast.Node { if value.Type() == ast.AliasType { - aliasNode := value.(*ast.AliasNode) + aliasNode, _ := value.(*ast.AliasNode) aliasName := aliasNode.Value.GetToken().Value return d.anchorNodeMap[aliasName] } return value } -func (d *Decoder) mapKeyNodeToString(node ast.MapKeyNode) string { - key := d.nodeToValue(node) +func (d *Decoder) mapKeyNodeToString(node ast.MapKeyNode) (string, error) { + key, err := d.nodeToValue(node) + if err != nil { + return "", err + } if key == nil { - return "null" + return "null", nil } if k, ok := key.(string); ok { - return k + return k, nil } - return fmt.Sprint(key) + return fmt.Sprint(key), nil } -func (d *Decoder) setToMapValue(node ast.Node, m map[string]interface{}) { +func (d *Decoder) setToMapValue(node ast.Node, m map[string]interface{}) error { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return ErrExceededMaxDepth + } + d.setPathToCommentMap(node) switch n := node.(type) { case *ast.MappingValueNode: if n.Key.Type() == ast.MergeKeyType { - d.setToMapValue(d.mergeValueNode(n.Value), m) + if err := d.setToMapValue(d.mergeValueNode(n.Value), m); err != nil { + return err + } } else { - key := d.mapKeyNodeToString(n.Key) - m[key] = d.nodeToValue(n.Value) + key, err := d.mapKeyNodeToString(n.Key) + if err != nil { + return err + } + v, err := d.nodeToValue(n.Value) + if err != nil { + return err + } + m[key] = v } case *ast.MappingNode: for _, value := range n.Values { - d.setToMapValue(value, m) + if err := d.setToMapValue(value, m); err != nil { + return err + } } case *ast.AnchorNode: anchorName := n.Name.GetToken().Value d.anchorNodeMap[anchorName] = n.Value } + return nil } -func (d *Decoder) setToOrderedMapValue(node ast.Node, m *MapSlice) { +func (d *Decoder) setToOrderedMapValue(node ast.Node, m *MapSlice) error { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return ErrExceededMaxDepth + } + + d.setPathToCommentMap(node) switch n := node.(type) { case *ast.MappingValueNode: if n.Key.Type() == ast.MergeKeyType { - d.setToOrderedMapValue(d.mergeValueNode(n.Value), m) + if err := d.setToOrderedMapValue(d.mergeValueNode(n.Value), m); err != nil { + return err + } } else { - key := d.mapKeyNodeToString(n.Key) - *m = append(*m, MapItem{Key: key, Value: d.nodeToValue(n.Value)}) + key, err := d.mapKeyNodeToString(n.Key) + if err != nil { + return err + } + value, err := d.nodeToValue(n.Value) + if err != nil { + return err + } + *m = append(*m, MapItem{Key: key, Value: value}) } case *ast.MappingNode: for _, value := range n.Values { - d.setToOrderedMapValue(value, m) + if err := d.setToOrderedMapValue(value, m); err != nil { + return err + } } } + return nil } func (d *Decoder) setPathToCommentMap(node ast.Node) { @@ -186,6 +242,14 @@ func (d *Decoder) addHeadOrLineCommentToMap(node ast.Node) { } commentPath := node.GetPath() if minCommentLine < targetLine { + switch n := node.(type) { + case *ast.MappingNode: + if len(n.Values) != 0 { + commentPath = n.Values[0].Key.GetPath() + } + case *ast.MappingValueNode: + commentPath = n.Key.GetPath() + } d.addCommentToMap(commentPath, HeadComment(texts...)) } else { d.addCommentToMap(commentPath, LineComment(texts[0])) @@ -226,14 +290,20 @@ func (d *Decoder) addFootCommentToMap(node ast.Node) { ) switch n := node.(type) { case *ast.SequenceNode: - if len(n.Values) != 0 { - footCommentPath = n.Values[len(n.Values)-1].GetPath() - } footComment = n.FootComment + if n.FootComment != nil { + footCommentPath = n.FootComment.GetPath() + } case *ast.MappingNode: footComment = n.FootComment + if n.FootComment != nil { + footCommentPath = n.FootComment.GetPath() + } case *ast.MappingValueNode: footComment = n.FootComment + if n.FootComment != nil { + footCommentPath = n.FootComment.GetPath() + } } if footComment == nil { return @@ -260,54 +330,127 @@ func (d *Decoder) addCommentToMap(path string, comment *Comment) { }) } -func (d *Decoder) nodeToValue(node ast.Node) interface{} { +func (d *Decoder) nodeToValue(node ast.Node) (any, error) { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return nil, ErrExceededMaxDepth + } + d.setPathToCommentMap(node) switch n := node.(type) { case *ast.NullNode: - return nil + return nil, nil case *ast.StringNode: - return n.GetValue() + return n.GetValue(), nil case *ast.IntegerNode: - return n.GetValue() + return n.GetValue(), nil case *ast.FloatNode: - return n.GetValue() + return n.GetValue(), nil case *ast.BoolNode: - return n.GetValue() + return n.GetValue(), nil case *ast.InfinityNode: - return n.GetValue() + return n.GetValue(), nil case *ast.NanNode: - return n.GetValue() + return n.GetValue(), nil case *ast.TagNode: switch token.ReservedTagKeyword(n.Start.Value) { case token.TimestampTag: t, _ := d.castToTime(n.Value) - return t + return t, nil case token.IntegerTag: - i, _ := strconv.Atoi(fmt.Sprint(d.nodeToValue(n.Value))) - return i + v, err := d.nodeToValue(n.Value) + if err != nil { + return nil, err + } + i, _ := strconv.Atoi(fmt.Sprint(v)) + return i, nil case token.FloatTag: - return d.castToFloat(d.nodeToValue(n.Value)) + v, err := d.nodeToValue(n.Value) + if err != nil { + return nil, err + } + return d.castToFloat(v), nil case token.NullTag: - return nil + return nil, nil case token.BinaryTag: - b, _ := base64.StdEncoding.DecodeString(d.nodeToValue(n.Value).(string)) - return b + v, err := d.nodeToValue(n.Value) + if err != nil { + return nil, err + } + str, ok := v.(string) + if !ok { + return nil, errors.ErrSyntax( + fmt.Sprintf("cannot convert %q to string", fmt.Sprint(v)), + n.Value.GetToken(), + ) + } + b, _ := base64.StdEncoding.DecodeString(str) + return b, nil + case token.BooleanTag: + v, err := d.nodeToValue(n.Value) + if err != nil { + return nil, err + } + str := strings.ToLower(fmt.Sprint(v)) + b, err := strconv.ParseBool(str) + if err == nil { + return b, nil + } + switch str { + case "yes": + return true, nil + case "no": + return false, nil + } + return nil, errors.ErrSyntax(fmt.Sprintf("cannot convert %q to boolean", fmt.Sprint(v)), n.Value.GetToken()) case token.StringTag: - return d.nodeToValue(n.Value) + v, err := d.nodeToValue(n.Value) + if err != nil { + return nil, err + } + if v == nil { + return "", nil + } + return fmt.Sprint(v), nil case token.MappingTag: return d.nodeToValue(n.Value) + default: + return d.nodeToValue(n.Value) } case *ast.AnchorNode: anchorName := n.Name.GetToken().Value - anchorValue := d.nodeToValue(n.Value) + + // To handle the case where alias is processed recursively, the result of alias can be set to nil in advance. + d.anchorNodeMap[anchorName] = nil + anchorValue, err := d.nodeToValue(n.Value) + if err != nil { + delete(d.anchorNodeMap, anchorName) + return nil, err + } d.anchorNodeMap[anchorName] = n.Value - return anchorValue + return anchorValue, nil case *ast.AliasNode: + if v, exists := d.aliasValueMap[n]; exists { + return v, nil + } + // To handle the case where alias is processed recursively, the result of alias can be set to nil in advance. + d.aliasValueMap[n] = nil + aliasName := n.Value.GetToken().Value - node := d.anchorNodeMap[aliasName] - return d.nodeToValue(node) + node, exists := d.anchorNodeMap[aliasName] + if !exists { + return nil, errors.ErrSyntax(fmt.Sprintf("could not find alias %q", aliasName), n.Value.GetToken()) + } + aliasValue, err := d.nodeToValue(node) + if err != nil { + return nil, err + } + // once the correct alias value is obtained, overwrite with that value. + d.aliasValueMap[n] = aliasValue + return aliasValue, nil case *ast.LiteralNode: - return n.Value.GetValue() + return n.Value.GetValue(), nil case *ast.MappingKeyNode: return d.nodeToValue(n.Value) case *ast.MappingValueNode: @@ -315,44 +458,71 @@ func (d *Decoder) nodeToValue(node ast.Node) interface{} { value := d.mergeValueNode(n.Value) if d.useOrderedMap { m := MapSlice{} - d.setToOrderedMapValue(value, &m) - return m + if err := d.setToOrderedMapValue(value, &m); err != nil { + return nil, err + } + return m, nil } m := map[string]interface{}{} - d.setToMapValue(value, m) - return m + if err := d.setToMapValue(value, m); err != nil { + return nil, err + } + return m, nil + } + key, err := d.mapKeyNodeToString(n.Key) + if err != nil { + return nil, err } - key := d.mapKeyNodeToString(n.Key) if d.useOrderedMap { - return MapSlice{{Key: key, Value: d.nodeToValue(n.Value)}} + v, err := d.nodeToValue(n.Value) + if err != nil { + return nil, err + } + return MapSlice{{Key: key, Value: v}}, nil } - return map[string]interface{}{ - key: d.nodeToValue(n.Value), + v, err := d.nodeToValue(n.Value) + if err != nil { + return nil, err } + return map[string]interface{}{key: v}, nil case *ast.MappingNode: if d.useOrderedMap { m := make(MapSlice, 0, len(n.Values)) for _, value := range n.Values { - d.setToOrderedMapValue(value, &m) + if err := d.setToOrderedMapValue(value, &m); err != nil { + return nil, err + } } - return m + return m, nil } m := make(map[string]interface{}, len(n.Values)) for _, value := range n.Values { - d.setToMapValue(value, m) + if err := d.setToMapValue(value, m); err != nil { + return nil, err + } } - return m + return m, nil case *ast.SequenceNode: v := make([]interface{}, 0, len(n.Values)) for _, value := range n.Values { - v = append(v, d.nodeToValue(value)) + vv, err := d.nodeToValue(value) + if err != nil { + return nil, err + } + v = append(v, vv) } - return v + return v, nil } - return nil + return nil, nil } func (d *Decoder) resolveAlias(node ast.Node) (ast.Node, error) { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return nil, ErrExceededMaxDepth + } + switch n := node.(type) { case *ast.MappingNode: for idx, v := range n.Values { @@ -360,7 +530,7 @@ func (d *Decoder) resolveAlias(node ast.Node) (ast.Node, error) { if err != nil { return nil, err } - n.Values[idx] = value.(*ast.MappingValueNode) + n.Values[idx], _ = value.(*ast.MappingValueNode) } case *ast.TagNode: value, err := d.resolveAlias(n.Value) @@ -389,7 +559,7 @@ func (d *Decoder) resolveAlias(node ast.Node) (ast.Node, error) { if err != nil { return nil, err } - n.Key = key.(ast.MapKeyNode) + n.Key, _ = key.(ast.MapKeyNode) value, err := d.resolveAlias(n.Value) if err != nil { return nil, err @@ -408,7 +578,7 @@ func (d *Decoder) resolveAlias(node ast.Node) (ast.Node, error) { aliasName := n.Value.GetToken().Value node := d.anchorNodeMap[aliasName] if node == nil { - return nil, xerrors.Errorf("cannot find anchor by alias name %s", aliasName) + return nil, fmt.Errorf("cannot find anchor by alias name %s", aliasName) } return d.resolveAlias(node) } @@ -416,6 +586,12 @@ func (d *Decoder) resolveAlias(node ast.Node) (ast.Node, error) { } func (d *Decoder) getMapNode(node ast.Node) (ast.MapNode, error) { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return nil, ErrExceededMaxDepth + } + if _, ok := node.(*ast.NullNode); ok { return nil, nil } @@ -424,28 +600,34 @@ func (d *Decoder) getMapNode(node ast.Node) (ast.MapNode, error) { if ok { return mapNode, nil } - return nil, errUnexpectedNodeType(anchor.Value.Type(), ast.MappingType, node.GetToken()) + return nil, errors.ErrUnexpectedNodeType(anchor.Value.Type(), ast.MappingType, node.GetToken()) } if alias, ok := node.(*ast.AliasNode); ok { aliasName := alias.Value.GetToken().Value node := d.anchorNodeMap[aliasName] if node == nil { - return nil, xerrors.Errorf("cannot find anchor by alias name %s", aliasName) + return nil, fmt.Errorf("cannot find anchor by alias name %s", aliasName) } mapNode, ok := node.(ast.MapNode) if ok { return mapNode, nil } - return nil, errUnexpectedNodeType(node.Type(), ast.MappingType, node.GetToken()) + return nil, errors.ErrUnexpectedNodeType(node.Type(), ast.MappingType, node.GetToken()) } mapNode, ok := node.(ast.MapNode) if !ok { - return nil, errUnexpectedNodeType(node.Type(), ast.MappingType, node.GetToken()) + return nil, errors.ErrUnexpectedNodeType(node.Type(), ast.MappingType, node.GetToken()) } return mapNode, nil } func (d *Decoder) getArrayNode(node ast.Node) (ast.ArrayNode, error) { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return nil, ErrExceededMaxDepth + } + if _, ok := node.(*ast.NullNode); ok { return nil, nil } @@ -455,36 +637,27 @@ func (d *Decoder) getArrayNode(node ast.Node) (ast.ArrayNode, error) { return arrayNode, nil } - return nil, errUnexpectedNodeType(anchor.Value.Type(), ast.SequenceType, node.GetToken()) + return nil, errors.ErrUnexpectedNodeType(anchor.Value.Type(), ast.SequenceType, node.GetToken()) } if alias, ok := node.(*ast.AliasNode); ok { aliasName := alias.Value.GetToken().Value node := d.anchorNodeMap[aliasName] if node == nil { - return nil, xerrors.Errorf("cannot find anchor by alias name %s", aliasName) + return nil, fmt.Errorf("cannot find anchor by alias name %s", aliasName) } arrayNode, ok := node.(ast.ArrayNode) if ok { return arrayNode, nil } - return nil, errUnexpectedNodeType(node.Type(), ast.SequenceType, node.GetToken()) + return nil, errors.ErrUnexpectedNodeType(node.Type(), ast.SequenceType, node.GetToken()) } arrayNode, ok := node.(ast.ArrayNode) if !ok { - return nil, errUnexpectedNodeType(node.Type(), ast.SequenceType, node.GetToken()) + return nil, errors.ErrUnexpectedNodeType(node.Type(), ast.SequenceType, node.GetToken()) } return arrayNode, nil } -func (d *Decoder) fileToNode(f *ast.File) ast.Node { - for _, doc := range f.Docs { - if v := d.nodeToValue(doc.Body); v != nil { - return doc.Body - } - } - return nil -} - func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node) (reflect.Value, error) { if typ.Kind() != reflect.String { if !v.Type().ConvertibleTo(typ) { @@ -503,7 +676,7 @@ func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node) // else, fall through to the error below } } - return reflect.Zero(typ), errTypeMismatch(typ, v.Type(), src.GetToken()) + return reflect.Zero(typ), errors.ErrTypeMismatch(typ, v.Type(), src.GetToken()) } return v.Convert(typ), nil } @@ -519,63 +692,18 @@ func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node) return reflect.ValueOf(fmt.Sprint(v.Bool())), nil } if !v.Type().ConvertibleTo(typ) { - return reflect.Zero(typ), errTypeMismatch(typ, v.Type(), src.GetToken()) + return reflect.Zero(typ), errors.ErrTypeMismatch(typ, v.Type(), src.GetToken()) } return v.Convert(typ), nil } -type overflowError struct { - dstType reflect.Type - srcNum string -} - -func (e *overflowError) Error() string { - return fmt.Sprintf("cannot unmarshal %s into Go value of type %s ( overflow )", e.srcNum, e.dstType) -} - -func errOverflow(dstType reflect.Type, num string) *overflowError { - return &overflowError{dstType: dstType, srcNum: num} -} - -func errTypeMismatch(dstType, srcType reflect.Type, token *token.Token) *errors.TypeError { - return &errors.TypeError{DstType: dstType, SrcType: srcType, Token: token} -} - -type unknownFieldError struct { - err error -} - -func (e *unknownFieldError) Error() string { - return e.err.Error() -} - -func errUnknownField(msg string, tk *token.Token) *unknownFieldError { - return &unknownFieldError{err: errors.ErrSyntax(msg, tk)} -} - -func errUnexpectedNodeType(actual, expected ast.NodeType, tk *token.Token) error { - return errors.ErrSyntax(fmt.Sprintf("%s was used where %s is expected", actual.YAMLName(), expected.YAMLName()), tk) -} - -type duplicateKeyError struct { - err error -} - -func (e *duplicateKeyError) Error() string { - return e.err.Error() -} - -func errDuplicateKey(msg string, tk *token.Token) *duplicateKeyError { - return &duplicateKeyError{err: errors.ErrSyntax(msg, tk)} -} - func (d *Decoder) deleteStructKeys(structType reflect.Type, unknownFields map[string]ast.Node) error { if structType.Kind() == reflect.Ptr { structType = structType.Elem() } structFieldMap, err := structFieldMap(structType) if err != nil { - return errors.Wrapf(err, "failed to create struct field map") + return err } for j := 0; j < structType.NumField(); j++ { @@ -590,7 +718,7 @@ func (d *Decoder) deleteStructKeys(structType reflect.Type, unknownFields map[st } if structField.IsInline { - d.deleteStructKeys(field.Type, unknownFields) + _ = d.deleteStructKeys(field.Type, unknownFields) } else { delete(unknownFields, structField.RenderName) } @@ -713,10 +841,10 @@ func (d *Decoder) decodeByUnmarshaler(ctx context.Context, dst reflect.Value, sr if unmarshaler, exists := d.unmarshalerFromCustomUnmarshalerMap(ptrValue.Type()); exists { b, err := d.unmarshalableDocument(src) if err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") + return err } if err := unmarshaler(ptrValue.Interface(), b); err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") + return err } return nil } @@ -725,10 +853,10 @@ func (d *Decoder) decodeByUnmarshaler(ctx context.Context, dst reflect.Value, sr if unmarshaler, ok := iface.(BytesUnmarshalerContext); ok { b, err := d.unmarshalableDocument(src) if err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") + return err } if err := unmarshaler.UnmarshalYAML(ctx, b); err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") + return err } return nil } @@ -736,10 +864,10 @@ func (d *Decoder) decodeByUnmarshaler(ctx context.Context, dst reflect.Value, sr if unmarshaler, ok := iface.(BytesUnmarshaler); ok { b, err := d.unmarshalableDocument(src) if err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") + return err } if err := unmarshaler.UnmarshalYAML(b); err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") + return err } return nil } @@ -748,14 +876,14 @@ func (d *Decoder) decodeByUnmarshaler(ctx context.Context, dst reflect.Value, sr if err := unmarshaler.UnmarshalYAML(ctx, func(v interface{}) error { rv := reflect.ValueOf(v) if rv.Type().Kind() != reflect.Ptr { - return errors.ErrDecodeRequiredPointerType + return ErrDecodeRequiredPointerType } if err := d.decodeValue(ctx, rv.Elem(), src); err != nil { - return errors.Wrapf(err, "failed to decode value") + return err } return nil }); err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") + return err } return nil } @@ -764,14 +892,14 @@ func (d *Decoder) decodeByUnmarshaler(ctx context.Context, dst reflect.Value, sr if err := unmarshaler.UnmarshalYAML(func(v interface{}) error { rv := reflect.ValueOf(v) if rv.Type().Kind() != reflect.Ptr { - return errors.ErrDecodeRequiredPointerType + return ErrDecodeRequiredPointerType } if err := d.decodeValue(ctx, rv.Elem(), src); err != nil { - return errors.Wrapf(err, "failed to decode value") + return err } return nil }); err != nil { - return errors.Wrapf(err, "failed to UnmarshalYAML") + return err } return nil } @@ -787,11 +915,11 @@ func (d *Decoder) decodeByUnmarshaler(ctx context.Context, dst reflect.Value, sr if unmarshaler, isText := iface.(encoding.TextUnmarshaler); isText { b, ok, err := d.unmarshalableText(src) if err != nil { - return errors.Wrapf(err, "failed to UnmarshalText") + return err } if ok { if err := unmarshaler.UnmarshalText(b); err != nil { - return errors.Wrapf(err, "failed to UnmarshalText") + return err } return nil } @@ -801,21 +929,21 @@ func (d *Decoder) decodeByUnmarshaler(ctx context.Context, dst reflect.Value, sr if unmarshaler, ok := iface.(jsonUnmarshaler); ok { b, err := d.unmarshalableDocument(src) if err != nil { - return errors.Wrapf(err, "failed to UnmarshalJSON") + return err } jsonBytes, err := YAMLToJSON(b) if err != nil { - return errors.Wrapf(err, "failed to convert yaml to json") + return err } jsonBytes = bytes.TrimRight(jsonBytes, "\n") if err := unmarshaler.UnmarshalJSON(jsonBytes); err != nil { - return errors.Wrapf(err, "failed to UnmarshalJSON") + return err } return nil } } - return xerrors.Errorf("does not implemented Unmarshaler") + return fmt.Errorf("does not implemented Unmarshaler") } var ( @@ -823,6 +951,12 @@ var ( ) func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.Node) error { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return ErrExceededMaxDepth + } + if src.Type() == ast.AnchorType { anchorName := src.(*ast.AnchorNode).Name.GetToken().Value if _, exists := d.anchorValueMap[anchorName]; !exists { @@ -831,7 +965,7 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No } if d.canDecodeByUnmarshaler(dst) { if err := d.decodeByUnmarshaler(ctx, dst, src); err != nil { - return errors.Wrapf(err, "failed to decode by unmarshaler") + return err } return nil } @@ -848,7 +982,7 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No } v := d.createDecodableValue(dst.Type()) if err := d.decodeValue(ctx, v, src); err != nil { - return errors.Wrapf(err, "failed to decode ptr value") + return err } dst.Set(d.castToAssignableValue(v, dst.Type())) case reflect.Interface: @@ -856,7 +990,11 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No dst.Set(reflect.ValueOf(src)) return nil } - v := reflect.ValueOf(d.nodeToValue(src)) + srcVal, err := d.nodeToValue(src) + if err != nil { + return err + } + v := reflect.ValueOf(srcVal) if v.IsValid() { dst.Set(v) } @@ -875,7 +1013,10 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No } return d.decodeStruct(ctx, dst, src) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - v := d.nodeToValue(src) + v, err := d.nodeToValue(src) + if err != nil { + return err + } switch vv := v.(type) { case int64: if !dst.OverflowInt(vv) { @@ -899,14 +1040,17 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No return nil } } else { // couldn't be parsed as float - return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) + return errors.ErrTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) } default: - return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) + return errors.ErrTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) } - return errOverflow(valueType, fmt.Sprint(v)) + return errors.ErrOverflow(valueType, fmt.Sprint(v), src.GetToken()) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - v := d.nodeToValue(src) + v, err := d.nodeToValue(src) + if err != nil { + return err + } switch vv := v.(type) { case int64: if 0 <= vv && !dst.OverflowUint(uint64(vv)) { @@ -930,19 +1074,23 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No return nil } } else { // couldn't be parsed as float - return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) + return errors.ErrTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) } default: - return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) + return errors.ErrTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken()) } - return errOverflow(valueType, fmt.Sprint(v)) + return errors.ErrOverflow(valueType, fmt.Sprint(v), src.GetToken()) } - v := reflect.ValueOf(d.nodeToValue(src)) + srcVal, err := d.nodeToValue(src) + if err != nil { + return err + } + v := reflect.ValueOf(srcVal) if v.IsValid() { convertedValue, err := d.convertValue(v, dst.Type(), src) if err != nil { - return errors.Wrapf(err, "failed to convert value") + return err } dst.Set(convertedValue) } @@ -989,26 +1137,36 @@ func (d *Decoder) createDecodedNewValue( return newValue, nil } } + var newValue reflect.Value if node.Type() == ast.NullType { - return reflect.Zero(typ), nil + newValue = reflect.New(typ).Elem() + } else { + newValue = d.createDecodableValue(typ) } - newValue := d.createDecodableValue(typ) for defaultVal.Kind() == reflect.Ptr { defaultVal = defaultVal.Elem() } if defaultVal.IsValid() && defaultVal.Type().AssignableTo(newValue.Type()) { newValue.Set(defaultVal) } - if err := d.decodeValue(ctx, newValue, node); err != nil { - return newValue, errors.Wrapf(err, "failed to decode value") + if node.Type() != ast.NullType { + if err := d.decodeValue(ctx, newValue, node); err != nil { + return newValue, err + } } return newValue, nil } func (d *Decoder) keyToNodeMap(node ast.Node, ignoreMergeKey bool, getKeyOrValueNode func(*ast.MapNodeIter) ast.Node) (map[string]ast.Node, error) { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return nil, ErrExceededMaxDepth + } + mapNode, err := d.getMapNode(node) if err != nil { - return nil, errors.Wrapf(err, "failed to get map node") + return nil, err } keyMap := map[string]struct{}{} keyToNodeMap := map[string]ast.Node{} @@ -1024,21 +1182,25 @@ func (d *Decoder) keyToNodeMap(node ast.Node, ignoreMergeKey bool, getKeyOrValue } mergeMap, err := d.keyToNodeMap(mapIter.Value(), ignoreMergeKey, getKeyOrValueNode) if err != nil { - return nil, errors.Wrapf(err, "failed to get keyToNodeMap by MergeKey node") + return nil, err } for k, v := range mergeMap { if err := d.validateDuplicateKey(keyMap, k, v); err != nil { - return nil, errors.Wrapf(err, "invalid struct key") + return nil, err } keyToNodeMap[k] = v } } else { - key, ok := d.nodeToValue(keyNode).(string) + keyVal, err := d.nodeToValue(keyNode) + if err != nil { + return nil, err + } + key, ok := keyVal.(string) if !ok { - return nil, errors.Wrapf(err, "failed to decode map key") + return nil, err } if err := d.validateDuplicateKey(keyMap, key, keyNode); err != nil { - return nil, errors.Wrapf(err, "invalid struct key") + return nil, err } keyToNodeMap[key] = getKeyOrValueNode(mapIter) } @@ -1049,7 +1211,7 @@ func (d *Decoder) keyToNodeMap(node ast.Node, ignoreMergeKey bool, getKeyOrValue func (d *Decoder) keyToKeyNodeMap(node ast.Node, ignoreMergeKey bool) (map[string]ast.Node, error) { m, err := d.keyToNodeMap(node, ignoreMergeKey, func(nodeMap *ast.MapNodeIter) ast.Node { return nodeMap.Key() }) if err != nil { - return nil, errors.Wrapf(err, "failed to get keyToNodeMap") + return nil, err } return m, nil } @@ -1057,7 +1219,7 @@ func (d *Decoder) keyToKeyNodeMap(node ast.Node, ignoreMergeKey bool) (map[strin func (d *Decoder) keyToValueNodeMap(node ast.Node, ignoreMergeKey bool) (map[string]ast.Node, error) { m, err := d.keyToNodeMap(node, ignoreMergeKey, func(nodeMap *ast.MapNodeIter) ast.Node { return nodeMap.Value() }) if err != nil { - return nil, errors.Wrapf(err, "failed to get keyToNodeMap") + return nil, err } return m, nil } @@ -1069,7 +1231,7 @@ func (d *Decoder) setDefaultValueIfConflicted(v reflect.Value, fieldMap StructFi } embeddedStructFieldMap, err := structFieldMap(typ) if err != nil { - return errors.Wrapf(err, "failed to get struct field map by embedded type") + return err } for i := 0; i < typ.NumField(); i++ { field := typ.Field(i) @@ -1102,13 +1264,16 @@ func (d *Decoder) castToTime(src ast.Node) (time.Time, error) { if src == nil { return time.Time{}, nil } - v := d.nodeToValue(src) + v, err := d.nodeToValue(src) + if err != nil { + return time.Time{}, err + } if t, ok := v.(time.Time); ok { return t, nil } s, ok := v.(string) if !ok { - return time.Time{}, errTypeMismatch(reflect.TypeOf(time.Time{}), reflect.TypeOf(v), src.GetToken()) + return time.Time{}, errors.ErrTypeMismatch(reflect.TypeOf(time.Time{}), reflect.TypeOf(v), src.GetToken()) } for _, format := range allowedTimestampFormats { t, err := time.Parse(format, s) @@ -1124,7 +1289,7 @@ func (d *Decoder) castToTime(src ast.Node) (time.Time, error) { func (d *Decoder) decodeTime(ctx context.Context, dst reflect.Value, src ast.Node) error { t, err := d.castToTime(src) if err != nil { - return errors.Wrapf(err, "failed to convert to time") + return err } dst.Set(reflect.ValueOf(t)) return nil @@ -1134,17 +1299,20 @@ func (d *Decoder) castToDuration(src ast.Node) (time.Duration, error) { if src == nil { return 0, nil } - v := d.nodeToValue(src) + v, err := d.nodeToValue(src) + if err != nil { + return 0, err + } if t, ok := v.(time.Duration); ok { return t, nil } s, ok := v.(string) if !ok { - return 0, errTypeMismatch(reflect.TypeOf(time.Duration(0)), reflect.TypeOf(v), src.GetToken()) + return 0, errors.ErrTypeMismatch(reflect.TypeOf(time.Duration(0)), reflect.TypeOf(v), src.GetToken()) } t, err := time.ParseDuration(s) if err != nil { - return 0, errors.Wrapf(err, "failed to parse duration") + return 0, err } return t, nil } @@ -1152,7 +1320,7 @@ func (d *Decoder) castToDuration(src ast.Node) (time.Duration, error) { func (d *Decoder) decodeDuration(ctx context.Context, dst reflect.Value, src ast.Node) error { t, err := d.castToDuration(src) if err != nil { - return errors.Wrapf(err, "failed to convert to duration") + return err } dst.Set(reflect.ValueOf(t)) return nil @@ -1182,6 +1350,12 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N if src == nil { return nil } + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return ErrExceededMaxDepth + } + structType := dst.Type() srcValue := reflect.ValueOf(src) srcType := srcValue.Type() @@ -1196,18 +1370,18 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N } structFieldMap, err := structFieldMap(structType) if err != nil { - return errors.Wrapf(err, "failed to create struct field map") + return err } ignoreMergeKey := structFieldMap.hasMergeProperty() keyToNodeMap, err := d.keyToValueNodeMap(src, ignoreMergeKey) if err != nil { - return errors.Wrapf(err, "failed to get keyToValueNodeMap") + return err } var unknownFields map[string]ast.Node if d.disallowUnknownField { unknownFields, err = d.keyToKeyNodeMap(src, ignoreMergeKey) if err != nil { - return errors.Wrapf(err, "failed to get keyToKeyNodeMap") + return err } } @@ -1232,7 +1406,7 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N continue } if !fieldValue.CanSet() { - return xerrors.Errorf("cannot set embedded type as unexported field %s.%s", field.PkgPath, field.Name) + return fmt.Errorf("cannot set embedded type as unexported field %s.%s", field.PkgPath, field.Name) } if fieldValue.Type().Kind() == reflect.Ptr && src.Type() == ast.NullType { // set nil value to pointer @@ -1247,7 +1421,7 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N newFieldValue, err := d.createDecodedNewValue(ctx, fieldValue.Type(), fieldValue, mapNode) if d.disallowUnknownField { if err := d.deleteStructKeys(fieldValue.Type(), unknownFields); err != nil { - return errors.Wrapf(err, "cannot delete struct keys") + return err } } @@ -1256,7 +1430,7 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N continue } var te *errors.TypeError - if xerrors.As(err, &te) { + if errors.As(err, &te) { if te.StructFieldName != nil { fieldName := fmt.Sprintf("%s.%s", structType.Name(), *te.StructFieldName) te.StructFieldName = &fieldName @@ -1271,7 +1445,7 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N } continue } - d.setDefaultValueIfConflicted(newFieldValue, structFieldMap) + _ = d.setDefaultValueIfConflicted(newFieldValue, structFieldMap) fieldValue.Set(d.castToAssignableValue(newFieldValue, fieldValue.Type())) continue } @@ -1292,7 +1466,7 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N continue } var te *errors.TypeError - if xerrors.As(err, &te) { + if errors.As(err, &te) { fieldName := fmt.Sprintf("%s.%s", structType.Name(), field.Name) te.StructFieldName = &fieldName foundErr = te @@ -1304,14 +1478,14 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N fieldValue.Set(d.castToAssignableValue(newFieldValue, fieldValue.Type())) } if foundErr != nil { - return errors.Wrapf(foundErr, "failed to decode value") + return foundErr } // Ignore unknown fields when parsing an inline struct (recognized by a nil token). // Unknown fields are expected (they could be fields from the parent struct). if len(unknownFields) != 0 && d.disallowUnknownField && src.GetToken() != nil { for key, node := range unknownFields { - return errUnknownField(fmt.Sprintf(`unknown field "%s"`, key), node.GetToken()) + return errors.ErrUnknownField(fmt.Sprintf(`unknown field "%s"`, key), node.GetToken()) } } @@ -1347,9 +1521,15 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N } func (d *Decoder) decodeArray(ctx context.Context, dst reflect.Value, src ast.Node) error { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return ErrExceededMaxDepth + } + arrayNode, err := d.getArrayNode(src) if err != nil { - return errors.Wrapf(err, "failed to get array node") + return err } if arrayNode == nil { return nil @@ -1381,15 +1561,21 @@ func (d *Decoder) decodeArray(ctx context.Context, dst reflect.Value, src ast.No } dst.Set(arrayValue) if foundErr != nil { - return errors.Wrapf(foundErr, "failed to decode value") + return foundErr } return nil } func (d *Decoder) decodeSlice(ctx context.Context, dst reflect.Value, src ast.Node) error { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return ErrExceededMaxDepth + } + arrayNode, err := d.getArrayNode(src) if err != nil { - return errors.Wrapf(err, "failed to get array node") + return err } if arrayNode == nil { return nil @@ -1418,15 +1604,21 @@ func (d *Decoder) decodeSlice(ctx context.Context, dst reflect.Value, src ast.No } dst.Set(sliceValue) if foundErr != nil { - return errors.Wrapf(foundErr, "failed to decode value") + return foundErr } return nil } func (d *Decoder) decodeMapItem(ctx context.Context, dst *MapItem, src ast.Node) error { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return ErrExceededMaxDepth + } + mapNode, err := d.getMapNode(src) if err != nil { - return errors.Wrapf(err, "failed to get map node") + return err } if mapNode == nil { return nil @@ -1439,14 +1631,19 @@ func (d *Decoder) decodeMapItem(ctx context.Context, dst *MapItem, src ast.Node) value := mapIter.Value() if key.Type() == ast.MergeKeyType { if err := d.decodeMapItem(ctx, dst, value); err != nil { - return errors.Wrapf(err, "failed to decode map with merge key") + return err } return nil } - *dst = MapItem{ - Key: d.nodeToValue(key), - Value: d.nodeToValue(value), + k, err := d.nodeToValue(key) + if err != nil { + return err + } + v, err := d.nodeToValue(value) + if err != nil { + return err } + *dst = MapItem{Key: k, Value: v} return nil } @@ -1455,9 +1652,9 @@ func (d *Decoder) validateDuplicateKey(keyMap map[string]struct{}, key interface if !ok { return nil } - if d.disallowDuplicateKey { + if !d.allowDuplicateMapKey { if _, exists := keyMap[k]; exists { - return errDuplicateKey(fmt.Sprintf(`duplicate key "%s"`, k), keyNode.GetToken()) + return errors.ErrDuplicateKey(fmt.Sprintf(`duplicate key "%s"`, k), keyNode.GetToken()) } } keyMap[k] = struct{}{} @@ -1465,9 +1662,15 @@ func (d *Decoder) validateDuplicateKey(keyMap map[string]struct{}, key interface } func (d *Decoder) decodeMapSlice(ctx context.Context, dst *MapSlice, src ast.Node) error { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return ErrExceededMaxDepth + } + mapNode, err := d.getMapNode(src) if err != nil { - return errors.Wrapf(err, "failed to get map node") + return err } if mapNode == nil { return nil @@ -1481,33 +1684,43 @@ func (d *Decoder) decodeMapSlice(ctx context.Context, dst *MapSlice, src ast.Nod if key.Type() == ast.MergeKeyType { var m MapSlice if err := d.decodeMapSlice(ctx, &m, value); err != nil { - return errors.Wrapf(err, "failed to decode map with merge key") + return err } for _, v := range m { if err := d.validateDuplicateKey(keyMap, v.Key, value); err != nil { - return errors.Wrapf(err, "invalid map key") + return err } mapSlice = append(mapSlice, v) } continue } - k := d.nodeToValue(key) + k, err := d.nodeToValue(key) + if err != nil { + return err + } if err := d.validateDuplicateKey(keyMap, k, key); err != nil { - return errors.Wrapf(err, "invalid map key") + return err + } + v, err := d.nodeToValue(value) + if err != nil { + return err } - mapSlice = append(mapSlice, MapItem{ - Key: k, - Value: d.nodeToValue(value), - }) + mapSlice = append(mapSlice, MapItem{Key: k, Value: v}) } *dst = mapSlice return nil } func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node) error { + d.stepIn() + defer d.stepOut() + if d.isExceededMaxDepth() { + return ErrExceededMaxDepth + } + mapNode, err := d.getMapNode(src) if err != nil { - return errors.Wrapf(err, "failed to get map node") + return err } if mapNode == nil { return nil @@ -1524,12 +1737,12 @@ func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node value := mapIter.Value() if key.Type() == ast.MergeKeyType { if err := d.decodeMap(ctx, dst, value); err != nil { - return errors.Wrapf(err, "failed to decode map with merge key") + return err } iter := dst.MapRange() for iter.Next() { if err := d.validateDuplicateKey(keyMap, iter.Key(), value); err != nil { - return errors.Wrapf(err, "invalid map key") + return err } mapValue.SetMapIndex(iter.Key(), iter.Value()) } @@ -1539,10 +1752,14 @@ func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node k := d.createDecodableValue(keyType) if d.canDecodeByUnmarshaler(k) { if err := d.decodeByUnmarshaler(ctx, k, key); err != nil { - return errors.Wrapf(err, "failed to decode by unmarshaler") + return err } } else { - k = reflect.ValueOf(d.nodeToValue(key)) + keyVal, err := d.nodeToValue(key) + if err != nil { + return err + } + k = reflect.ValueOf(keyVal) if k.IsValid() && k.Type().ConvertibleTo(keyType) { k = k.Convert(keyType) } @@ -1550,7 +1767,7 @@ func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node if k.IsValid() { if err := d.validateDuplicateKey(keyMap, k.Interface(), key); err != nil { - return errors.Wrapf(err, "invalid map key") + return err } } if valueType.Kind() == reflect.Ptr && value.Type() == ast.NullType { @@ -1569,11 +1786,17 @@ func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node mapValue.SetMapIndex(d.createDecodableValue(keyType), d.castToAssignableValue(dstValue, valueType)) continue } + if keyType.Kind() != k.Kind() { + return errors.ErrSyntax( + fmt.Sprintf("cannot convert %q type to %q type", k.Kind(), keyType.Kind()), + key.GetToken(), + ) + } mapValue.SetMapIndex(k, d.castToAssignableValue(dstValue, valueType)) } dst.Set(mapValue) if foundErr != nil { - return errors.Wrapf(foundErr, "failed to decode value") + return foundErr } return nil } @@ -1581,7 +1804,7 @@ func (d *Decoder) decodeMap(ctx context.Context, dst reflect.Value, src ast.Node func (d *Decoder) fileToReader(file string) (io.Reader, error) { reader, err := os.Open(file) if err != nil { - return nil, errors.Wrapf(err, "failed to open file") + return nil, err } return reader, nil } @@ -1601,7 +1824,7 @@ func (d *Decoder) readersUnderDir(dir string) ([]io.Reader, error) { pattern := fmt.Sprintf("%s/*", dir) matches, err := filepath.Glob(pattern) if err != nil { - return nil, errors.Wrapf(err, "failed to get files by %s", pattern) + return nil, err } readers := []io.Reader{} for _, match := range matches { @@ -1610,7 +1833,7 @@ func (d *Decoder) readersUnderDir(dir string) ([]io.Reader, error) { } reader, err := d.fileToReader(match) if err != nil { - return nil, errors.Wrapf(err, "failed to get reader") + return nil, err } readers = append(readers, reader) } @@ -1619,18 +1842,18 @@ func (d *Decoder) readersUnderDir(dir string) ([]io.Reader, error) { func (d *Decoder) readersUnderDirRecursive(dir string) ([]io.Reader, error) { readers := []io.Reader{} - if err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err := filepath.Walk(dir, func(path string, info os.FileInfo, _ error) error { if !d.isYAMLFile(path) { return nil } - reader, err := d.fileToReader(path) - if err != nil { - return errors.Wrapf(err, "failed to get reader") + reader, readerErr := d.fileToReader(path) + if readerErr != nil { + return readerErr } readers = append(readers, reader) return nil }); err != nil { - return nil, errors.Wrapf(err, "interrupt walk in %s", dir) + return nil, err } return readers, nil } @@ -1638,13 +1861,13 @@ func (d *Decoder) readersUnderDirRecursive(dir string) ([]io.Reader, error) { func (d *Decoder) resolveReference() error { for _, opt := range d.opts { if err := opt(d); err != nil { - return errors.Wrapf(err, "failed to exec option") + return err } } for _, file := range d.referenceFiles { reader, err := d.fileToReader(file) if err != nil { - return errors.Wrapf(err, "failed to get reader") + return err } d.referenceReaders = append(d.referenceReaders, reader) } @@ -1652,13 +1875,13 @@ func (d *Decoder) resolveReference() error { if !d.isRecursiveDir { readers, err := d.readersUnderDir(dir) if err != nil { - return errors.Wrapf(err, "failed to get readers from under the %s", dir) + return err } d.referenceReaders = append(d.referenceReaders, readers...) } else { readers, err := d.readersUnderDirRecursive(dir) if err != nil { - return errors.Wrapf(err, "failed to get readers from under the %s", dir) + return err } d.referenceReaders = append(d.referenceReaders, readers...) } @@ -1666,12 +1889,12 @@ func (d *Decoder) resolveReference() error { for _, reader := range d.referenceReaders { bytes, err := io.ReadAll(reader) if err != nil { - return errors.Wrapf(err, "failed to read buffer") + return err } // assign new anchor definition to anchorMap if _, err := d.parse(bytes); err != nil { - return errors.Wrapf(err, "failed to decode") + return err } } d.isResolvedReference = true @@ -1683,14 +1906,22 @@ func (d *Decoder) parse(bytes []byte) (*ast.File, error) { if d.toCommentMap != nil { parseMode = parser.ParseComments } - f, err := parser.ParseBytes(bytes, parseMode) + var opts []parser.Option + if d.allowDuplicateMapKey { + opts = append(opts, parser.AllowDuplicateMapKey()) + } + f, err := parser.ParseBytes(bytes, parseMode, opts...) if err != nil { - return nil, errors.Wrapf(err, "failed to parse yaml") + return nil, err } normalizedFile := &ast.File{} for _, doc := range f.Docs { // try to decode ast.Node to value and map anchor value to anchorMap - if v := d.nodeToValue(doc.Body); v != nil { + v, err := d.nodeToValue(doc.Body) + if err != nil { + return nil, err + } + if v != nil { normalizedFile.Docs = append(normalizedFile.Docs, doc) } } @@ -1704,22 +1935,23 @@ func (d *Decoder) isInitialized() bool { func (d *Decoder) decodeInit() error { if !d.isResolvedReference { if err := d.resolveReference(); err != nil { - return errors.Wrapf(err, "failed to resolve reference") + return err } } var buf bytes.Buffer if _, err := io.Copy(&buf, d.reader); err != nil { - return errors.Wrapf(err, "failed to copy from reader") + return err } file, err := d.parse(buf.Bytes()) if err != nil { - return errors.Wrapf(err, "failed to decode") + return err } d.parsedFile = file return nil } func (d *Decoder) decode(ctx context.Context, v reflect.Value) error { + d.decodeDepth = 0 if len(d.parsedFile.Docs) <= d.streamIndex { return io.EOF } @@ -1728,7 +1960,7 @@ func (d *Decoder) decode(ctx context.Context, v reflect.Value) error { return nil } if err := d.decodeValue(ctx, v.Elem(), body); err != nil { - return errors.Wrapf(err, "failed to decode value") + return err } d.streamIndex++ return nil @@ -1748,25 +1980,25 @@ func (d *Decoder) Decode(v interface{}) error { func (d *Decoder) DecodeContext(ctx context.Context, v interface{}) error { rv := reflect.ValueOf(v) if rv.Type().Kind() != reflect.Ptr { - return errors.ErrDecodeRequiredPointerType + return ErrDecodeRequiredPointerType } if d.isInitialized() { if err := d.decode(ctx, rv); err != nil { if err == io.EOF { return err } - return errors.Wrapf(err, "failed to decode") + return err } return nil } if err := d.decodeInit(); err != nil { - return errors.Wrapf(err, "failed to decodeInit") + return err } if err := d.decode(ctx, rv); err != nil { if err == io.EOF { return err } - return errors.Wrapf(err, "failed to decode") + return err } return nil } @@ -1780,17 +2012,19 @@ func (d *Decoder) DecodeFromNode(node ast.Node, v interface{}) error { func (d *Decoder) DecodeFromNodeContext(ctx context.Context, node ast.Node, v interface{}) error { rv := reflect.ValueOf(v) if rv.Type().Kind() != reflect.Ptr { - return errors.ErrDecodeRequiredPointerType + return ErrDecodeRequiredPointerType } if !d.isInitialized() { if err := d.decodeInit(); err != nil { - return errors.Wrapf(err, "failed to decodInit") + return err } } // resolve references to the anchor on the same file - d.nodeToValue(node) + if _, err := d.nodeToValue(node); err != nil { + return err + } if err := d.decodeValue(ctx, rv.Elem(), node); err != nil { - return errors.Wrapf(err, "failed to decode value") + return err } return nil } diff --git a/vendor/github.com/goccy/go-yaml/encode.go b/vendor/github.com/goccy/go-yaml/encode.go index 3b9b298..97c1fa5 100644 --- a/vendor/github.com/goccy/go-yaml/encode.go +++ b/vendor/github.com/goccy/go-yaml/encode.go @@ -17,7 +17,6 @@ import ( "github.com/goccy/go-yaml/parser" "github.com/goccy/go-yaml/printer" "github.com/goccy/go-yaml/token" - "golang.org/x/xerrors" ) const ( @@ -84,19 +83,19 @@ func (e *Encoder) Encode(v interface{}) error { func (e *Encoder) EncodeContext(ctx context.Context, v interface{}) error { node, err := e.EncodeToNodeContext(ctx, v) if err != nil { - return errors.Wrapf(err, "failed to encode to node") + return err } if err := e.setCommentByCommentMap(node); err != nil { - return errors.Wrapf(err, "failed to set comment by comment map") + return err } if !e.written { e.written = true } else { // write document separator - e.writer.Write([]byte("---\n")) + _, _ = e.writer.Write([]byte("---\n")) } var p printer.Printer - e.writer.Write(p.PrintNode(node)) + _, _ = e.writer.Write(p.PrintNode(node)) return nil } @@ -109,12 +108,12 @@ func (e *Encoder) EncodeToNode(v interface{}) (ast.Node, error) { func (e *Encoder) EncodeToNodeContext(ctx context.Context, v interface{}) (ast.Node, error) { for _, opt := range e.opts { if err := opt(e); err != nil { - return nil, errors.Wrapf(err, "failed to run option for encoder") + return nil, err } } node, err := e.encodeValue(ctx, reflect.ValueOf(v), 1) if err != nil { - return nil, errors.Wrapf(err, "failed to encode value") + return nil, err } return node, nil } @@ -126,7 +125,7 @@ func (e *Encoder) setCommentByCommentMap(node ast.Node) error { for path, comments := range e.commentMap { n, err := path.FilterNode(node) if err != nil { - return errors.Wrapf(err, "failed to filter node") + return err } if n == nil { continue @@ -140,15 +139,15 @@ func (e *Encoder) setCommentByCommentMap(node ast.Node) error { switch comment.Position { case CommentHeadPosition: if err := e.setHeadComment(node, n, commentGroup); err != nil { - return errors.Wrapf(err, "failed to set head comment") + return err } case CommentLinePosition: if err := e.setLineComment(node, n, commentGroup); err != nil { - return errors.Wrapf(err, "failed to set line comment") + return err } case CommentFootPosition: if err := e.setFootComment(node, n, commentGroup); err != nil { - return errors.Wrapf(err, "failed to set foot comment") + return err } default: return ErrUnknownCommentPositionType @@ -166,11 +165,11 @@ func (e *Encoder) setHeadComment(node ast.Node, filtered ast.Node, comment *ast. switch p := parent.(type) { case *ast.MappingValueNode: if err := p.SetComment(comment); err != nil { - return errors.Wrapf(err, "failed to set comment") + return err } case *ast.MappingNode: if err := p.SetComment(comment); err != nil { - return errors.Wrapf(err, "failed to set comment") + return err } case *ast.SequenceNode: if len(p.ValueHeadComments) == 0 { @@ -196,11 +195,11 @@ func (e *Encoder) setLineComment(node ast.Node, filtered ast.Node, comment *ast. // Line comment cannot be set for mapping value node. // It should probably be set for the parent map node if err := e.setLineCommentToParentMapNode(node, filtered, comment); err != nil { - return errors.Wrapf(err, "failed to set line comment to parent node") + return err } default: if err := filtered.SetComment(comment); err != nil { - return errors.Wrapf(err, "failed to set comment") + return err } } return nil @@ -214,11 +213,11 @@ func (e *Encoder) setLineCommentToParentMapNode(node ast.Node, filtered ast.Node switch p := parent.(type) { case *ast.MappingValueNode: if err := p.Key.SetComment(comment); err != nil { - return errors.Wrapf(err, "failed to set comment") + return err } case *ast.MappingNode: if err := p.SetComment(comment); err != nil { - return errors.Wrapf(err, "failed to set comment") + return err } default: return ErrUnsupportedLinePositionType(parent) @@ -247,7 +246,7 @@ func (e *Encoder) setFootComment(node ast.Node, filtered ast.Node, comment *ast. func (e *Encoder) encodeDocument(doc []byte) (ast.Node, error) { f, err := parser.ParseBytes(doc, 0) if err != nil { - return nil, errors.Wrapf(err, "failed to parse yaml") + return nil, err } for _, docNode := range f.Docs { if docNode.Body != nil { @@ -336,11 +335,11 @@ func (e *Encoder) encodeByMarshaler(ctx context.Context, v reflect.Value, column if marshaler, exists := e.marshalerFromCustomMarshalerMap(v.Type()); exists { doc, err := marshaler(iface) if err != nil { - return nil, errors.Wrapf(err, "failed to MarshalYAML") + return nil, err } node, err := e.encodeDocument(doc) if err != nil { - return nil, errors.Wrapf(err, "failed to encode document") + return nil, err } return node, nil } @@ -348,11 +347,11 @@ func (e *Encoder) encodeByMarshaler(ctx context.Context, v reflect.Value, column if marshaler, ok := iface.(BytesMarshalerContext); ok { doc, err := marshaler.MarshalYAML(ctx) if err != nil { - return nil, errors.Wrapf(err, "failed to MarshalYAML") + return nil, err } node, err := e.encodeDocument(doc) if err != nil { - return nil, errors.Wrapf(err, "failed to encode document") + return nil, err } return node, nil } @@ -360,11 +359,11 @@ func (e *Encoder) encodeByMarshaler(ctx context.Context, v reflect.Value, column if marshaler, ok := iface.(BytesMarshaler); ok { doc, err := marshaler.MarshalYAML() if err != nil { - return nil, errors.Wrapf(err, "failed to MarshalYAML") + return nil, err } node, err := e.encodeDocument(doc) if err != nil { - return nil, errors.Wrapf(err, "failed to encode document") + return nil, err } return node, nil } @@ -372,7 +371,7 @@ func (e *Encoder) encodeByMarshaler(ctx context.Context, v reflect.Value, column if marshaler, ok := iface.(InterfaceMarshalerContext); ok { marshalV, err := marshaler.MarshalYAML(ctx) if err != nil { - return nil, errors.Wrapf(err, "failed to MarshalYAML") + return nil, err } return e.encodeValue(ctx, reflect.ValueOf(marshalV), column) } @@ -380,7 +379,7 @@ func (e *Encoder) encodeByMarshaler(ctx context.Context, v reflect.Value, column if marshaler, ok := iface.(InterfaceMarshaler); ok { marshalV, err := marshaler.MarshalYAML() if err != nil { - return nil, errors.Wrapf(err, "failed to MarshalYAML") + return nil, err } return e.encodeValue(ctx, reflect.ValueOf(marshalV), column) } @@ -396,11 +395,11 @@ func (e *Encoder) encodeByMarshaler(ctx context.Context, v reflect.Value, column if marshaler, ok := iface.(encoding.TextMarshaler); ok { doc, err := marshaler.MarshalText() if err != nil { - return nil, errors.Wrapf(err, "failed to MarshalText") + return nil, err } node, err := e.encodeDocument(doc) if err != nil { - return nil, errors.Wrapf(err, "failed to encode document") + return nil, err } return node, nil } @@ -409,21 +408,21 @@ func (e *Encoder) encodeByMarshaler(ctx context.Context, v reflect.Value, column if marshaler, ok := iface.(jsonMarshaler); ok { jsonBytes, err := marshaler.MarshalJSON() if err != nil { - return nil, errors.Wrapf(err, "failed to MarshalJSON") + return nil, err } doc, err := JSONToYAML(jsonBytes) if err != nil { - return nil, errors.Wrapf(err, "failed to convert json to yaml") + return nil, err } node, err := e.encodeDocument(doc) if err != nil { - return nil, errors.Wrapf(err, "failed to encode document") + return nil, err } return node, nil } } - return nil, xerrors.Errorf("does not implemented Marshaler") + return nil, errors.New("does not implemented Marshaler") } func (e *Encoder) encodeValue(ctx context.Context, v reflect.Value, column int) (ast.Node, error) { @@ -433,7 +432,7 @@ func (e *Encoder) encodeValue(ctx context.Context, v reflect.Value, column int) if e.canEncodeByMarshaler(v) { node, err := e.encodeByMarshaler(ctx, v, column) if err != nil { - return nil, errors.Wrapf(err, "failed to encode by marshaler") + return nil, err } return node, nil } @@ -481,7 +480,7 @@ func (e *Encoder) encodeValue(ctx context.Context, v reflect.Value, column int) case reflect.Map: return e.encodeMap(ctx, v, column), nil default: - return nil, xerrors.Errorf("unknown value type %s", v.Type().String()) + return nil, fmt.Errorf("unknown value type %s", v.Type().String()) } } @@ -570,7 +569,7 @@ func (e *Encoder) encodeSlice(ctx context.Context, value reflect.Value) (*ast.Se for i := 0; i < value.Len(); i++ { node, err := e.encodeValue(ctx, value.Index(i), column) if err != nil { - return nil, errors.Wrapf(err, "failed to encode value for slice") + return nil, err } sequence.Values = append(sequence.Values, node) } @@ -589,7 +588,7 @@ func (e *Encoder) encodeArray(ctx context.Context, value reflect.Value) (*ast.Se for i := 0; i < value.Len(); i++ { node, err := e.encodeValue(ctx, value.Index(i), column) if err != nil { - return nil, errors.Wrapf(err, "failed to encode value for array") + return nil, err } sequence.Values = append(sequence.Values, node) } @@ -604,7 +603,7 @@ func (e *Encoder) encodeMapItem(ctx context.Context, item MapItem, column int) ( v := reflect.ValueOf(item.Value) value, err := e.encodeValue(ctx, v, column) if err != nil { - return nil, errors.Wrapf(err, "failed to encode MapItem") + return nil, err } if e.isMapNode(value) { value.AddColumn(e.indent) @@ -621,7 +620,7 @@ func (e *Encoder) encodeMapSlice(ctx context.Context, value MapSlice, column int for _, item := range value { value, err := e.encodeMapItem(ctx, item, column) if err != nil { - return nil, errors.Wrapf(err, "failed to encode MapItem for MapSlice") + return nil, err } node.Values = append(node.Values, value) } @@ -730,7 +729,7 @@ func (e *Encoder) encodeAnchor(anchorName string, value ast.Node, fieldValue ref anchorNode.Value = value if e.anchorCallback != nil { if err := e.anchorCallback(anchorNode, fieldValue.Interface()); err != nil { - return nil, errors.Wrapf(err, "failed to marshal anchor") + return nil, err } if snode, ok := anchorNode.Name.(*ast.StringNode); ok { anchorName = snode.Value @@ -747,7 +746,7 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column structType := value.Type() structFieldMap, err := structFieldMap(structType) if err != nil { - return nil, errors.Wrapf(err, "failed to get struct field map") + return nil, err } hasInlineAnchorField := false var inlineAnchorValue reflect.Value @@ -770,7 +769,7 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column } value, err := ve.encodeValue(ctx, fieldValue, column) if err != nil { - return nil, errors.Wrapf(err, "failed to encode value") + return nil, err } if e.isMapNode(value) { value.AddColumn(e.indent) @@ -780,19 +779,19 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column case structField.AnchorName != "": anchorNode, err := e.encodeAnchor(structField.AnchorName, value, fieldValue, column) if err != nil { - return nil, errors.Wrapf(err, "failed to encode anchor") + return nil, err } value = anchorNode case structField.IsAutoAlias: if fieldValue.Kind() != reflect.Ptr { - return nil, xerrors.Errorf( + return nil, fmt.Errorf( "%s in struct is not pointer type. but required automatically alias detection", structField.FieldName, ) } anchorName := e.anchorPtrToNameMap[fieldValue.Pointer()] if anchorName == "" { - return nil, xerrors.Errorf( + return nil, errors.New( "cannot find anchor name from pointer address for automatically alias detection", ) } @@ -827,7 +826,7 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column if _, ok := value.(*ast.NullNode); ok { continue } - return nil, xerrors.Errorf("inline value is must be map or struct type") + return nil, errors.New("inline value is must be map or struct type") } mapIter := mapNode.MapRange() for mapIter.Next() { @@ -846,7 +845,7 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column case structField.IsAutoAnchor: anchorNode, err := e.encodeAnchor(structField.RenderName, value, fieldValue, column) if err != nil { - return nil, errors.Wrapf(err, "failed to encode anchor") + return nil, err } value = anchorNode } @@ -860,7 +859,7 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column anchorNode.Value = node if e.anchorCallback != nil { if err := e.anchorCallback(anchorNode, value.Addr().Interface()); err != nil { - return nil, errors.Wrapf(err, "failed to marshal anchor") + return nil, err } if snode, ok := anchorNode.Name.(*ast.StringNode); ok { anchorName = snode.Value diff --git a/vendor/github.com/goccy/go-yaml/error.go b/vendor/github.com/goccy/go-yaml/error.go index 163dcc5..6d2a759 100644 --- a/vendor/github.com/goccy/go-yaml/error.go +++ b/vendor/github.com/goccy/go-yaml/error.go @@ -1,62 +1,75 @@ package yaml import ( + "fmt" + "github.com/goccy/go-yaml/ast" - "golang.org/x/xerrors" + "github.com/goccy/go-yaml/internal/errors" ) var ( - ErrInvalidQuery = xerrors.New("invalid query") - ErrInvalidPath = xerrors.New("invalid path instance") - ErrInvalidPathString = xerrors.New("invalid path string") - ErrNotFoundNode = xerrors.New("node not found") - ErrUnknownCommentPositionType = xerrors.New("unknown comment position type") - ErrInvalidCommentMapValue = xerrors.New("invalid comment map value. it must be not nil value") + ErrInvalidQuery = errors.New("invalid query") + ErrInvalidPath = errors.New("invalid path instance") + ErrInvalidPathString = errors.New("invalid path string") + ErrNotFoundNode = errors.New("node not found") + ErrUnknownCommentPositionType = errors.New("unknown comment position type") + ErrInvalidCommentMapValue = errors.New("invalid comment map value. it must be not nil value") + ErrDecodeRequiredPointerType = errors.New("required pointer type value") + ErrExceededMaxDepth = errors.New("exceeded max depth") +) + +type ( + SyntaxError = errors.SyntaxError + TypeError = errors.TypeError + OverflowError = errors.OverflowError + DuplicateKeyError = errors.DuplicateKeyError + UnknownFieldError = errors.UnknownFieldError + UnexpectedNodeTypeError = errors.UnexpectedNodeTypeError ) func ErrUnsupportedHeadPositionType(node ast.Node) error { - return xerrors.Errorf("unsupported comment head position for %s", node.Type()) + return fmt.Errorf("unsupported comment head position for %s", node.Type()) } func ErrUnsupportedLinePositionType(node ast.Node) error { - return xerrors.Errorf("unsupported comment line position for %s", node.Type()) + return fmt.Errorf("unsupported comment line position for %s", node.Type()) } func ErrUnsupportedFootPositionType(node ast.Node) error { - return xerrors.Errorf("unsupported comment foot position for %s", node.Type()) + return fmt.Errorf("unsupported comment foot position for %s", node.Type()) } // IsInvalidQueryError whether err is ErrInvalidQuery or not. func IsInvalidQueryError(err error) bool { - return xerrors.Is(err, ErrInvalidQuery) + return errors.Is(err, ErrInvalidQuery) } // IsInvalidPathError whether err is ErrInvalidPath or not. func IsInvalidPathError(err error) bool { - return xerrors.Is(err, ErrInvalidPath) + return errors.Is(err, ErrInvalidPath) } // IsInvalidPathStringError whether err is ErrInvalidPathString or not. func IsInvalidPathStringError(err error) bool { - return xerrors.Is(err, ErrInvalidPathString) + return errors.Is(err, ErrInvalidPathString) } // IsNotFoundNodeError whether err is ErrNotFoundNode or not. func IsNotFoundNodeError(err error) bool { - return xerrors.Is(err, ErrNotFoundNode) + return errors.Is(err, ErrNotFoundNode) } // IsInvalidTokenTypeError whether err is ast.ErrInvalidTokenType or not. func IsInvalidTokenTypeError(err error) bool { - return xerrors.Is(err, ast.ErrInvalidTokenType) + return errors.Is(err, ast.ErrInvalidTokenType) } // IsInvalidAnchorNameError whether err is ast.ErrInvalidAnchorName or not. func IsInvalidAnchorNameError(err error) bool { - return xerrors.Is(err, ast.ErrInvalidAnchorName) + return errors.Is(err, ast.ErrInvalidAnchorName) } // IsInvalidAliasNameError whether err is ast.ErrInvalidAliasName or not. func IsInvalidAliasNameError(err error) bool { - return xerrors.Is(err, ast.ErrInvalidAliasName) + return errors.Is(err, ast.ErrInvalidAliasName) } diff --git a/vendor/github.com/goccy/go-yaml/internal/errors/error.go b/vendor/github.com/goccy/go-yaml/internal/errors/error.go index 7f1ea9a..d7f1124 100644 --- a/vendor/github.com/goccy/go-yaml/internal/errors/error.go +++ b/vendor/github.com/goccy/go-yaml/internal/errors/error.go @@ -1,260 +1,175 @@ package errors import ( - "bytes" + "errors" "fmt" "reflect" + "github.com/goccy/go-yaml/ast" "github.com/goccy/go-yaml/printer" "github.com/goccy/go-yaml/token" - "golang.org/x/xerrors" ) -const ( - defaultColorize = false - defaultIncludeSource = true +var ( + As = errors.As + Is = errors.Is + New = errors.New ) -var ( - ErrDecodeRequiredPointerType = xerrors.New("required pointer type value") +const ( + defaultFormatColor = false + defaultIncludeSource = true ) -// Wrapf wrap error for stack trace -func Wrapf(err error, msg string, args ...interface{}) error { - return &wrapError{ - baseError: &baseError{}, - err: xerrors.Errorf(msg, args...), - nextErr: err, - frame: xerrors.Caller(1), - } +type PrettyFormatError interface { + FormatError(bool, bool) string } -// ErrSyntax create syntax error instance with message and token -func ErrSyntax(msg string, tk *token.Token) *syntaxError { - return &syntaxError{ - baseError: &baseError{}, - msg: msg, - token: tk, - frame: xerrors.Caller(1), - } +type SyntaxError struct { + Message string + Token *token.Token } -type baseError struct { - state fmt.State - verb rune +type TypeError struct { + DstType reflect.Type + SrcType reflect.Type + StructFieldName *string + Token *token.Token } -func (e *baseError) Error() string { - return "" +type OverflowError struct { + DstType reflect.Type + SrcNum string + Token *token.Token } -func (e *baseError) chainStateAndVerb(err error) { - wrapErr, ok := err.(*wrapError) - if ok { - wrapErr.state = e.state - wrapErr.verb = e.verb - } - syntaxErr, ok := err.(*syntaxError) - if ok { - syntaxErr.state = e.state - syntaxErr.verb = e.verb - } +type DuplicateKeyError struct { + Message string + Token *token.Token } -type wrapError struct { - *baseError - err error - nextErr error - frame xerrors.Frame +type UnknownFieldError struct { + Message string + Token *token.Token } -type FormatErrorPrinter struct { - xerrors.Printer - Colored bool - InclSource bool +type UnexpectedNodeTypeError struct { + Actual ast.NodeType + Expected ast.NodeType + Token *token.Token } -func (e *wrapError) As(target interface{}) bool { - err := e.nextErr - for { - if wrapErr, ok := err.(*wrapError); ok { - err = wrapErr.nextErr - continue - } - break +// ErrSyntax create syntax error instance with message and token +func ErrSyntax(msg string, tk *token.Token) *SyntaxError { + return &SyntaxError{ + Message: msg, + Token: tk, } - return xerrors.As(err, target) -} - -func (e *wrapError) Unwrap() error { - return e.nextErr -} - -func (e *wrapError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error { - return e.FormatError(&FormatErrorPrinter{Printer: p, Colored: colored, InclSource: inclSource}) } -func (e *wrapError) FormatError(p xerrors.Printer) error { - if _, ok := p.(*FormatErrorPrinter); !ok { - p = &FormatErrorPrinter{ - Printer: p, - Colored: defaultColorize, - InclSource: defaultIncludeSource, - } +// ErrOverflow creates an overflow error instance with message and a token. +func ErrOverflow(dstType reflect.Type, num string, tk *token.Token) *OverflowError { + return &OverflowError{ + DstType: dstType, + SrcNum: num, + Token: tk, } - if e.verb == 'v' && e.state.Flag('+') { - // print stack trace for debugging - p.Print(e.err, "\n") - e.frame.Format(p) - e.chainStateAndVerb(e.nextErr) - return e.nextErr - } - err := e.nextErr - for { - if wrapErr, ok := err.(*wrapError); ok { - err = wrapErr.nextErr - continue - } - break - } - e.chainStateAndVerb(err) - if fmtErr, ok := err.(xerrors.Formatter); ok { - fmtErr.FormatError(p) - } else { - p.Print(err) - } - return nil } -type wrapState struct { - org fmt.State -} - -func (s *wrapState) Write(b []byte) (n int, err error) { - return s.org.Write(b) +// ErrTypeMismatch cerates an type mismatch error instance with token. +func ErrTypeMismatch(dstType, srcType reflect.Type, token *token.Token) *TypeError { + return &TypeError{ + DstType: dstType, + SrcType: srcType, + Token: token, + } } -func (s *wrapState) Width() (wid int, ok bool) { - return s.org.Width() +// ErrDuplicateKey creates an duplicate key error instance with token. +func ErrDuplicateKey(msg string, tk *token.Token) *DuplicateKeyError { + return &DuplicateKeyError{ + Message: msg, + Token: tk, + } } -func (s *wrapState) Precision() (prec int, ok bool) { - return s.org.Precision() +// ErrUnknownField creates an unknown field error instance with token. +func ErrUnknownField(msg string, tk *token.Token) *UnknownFieldError { + return &UnknownFieldError{ + Message: msg, + Token: tk, + } } -func (s *wrapState) Flag(c int) bool { - // set true to 'printDetail' forced because when p.Detail() is false, xerrors.Printer no output any text - if c == '#' { - // ignore '#' keyword because xerrors.FormatError doesn't set true to printDetail. - // ( see https://github.com/golang/xerrors/blob/master/adaptor.go#L39-L43 ) - return false +func ErrUnexpectedNodeType(actual, expected ast.NodeType, tk *token.Token) *UnexpectedNodeTypeError { + return &UnexpectedNodeTypeError{ + Actual: actual, + Expected: expected, + Token: tk, } - return true } -func (e *wrapError) Format(state fmt.State, verb rune) { - e.state = state - e.verb = verb - xerrors.FormatError(e, &wrapState{org: state}, verb) +func (e *SyntaxError) Error() string { + return e.FormatError(defaultFormatColor, defaultIncludeSource) } -func (e *wrapError) Error() string { - var buf bytes.Buffer - e.PrettyPrint(&Sink{&buf}, defaultColorize, defaultIncludeSource) - return buf.String() +func (e *SyntaxError) FormatError(colored, inclSource bool) string { + return formatError(e.Message, e.Token, colored, inclSource) } -type syntaxError struct { - *baseError - msg string - token *token.Token - frame xerrors.Frame +func (e *OverflowError) Error() string { + return e.FormatError(defaultFormatColor, defaultIncludeSource) } -func (e *syntaxError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error { - return e.FormatError(&FormatErrorPrinter{Printer: p, Colored: colored, InclSource: inclSource}) +func (e *OverflowError) FormatError(colored, inclSource bool) string { + return formatError(fmt.Sprintf("cannot unmarshal %s into Go value of type %s ( overflow )", e.SrcNum, e.DstType), e.Token, colored, inclSource) } -func (e *syntaxError) FormatError(p xerrors.Printer) error { - var pp printer.Printer - - var colored, inclSource bool - if fep, ok := p.(*FormatErrorPrinter); ok { - colored = fep.Colored - inclSource = fep.InclSource - } - - pos := fmt.Sprintf("[%d:%d] ", e.token.Position.Line, e.token.Position.Column) - msg := pp.PrintErrorMessage(fmt.Sprintf("%s%s", pos, e.msg), colored) - if inclSource { - msg += "\n" + pp.PrintErrorToken(e.token, colored) - } - p.Print(msg) - - if e.verb == 'v' && e.state.Flag('+') { - // %+v - // print stack trace for debugging - e.frame.Format(p) +func (e *TypeError) msg() string { + if e.StructFieldName != nil { + return fmt.Sprintf("cannot unmarshal %s into Go struct field %s of type %s", e.SrcType, *e.StructFieldName, e.DstType) } - return nil + return fmt.Sprintf("cannot unmarshal %s into Go value of type %s", e.SrcType, e.DstType) } -type PrettyPrinter interface { - PrettyPrint(xerrors.Printer, bool, bool) error +func (e *TypeError) Error() string { + return e.FormatError(defaultFormatColor, defaultIncludeSource) } -type Sink struct{ *bytes.Buffer } -func (es *Sink) Print(args ...interface{}) { - fmt.Fprint(es.Buffer, args...) +func (e *TypeError) FormatError(colored, inclSource bool) string { + return formatError(e.msg(), e.Token, colored, inclSource) } -func (es *Sink) Printf(f string, args ...interface{}) { - fmt.Fprintf(es.Buffer, f, args...) +func (e *DuplicateKeyError) Error() string { + return e.FormatError(defaultFormatColor, defaultIncludeSource) } -func (es *Sink) Detail() bool { - return false +func (e *DuplicateKeyError) FormatError(colored, inclSource bool) string { + return formatError(e.Message, e.Token, colored, inclSource) } -func (e *syntaxError) Error() string { - var buf bytes.Buffer - e.PrettyPrint(&Sink{&buf}, defaultColorize, defaultIncludeSource) - return buf.String() +func (e *UnknownFieldError) Error() string { + return e.FormatError(defaultFormatColor, defaultIncludeSource) } -type TypeError struct { - DstType reflect.Type - SrcType reflect.Type - StructFieldName *string - Token *token.Token +func (e *UnknownFieldError) FormatError(colored, inclSource bool) string { + return formatError(e.Message, e.Token, colored, inclSource) } -func (e *TypeError) Error() string { - if e.StructFieldName != nil { - return fmt.Sprintf("cannot unmarshal %s into Go struct field %s of type %s", e.SrcType, *e.StructFieldName, e.DstType) - } - return fmt.Sprintf("cannot unmarshal %s into Go value of type %s", e.SrcType, e.DstType) +func (e *UnexpectedNodeTypeError) Error() string { + return e.FormatError(defaultFormatColor, defaultIncludeSource) } -func (e *TypeError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error { - return e.FormatError(&FormatErrorPrinter{Printer: p, Colored: colored, InclSource: inclSource}) +func (e *UnexpectedNodeTypeError) FormatError(colored, inclSource bool) string { + return formatError(fmt.Sprintf("%s was used where %s is expected", e.Actual.YAMLName(), e.Expected.YAMLName()), e.Token, colored, inclSource) } -func (e *TypeError) FormatError(p xerrors.Printer) error { +func formatError(errMsg string, token *token.Token, colored, inclSource bool) string { var pp printer.Printer - - var colored, inclSource bool - if fep, ok := p.(*FormatErrorPrinter); ok { - colored = fep.Colored - inclSource = fep.InclSource - } - - pos := fmt.Sprintf("[%d:%d] ", e.Token.Position.Line, e.Token.Position.Column) - msg := pp.PrintErrorMessage(fmt.Sprintf("%s%s", pos, e.Error()), colored) + pos := fmt.Sprintf("[%d:%d] ", token.Position.Line, token.Position.Column) + msg := pp.PrintErrorMessage(fmt.Sprintf("%s%s", pos, errMsg), colored) if inclSource { - msg += "\n" + pp.PrintErrorToken(e.Token, colored) + msg += "\n" + pp.PrintErrorToken(token, colored) } - p.Print(msg) - - return nil + return msg } diff --git a/vendor/github.com/goccy/go-yaml/option.go b/vendor/github.com/goccy/go-yaml/option.go index eab5d43..ad43c47 100644 --- a/vendor/github.com/goccy/go-yaml/option.go +++ b/vendor/github.com/goccy/go-yaml/option.go @@ -54,7 +54,6 @@ func Validator(v StructValidator) DecodeOption { func Strict() DecodeOption { return func(d *Decoder) error { d.disallowUnknownField = true - d.disallowDuplicateKey = true return nil } } @@ -69,10 +68,10 @@ func DisallowUnknownField() DecodeOption { } } -// DisallowDuplicateKey causes an error when mapping keys that are duplicates -func DisallowDuplicateKey() DecodeOption { +// AllowDuplicateMapKey ignore syntax error when mapping keys that are duplicates. +func AllowDuplicateMapKey() DecodeOption { return func(d *Decoder) error { - d.disallowDuplicateKey = true + d.allowDuplicateMapKey = true return nil } } diff --git a/vendor/github.com/goccy/go-yaml/parser/color.go b/vendor/github.com/goccy/go-yaml/parser/color.go new file mode 100644 index 0000000..aeee0dc --- /dev/null +++ b/vendor/github.com/goccy/go-yaml/parser/color.go @@ -0,0 +1,28 @@ +package parser + +import "fmt" + +const ( + colorFgHiBlack int = iota + 90 + colorFgHiRed + colorFgHiGreen + colorFgHiYellow + colorFgHiBlue + colorFgHiMagenta + colorFgHiCyan +) + +var colorTable = []int{ + colorFgHiRed, + colorFgHiGreen, + colorFgHiYellow, + colorFgHiBlue, + colorFgHiMagenta, + colorFgHiCyan, +} + +func colorize(idx int, content string) string { + colorIdx := idx % len(colorTable) + color := colorTable[colorIdx] + return fmt.Sprintf("\x1b[1;%dm", color) + content + "\x1b[22;0m" +} diff --git a/vendor/github.com/goccy/go-yaml/parser/context.go b/vendor/github.com/goccy/go-yaml/parser/context.go index 42cc4f8..36ceb58 100644 --- a/vendor/github.com/goccy/go-yaml/parser/context.go +++ b/vendor/github.com/goccy/go-yaml/parser/context.go @@ -9,11 +9,15 @@ import ( // context context at parsing type context struct { - parent *context - idx int + tokenRef *tokenRef + path string + isFlow bool +} + +type tokenRef struct { + tokens []*Token size int - tokens token.Tokens - path string + idx int } var pathSpecialChars = []string{ @@ -36,157 +40,120 @@ func normalizePath(path string) string { return path } -func (c *context) withChild(path string) *context { - ctx := c.copy() - path = normalizePath(path) - ctx.path += fmt.Sprintf(".%s", path) - return ctx +func (c *context) currentToken() *Token { + if c.tokenRef.idx >= c.tokenRef.size { + return nil + } + return c.tokenRef.tokens[c.tokenRef.idx] } -func (c *context) withIndex(idx uint) *context { - ctx := c.copy() - ctx.path += fmt.Sprintf("[%d]", idx) - return ctx +func (c *context) isComment() bool { + return c.currentToken().Type() == token.CommentType } -func (c *context) copy() *context { - return &context{ - parent: c, - idx: c.idx, - size: c.size, - tokens: append(token.Tokens{}, c.tokens...), - path: c.path, +func (c *context) nextToken() *Token { + if c.tokenRef.idx+1 >= c.tokenRef.size { + return nil } + return c.tokenRef.tokens[c.tokenRef.idx+1] } -func (c *context) next() bool { - return c.idx < c.size -} - -func (c *context) previousToken() *token.Token { - if c.idx > 0 { - return c.tokens[c.idx-1] +func (c *context) nextNotCommentToken() *Token { + for i := c.tokenRef.idx + 1; i < c.tokenRef.size; i++ { + tk := c.tokenRef.tokens[i] + if tk.Type() == token.CommentType { + continue + } + return tk } return nil } -func (c *context) insertToken(idx int, tk *token.Token) { - if c.parent != nil { - c.parent.insertToken(idx, tk) - } - if c.size < idx { - return - } - if c.size == idx { - curToken := c.tokens[c.size-1] - tk.Next = curToken - curToken.Prev = tk +func (c *context) isTokenNotFound() bool { + return c.currentToken() == nil +} - c.tokens = append(c.tokens, tk) - c.size = len(c.tokens) - return +func (c *context) withGroup(g *TokenGroup) *context { + ctx := *c + ctx.tokenRef = &tokenRef{ + tokens: g.Tokens, + size: len(g.Tokens), } + return &ctx +} - curToken := c.tokens[idx] - tk.Next = curToken - curToken.Prev = tk - - c.tokens = append(c.tokens[:idx+1], c.tokens[idx:]...) - c.tokens[idx] = tk - c.size = len(c.tokens) +func (c *context) withChild(path string) *context { + ctx := *c + ctx.path = c.path + "." + normalizePath(path) + return &ctx } -func (c *context) currentToken() *token.Token { - if c.idx >= c.size { - return nil - } - return c.tokens[c.idx] +func (c *context) withIndex(idx uint) *context { + ctx := *c + ctx.path = c.path + "[" + fmt.Sprint(idx) + "]" + return &ctx } -func (c *context) nextToken() *token.Token { - if c.idx+1 >= c.size { - return nil - } - return c.tokens[c.idx+1] +func (c *context) withFlow(isFlow bool) *context { + ctx := *c + ctx.isFlow = isFlow + return &ctx } -func (c *context) afterNextToken() *token.Token { - if c.idx+2 >= c.size { - return nil +func newContext() *context { + return &context{ + path: "$", } - return c.tokens[c.idx+2] } -func (c *context) nextNotCommentToken() *token.Token { - for i := c.idx + 1; i < c.size; i++ { - tk := c.tokens[i] - if tk.Type == token.CommentType { - continue - } - return tk +func (c *context) goNext() { + ref := c.tokenRef + if ref.size <= ref.idx+1 { + ref.idx = ref.size + } else { + ref.idx++ } - return nil } -func (c *context) afterNextNotCommentToken() *token.Token { - notCommentTokenCount := 0 - for i := c.idx + 1; i < c.size; i++ { - tk := c.tokens[i] - if tk.Type == token.CommentType { - continue - } - notCommentTokenCount++ - if notCommentTokenCount == 2 { - return tk - } - } - return nil +func (c *context) next() bool { + return c.tokenRef.idx < c.tokenRef.size } -func (c *context) isCurrentCommentToken() bool { - tk := c.currentToken() - if tk == nil { - return false - } - return tk.Type == token.CommentType +func (c *context) insertNullToken(tk *Token) *Token { + nullToken := c.createNullToken(tk) + c.insertToken(nullToken) + c.goNext() + + return nullToken } -func (c *context) progressIgnoreComment(num int) { - if c.parent != nil { - c.parent.progressIgnoreComment(num) - } - if c.size <= c.idx+num { - c.idx = c.size - } else { - c.idx += num - } +func (c *context) createNullToken(base *Token) *Token { + pos := *(base.RawToken().Position) + pos.Column++ + return &Token{Token: token.New("null", "null", &pos)} } -func (c *context) progress(num int) { - if c.isCurrentCommentToken() { +func (c *context) insertToken(tk *Token) { + ref := c.tokenRef + idx := ref.idx + if ref.size < idx { return } - c.progressIgnoreComment(num) -} + if ref.size == idx { + curToken := ref.tokens[ref.size-1] + tk.RawToken().Next = curToken.RawToken() + curToken.RawToken().Prev = tk.RawToken() -func newContext(tokens token.Tokens, mode Mode) *context { - filteredTokens := []*token.Token{} - if mode&ParseComments != 0 { - filteredTokens = tokens - } else { - for _, tk := range tokens { - if tk.Type == token.CommentType { - continue - } - // keep prev/next reference between tokens containing comments - // https://github.com/goccy/go-yaml/issues/254 - filteredTokens = append(filteredTokens, tk) - } - } - return &context{ - idx: 0, - size: len(filteredTokens), - tokens: token.Tokens(filteredTokens), - path: "$", + ref.tokens = append(ref.tokens, tk) + ref.size = len(ref.tokens) + return } + + curToken := ref.tokens[idx] + tk.RawToken().Next = curToken.RawToken() + curToken.RawToken().Prev = tk.RawToken() + + ref.tokens = append(ref.tokens[:idx+1], ref.tokens[idx:]...) + ref.tokens[idx] = tk + ref.size = len(ref.tokens) } diff --git a/vendor/github.com/goccy/go-yaml/parser/node.go b/vendor/github.com/goccy/go-yaml/parser/node.go new file mode 100644 index 0000000..c9ebefc --- /dev/null +++ b/vendor/github.com/goccy/go-yaml/parser/node.go @@ -0,0 +1,248 @@ +package parser + +import ( + "fmt" + + "github.com/goccy/go-yaml/ast" + "github.com/goccy/go-yaml/internal/errors" + "github.com/goccy/go-yaml/token" +) + +func newMappingNode(ctx *context, tk *Token, isFlow bool, values ...*ast.MappingValueNode) (*ast.MappingNode, error) { + node := ast.Mapping(tk.RawToken(), isFlow, values...) + node.SetPath(ctx.path) + return node, nil +} + +func newMappingValueNode(ctx *context, tk *Token, key ast.MapKeyNode, value ast.Node) (*ast.MappingValueNode, error) { + node := ast.MappingValue(tk.RawToken(), key, value) + node.SetPath(ctx.path) + if key.GetToken().Position.Line == value.GetToken().Position.Line { + // originally key was commented, but now that null value has been added, value must be commented. + if err := setLineComment(ctx, value, tk); err != nil { + return nil, err + } + } else { + if err := setLineComment(ctx, key, tk); err != nil { + return nil, err + } + } + return node, nil +} + +func newMappingKeyNode(ctx *context, tk *Token) (*ast.MappingKeyNode, error) { + node := ast.MappingKey(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newAnchorNode(ctx *context, tk *Token) (*ast.AnchorNode, error) { + node := ast.Anchor(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newAliasNode(ctx *context, tk *Token) (*ast.AliasNode, error) { + node := ast.Alias(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newDirectiveNode(ctx *context, tk *Token) (*ast.DirectiveNode, error) { + node := ast.Directive(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newMergeKeyNode(ctx *context, tk *Token) (*ast.MergeKeyNode, error) { + node := ast.MergeKey(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newNullNode(ctx *context, tk *Token) (*ast.NullNode, error) { + node := ast.Null(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newBoolNode(ctx *context, tk *Token) (*ast.BoolNode, error) { + node := ast.Bool(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newIntegerNode(ctx *context, tk *Token) (*ast.IntegerNode, error) { + node := ast.Integer(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newFloatNode(ctx *context, tk *Token) (*ast.FloatNode, error) { + node := ast.Float(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newInfinityNode(ctx *context, tk *Token) (*ast.InfinityNode, error) { + node := ast.Infinity(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newNanNode(ctx *context, tk *Token) (*ast.NanNode, error) { + node := ast.Nan(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newStringNode(ctx *context, tk *Token) (*ast.StringNode, error) { + node := ast.String(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newLiteralNode(ctx *context, tk *Token) (*ast.LiteralNode, error) { + node := ast.Literal(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newTagNode(ctx *context, tk *Token) (*ast.TagNode, error) { + node := ast.Tag(tk.RawToken()) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newSequenceNode(ctx *context, tk *Token, isFlow bool) (*ast.SequenceNode, error) { + node := ast.Sequence(tk.RawToken(), isFlow) + node.SetPath(ctx.path) + if err := setLineComment(ctx, node, tk); err != nil { + return nil, err + } + return node, nil +} + +func newTagDefaultScalarValueNode(ctx *context, tag *token.Token) (ast.ScalarNode, error) { + pos := *(tag.Position) + pos.Column++ + + var ( + tk *Token + node ast.ScalarNode + ) + switch token.ReservedTagKeyword(tag.Value) { + case token.IntegerTag: + tk = &Token{Token: token.New("0", "0", &pos)} + n, err := newIntegerNode(ctx, tk) + if err != nil { + return nil, err + } + node = n + case token.FloatTag: + tk = &Token{Token: token.New("0", "0", &pos)} + n, err := newFloatNode(ctx, tk) + if err != nil { + return nil, err + } + node = n + case token.StringTag, token.BinaryTag, token.TimestampTag: + tk = &Token{Token: token.New("", "", &pos)} + n, err := newStringNode(ctx, tk) + if err != nil { + return nil, err + } + node = n + case token.BooleanTag: + tk = &Token{Token: token.New("false", "false", &pos)} + n, err := newBoolNode(ctx, tk) + if err != nil { + return nil, err + } + node = n + case token.NullTag: + tk = &Token{Token: token.New("null", "null", &pos)} + n, err := newNullNode(ctx, tk) + if err != nil { + return nil, err + } + node = n + default: + return nil, errors.ErrSyntax(fmt.Sprintf("cannot assign default value for %q tag", tag.Value), tag) + } + ctx.insertToken(tk) + ctx.goNext() + return node, nil +} + +func setLineComment(ctx *context, node ast.Node, tk *Token) error { + if tk.LineComment == nil { + return nil + } + comment := ast.CommentGroup([]*token.Token{tk.LineComment}) + comment.SetPath(ctx.path) + if err := node.SetComment(comment); err != nil { + return err + } + return nil +} + +func setHeadComment(cm *ast.CommentGroupNode, value ast.Node) error { + if cm == nil { + return nil + } + switch n := value.(type) { + case *ast.MappingNode: + if len(n.Values) != 0 && value.GetComment() == nil { + cm.SetPath(n.Values[0].GetPath()) + return n.Values[0].SetComment(cm) + } + case *ast.MappingValueNode: + cm.SetPath(n.GetPath()) + return n.SetComment(cm) + } + cm.SetPath(value.GetPath()) + return value.SetComment(cm) +} diff --git a/vendor/github.com/goccy/go-yaml/parser/option.go b/vendor/github.com/goccy/go-yaml/parser/option.go new file mode 100644 index 0000000..3121a64 --- /dev/null +++ b/vendor/github.com/goccy/go-yaml/parser/option.go @@ -0,0 +1,12 @@ +package parser + +// Option represents parser's option. +type Option func(p *parser) + +// AllowDuplicateMapKey allow the use of keys with the same name in the same map, +// but by default, this is not permitted. +func AllowDuplicateMapKey() Option { + return func(p *parser) { + p.allowDuplicateMapKey = true + } +} diff --git a/vendor/github.com/goccy/go-yaml/parser/parser.go b/vendor/github.com/goccy/go-yaml/parser/parser.go index 2bec5fe..5173393 100644 --- a/vendor/github.com/goccy/go-yaml/parser/parser.go +++ b/vendor/github.com/goccy/go-yaml/parser/parser.go @@ -9,735 +9,1090 @@ import ( "github.com/goccy/go-yaml/internal/errors" "github.com/goccy/go-yaml/lexer" "github.com/goccy/go-yaml/token" - "golang.org/x/xerrors" ) -type parser struct{} +type Mode uint -func (p *parser) parseMapping(ctx *context) (*ast.MappingNode, error) { - mapTk := ctx.currentToken() - node := ast.Mapping(mapTk, true) - node.SetPath(ctx.path) - ctx.progress(1) // skip MappingStart token - for ctx.next() { - tk := ctx.currentToken() - if tk.Type == token.MappingEndType { - node.End = tk - return node, nil - } else if tk.Type == token.CollectEntryType { - ctx.progress(1) - continue - } +const ( + ParseComments Mode = 1 << iota // parse comments and add them to AST +) - value, err := p.parseMappingValue(ctx) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse mapping value in mapping node") - } - mvnode, ok := value.(*ast.MappingValueNode) - if !ok { - return nil, errors.ErrSyntax("failed to parse flow mapping node", value.GetToken()) - } - node.Values = append(node.Values, mvnode) - ctx.progress(1) +// ParseBytes parse from byte slice, and returns ast.File +func ParseBytes(bytes []byte, mode Mode, opts ...Option) (*ast.File, error) { + tokens := lexer.Tokenize(string(bytes)) + f, err := Parse(tokens, mode, opts...) + if err != nil { + return nil, err } - return nil, errors.ErrSyntax("unterminated flow mapping", node.GetToken()) + return f, nil } -func (p *parser) parseSequence(ctx *context) (*ast.SequenceNode, error) { - node := ast.Sequence(ctx.currentToken(), true) - node.SetPath(ctx.path) - ctx.progress(1) // skip SequenceStart token - for ctx.next() { - tk := ctx.currentToken() - if tk.Type == token.SequenceEndType { - node.End = tk - break - } else if tk.Type == token.CollectEntryType { - ctx.progress(1) - continue +// Parse parse from token instances, and returns ast.File +func Parse(tokens token.Tokens, mode Mode, opts ...Option) (*ast.File, error) { + if tk := tokens.InvalidToken(); tk != nil { + return nil, errors.ErrSyntax(tk.Error, tk) + } + p, err := newParser(tokens, mode, opts) + if err != nil { + return nil, err + } + f, err := p.parse(newContext()) + if err != nil { + return nil, err + } + return f, nil +} + +// Parse parse from filename, and returns ast.File +func ParseFile(filename string, mode Mode, opts ...Option) (*ast.File, error) { + file, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + f, err := ParseBytes(file, mode, opts...) + if err != nil { + return nil, err + } + f.Name = filename + return f, nil +} + +type parser struct { + tokens []*Token + pathMap map[string]ast.Node + allowDuplicateMapKey bool +} + +func newParser(tokens token.Tokens, mode Mode, opts []Option) (*parser, error) { + filteredTokens := []*token.Token{} + if mode&ParseComments != 0 { + filteredTokens = tokens + } else { + for _, tk := range tokens { + if tk.Type == token.CommentType { + continue + } + // keep prev/next reference between tokens containing comments + // https://github.com/goccy/go-yaml/issues/254 + filteredTokens = append(filteredTokens, tk) } + } + tks, err := createGroupedTokens(token.Tokens(filteredTokens)) + if err != nil { + return nil, err + } + p := &parser{ + tokens: tks, + pathMap: make(map[string]ast.Node), + } + for _, opt := range opts { + opt(p) + } + return p, nil +} - value, err := p.parseToken(ctx.withIndex(uint(len(node.Values))), tk) +func (p *parser) parse(ctx *context) (*ast.File, error) { + file := &ast.File{Docs: []*ast.DocumentNode{}} + for _, token := range p.tokens { + doc, err := p.parseDocument(ctx, token.Group) if err != nil { - return nil, errors.Wrapf(err, "failed to parse sequence value in flow sequence node") + return nil, err } - node.Values = append(node.Values, value) - ctx.progress(1) + file.Docs = append(file.Docs, doc) } - return node, nil + return file, nil } -func (p *parser) parseTag(ctx *context) (*ast.TagNode, error) { - tagToken := ctx.currentToken() - node := ast.Tag(tagToken) - node.SetPath(ctx.path) - ctx.progress(1) // skip tag token +func (p *parser) parseDocument(ctx *context, docGroup *TokenGroup) (*ast.DocumentNode, error) { + if len(docGroup.Tokens) == 0 { + return ast.Document(docGroup.RawToken(), nil), nil + } + + p.pathMap = make(map[string]ast.Node) + var ( - value ast.Node - err error + tokens = docGroup.Tokens + start *token.Token + end *token.Token ) - switch token.ReservedTagKeyword(tagToken.Value) { - case token.MappingTag, - token.OrderedMapTag: - value, err = p.parseMapping(ctx) - case token.IntegerTag, - token.FloatTag, - token.StringTag, - token.BinaryTag, - token.TimestampTag, - token.NullTag: - typ := ctx.currentToken().Type - if typ == token.LiteralType || typ == token.FoldedType { - value, err = p.parseLiteral(ctx) - } else { - value = p.parseScalarValue(ctx.currentToken()) - } - case token.SequenceTag, - token.SetTag: - err = errors.ErrSyntax(fmt.Sprintf("sorry, currently not supported %s tag", tagToken.Value), tagToken) - default: - // custom tag - value, err = p.parseToken(ctx, ctx.currentToken()) + if docGroup.First().Type() == token.DocumentHeaderType { + start = docGroup.First().RawToken() + tokens = tokens[1:] } + if docGroup.Last().Type() == token.DocumentEndType { + end = docGroup.Last().RawToken() + tokens = tokens[:len(tokens)-1] + } + + if len(tokens) == 0 { + return ast.Document(docGroup.RawToken(), nil), nil + } + + body, err := p.parseDocumentBody(ctx.withGroup(&TokenGroup{ + Type: TokenGroupDocumentBody, + Tokens: tokens, + })) if err != nil { - return nil, errors.Wrapf(err, "failed to parse tag value") + return nil, err } - node.Value = value + node := ast.Document(start, body) + node.End = end return node, nil } -func (p *parser) removeLeftSideNewLineCharacter(src string) string { - // CR or LF or CRLF - return strings.TrimLeft(strings.TrimLeft(strings.TrimLeft(src, "\r"), "\n"), "\r\n") -} - -func (p *parser) existsNewLineCharacter(src string) bool { - if strings.Index(src, "\n") > 0 { - return true +func (p *parser) parseDocumentBody(ctx *context) (ast.Node, error) { + node, err := p.parseToken(ctx, ctx.currentToken()) + if err != nil { + return nil, err } - if strings.Index(src, "\r") > 0 { - return true + if ctx.next() { + return nil, errors.ErrSyntax("value is not allowed in this context", ctx.currentToken().RawToken()) } - return false + return node, nil } -func (p *parser) validateMapKey(tk *token.Token) error { - if tk.Type != token.StringType { - return nil +func (p *parser) parseToken(ctx *context, tk *Token) (ast.Node, error) { + switch tk.GroupType() { + case TokenGroupMapKey, TokenGroupMapKeyValue: + return p.parseMap(ctx) + case TokenGroupDirective: + node, err := p.parseDirective(ctx.withGroup(tk.Group), tk.Group) + if err != nil { + return nil, err + } + ctx.goNext() + return node, nil + case TokenGroupAnchor: + node, err := p.parseAnchor(ctx.withGroup(tk.Group), tk.Group) + if err != nil { + return nil, err + } + ctx.goNext() + return node, nil + case TokenGroupAnchorName: + anchor, err := p.parseAnchorName(ctx.withGroup(tk.Group)) + if err != nil { + return nil, err + } + ctx.goNext() + if ctx.isTokenNotFound() { + return nil, errors.ErrSyntax("could not find anchor value", tk.RawToken()) + } + value, err := p.parseToken(ctx, ctx.currentToken()) + if err != nil { + return nil, err + } + anchor.Value = value + return anchor, nil + case TokenGroupAlias: + node, err := p.parseAlias(ctx.withGroup(tk.Group)) + if err != nil { + return nil, err + } + ctx.goNext() + return node, nil + case TokenGroupLiteral, TokenGroupFolded: + node, err := p.parseLiteral(ctx.withGroup(tk.Group)) + if err != nil { + return nil, err + } + ctx.goNext() + return node, nil + case TokenGroupScalarTag: + node, err := p.parseTag(ctx.withGroup(tk.Group)) + if err != nil { + return nil, err + } + ctx.goNext() + return node, nil } - origin := p.removeLeftSideNewLineCharacter(tk.Origin) - if p.existsNewLineCharacter(origin) { - return errors.ErrSyntax("unexpected key name", tk) + switch tk.Type() { + case token.CommentType: + return p.parseComment(ctx) + case token.TagType: + return p.parseTag(ctx) + case token.MappingStartType: + return p.parseFlowMap(ctx) + case token.SequenceStartType: + return p.parseFlowSequence(ctx) + case token.SequenceEntryType: + return p.parseSequence(ctx) + case token.SequenceEndType: + // SequenceEndType is always validated in parseFlowSequence. + // Therefore, if this is found in other cases, it is treated as a syntax error. + return nil, errors.ErrSyntax("could not find '[' character corresponding to ']'", tk.RawToken()) + case token.MappingEndType: + // MappingEndType is always validated in parseFlowMap. + // Therefore, if this is found in other cases, it is treated as a syntax error. + return nil, errors.ErrSyntax("could not find '{' character corresponding to '}'", tk.RawToken()) + case token.MappingValueType: + return nil, errors.ErrSyntax("found an invalid key for this map", tk.RawToken()) + } + node, err := p.parseScalarValue(ctx, tk) + if err != nil { + return nil, err } - return nil -} - -func (p *parser) createNullToken(base *token.Token) *token.Token { - pos := *(base.Position) - pos.Column++ - return token.New("null", "null", &pos) + ctx.goNext() + return node, nil } -func (p *parser) parseMapValue(ctx *context, key ast.MapKeyNode, colonToken *token.Token) (ast.Node, error) { - node, err := p.createMapValueNode(ctx, key, colonToken) - if err != nil { - return nil, errors.Wrapf(err, "failed to create map value node") +func (p *parser) parseScalarValue(ctx *context, tk *Token) (ast.ScalarNode, error) { + if tk.Group != nil { + switch tk.GroupType() { + case TokenGroupAnchor: + return p.parseAnchor(ctx.withGroup(tk.Group), tk.Group) + case TokenGroupAnchorName: + anchor, err := p.parseAnchorName(ctx.withGroup(tk.Group)) + if err != nil { + return nil, err + } + ctx.goNext() + if ctx.isTokenNotFound() { + return nil, errors.ErrSyntax("could not find anchor value", tk.RawToken()) + } + value, err := p.parseToken(ctx, ctx.currentToken()) + if err != nil { + return nil, err + } + anchor.Value = value + return anchor, nil + case TokenGroupAlias: + return p.parseAlias(ctx.withGroup(tk.Group)) + case TokenGroupLiteral, TokenGroupFolded: + return p.parseLiteral(ctx.withGroup(tk.Group)) + case TokenGroupScalarTag: + return p.parseTag(ctx.withGroup(tk.Group)) + default: + return nil, errors.ErrSyntax("unexpected scalar value", tk.RawToken()) + } } - if node != nil && node.GetPath() == "" { - node.SetPath(ctx.path) + switch tk.Type() { + case token.MergeKeyType: + return newMergeKeyNode(ctx, tk) + case token.NullType: + return newNullNode(ctx, tk) + case token.BoolType: + return newBoolNode(ctx, tk) + case token.IntegerType, token.BinaryIntegerType, token.OctetIntegerType, token.HexIntegerType: + return newIntegerNode(ctx, tk) + case token.FloatType: + return newFloatNode(ctx, tk) + case token.InfinityType: + return newInfinityNode(ctx, tk) + case token.NanType: + return newNanNode(ctx, tk) + case token.StringType, token.SingleQuoteType, token.DoubleQuoteType: + return newStringNode(ctx, tk) + case token.TagType: + // this case applies when it is a scalar tag and its value does not exist. + // Examples of cases where the value does not exist include cases like `key: !!str,` or `!!str : value`. + return p.parseScalarTag(ctx) } - return node, nil + return nil, errors.ErrSyntax("unexpected scalar value type", tk.RawToken()) } -func (p *parser) createMapValueNode(ctx *context, key ast.MapKeyNode, colonToken *token.Token) (ast.Node, error) { - tk := ctx.currentToken() - if tk == nil { - nullToken := p.createNullToken(colonToken) - ctx.insertToken(ctx.idx, nullToken) - return ast.Null(nullToken), nil +func (p *parser) parseFlowMap(ctx *context) (*ast.MappingNode, error) { + node, err := newMappingNode(ctx, ctx.currentToken(), true) + if err != nil { + return nil, err } - var comment *ast.CommentGroupNode - if tk.Type == token.CommentType { - comment = p.parseCommentOnly(ctx) - if comment != nil { - comment.SetPath(ctx.withChild(key.GetToken().Value).path) + ctx.goNext() // skip MappingStart token + + isFirst := true + for ctx.next() { + tk := ctx.currentToken() + if tk.Type() == token.MappingEndType { + node.End = tk.RawToken() + break } - tk = ctx.currentToken() - } - if tk.Position.Column == key.GetToken().Position.Column && tk.Type == token.StringType { - // in this case, - // ---- - // key: - // next - nullToken := p.createNullToken(colonToken) - ctx.insertToken(ctx.idx, nullToken) - nullNode := ast.Null(nullToken) + if tk.Type() == token.CollectEntryType { + ctx.goNext() + } else if !isFirst { + return nil, errors.ErrSyntax("',' or '}' must be specified", tk.RawToken()) + } - if comment != nil { - nullNode.SetComment(comment) - } else { - // If there is a comment, it is already bound to the key node, - // so remove the comment from the key to bind it to the null value. - keyComment := key.GetComment() - if keyComment != nil { - if err := key.SetComment(nil); err != nil { + if tk := ctx.currentToken(); tk.Type() == token.MappingEndType { + // this case is here: "{ elem, }". + // In this case, ignore the last element and break mapping parsing. + node.End = tk.RawToken() + break + } + + mapKeyTk := ctx.currentToken() + switch mapKeyTk.GroupType() { + case TokenGroupMapKeyValue: + value, err := p.parseMapKeyValue(ctx.withGroup(mapKeyTk.Group), mapKeyTk.Group) + if err != nil { + return nil, err + } + node.Values = append(node.Values, value) + ctx.goNext() + case TokenGroupMapKey: + key, err := p.parseMapKey(ctx.withGroup(mapKeyTk.Group), mapKeyTk.Group) + if err != nil { + return nil, err + } + ctx := ctx.withChild(p.mapKeyText(key)) + colonTk := mapKeyTk.Group.Last() + if p.isFlowMapDelim(ctx.nextToken()) { + value, err := newNullNode(ctx, ctx.insertNullToken(colonTk)) + if err != nil { return nil, err } - nullNode.SetComment(keyComment) + mapValue, err := newMappingValueNode(ctx, colonTk, key, value) + if err != nil { + return nil, err + } + node.Values = append(node.Values, mapValue) + ctx.goNext() + } else { + ctx.goNext() + if ctx.isTokenNotFound() { + return nil, errors.ErrSyntax("could not find map value", colonTk.RawToken()) + } + value, err := p.parseToken(ctx, ctx.currentToken()) + if err != nil { + return nil, err + } + mapValue, err := newMappingValueNode(ctx, colonTk, key, value) + if err != nil { + return nil, err + } + node.Values = append(node.Values, mapValue) + } + default: + if !p.isFlowMapDelim(ctx.nextToken()) { + return nil, errors.ErrSyntax("could not find flow map content", mapKeyTk.RawToken()) + } + key, err := p.parseScalarValue(ctx, mapKeyTk) + if err != nil { + return nil, err + } + value, err := newNullNode(ctx, ctx.insertNullToken(mapKeyTk)) + if err != nil { + return nil, err + } + mapValue, err := newMappingValueNode(ctx, mapKeyTk, key, value) + if err != nil { + return nil, err } + node.Values = append(node.Values, mapValue) + ctx.goNext() } - return nullNode, nil + isFirst = false } + if node.End == nil { + return nil, errors.ErrSyntax("could not find flow mapping end token '}'", node.Start) + } + ctx.goNext() // skip mapping end token. + return node, nil +} - if tk.Position.Column < key.GetToken().Position.Column { - // in this case, - // ---- - // key: - // next - nullToken := p.createNullToken(colonToken) - ctx.insertToken(ctx.idx, nullToken) - nullNode := ast.Null(nullToken) - if comment != nil { - nullNode.SetComment(comment) - } - return nullNode, nil +func (p *parser) isFlowMapDelim(tk *Token) bool { + return tk.Type() == token.MappingEndType || tk.Type() == token.CollectEntryType +} + +func (p *parser) parseMap(ctx *context) (*ast.MappingNode, error) { + keyTk := ctx.currentToken() + if keyTk.Group == nil { + return nil, errors.ErrSyntax("unexpected map key", keyTk.RawToken()) } + var keyValueNode *ast.MappingValueNode + if keyTk.GroupType() == TokenGroupMapKeyValue { + node, err := p.parseMapKeyValue(ctx.withGroup(keyTk.Group), keyTk.Group) + if err != nil { + return nil, err + } + keyValueNode = node + ctx.goNext() + if err := p.validateMapKeyValueNextToken(ctx, keyTk, ctx.currentToken()); err != nil { + return nil, err + } + } else { + key, err := p.parseMapKey(ctx.withGroup(keyTk.Group), keyTk.Group) + if err != nil { + return nil, err + } + ctx.goNext() - value, err := p.parseToken(ctx, ctx.currentToken()) + valueTk := ctx.currentToken() + if keyTk.Line() == valueTk.Line() && valueTk.Type() == token.SequenceEntryType { + return nil, errors.ErrSyntax("block sequence entries are not allowed in this context", valueTk.RawToken()) + } + ctx := ctx.withChild(p.mapKeyText(key)) + value, err := p.parseMapValue(ctx, key, keyTk.Group.Last()) + if err != nil { + return nil, err + } + node, err := newMappingValueNode(ctx, keyTk.Group.Last(), key, value) + if err != nil { + return nil, err + } + keyValueNode = node + } + mapNode, err := newMappingNode(ctx, &Token{Token: keyValueNode.GetToken()}, false, keyValueNode) if err != nil { - return nil, errors.Wrapf(err, "failed to parse mapping 'value' node") + return nil, err } - if comment != nil { - value.SetComment(comment) + var tk *Token + if ctx.isComment() { + tk = ctx.nextNotCommentToken() + } else { + tk = ctx.currentToken() } - return value, nil + for tk.Column() == keyTk.Column() { + typ := tk.Type() + if ctx.isFlow && typ == token.SequenceEndType { + // [ + // key: value + // ] <= + break + } + if !p.isMapToken(tk) { + return nil, errors.ErrSyntax("non-map value is specified", tk.RawToken()) + } + cm := p.parseHeadComment(ctx) + if typ == token.MappingEndType { + // a: { + // b: c + // } <= + ctx.goNext() + break + } + node, err := p.parseMap(ctx) + if err != nil { + return nil, err + } + if len(node.Values) != 0 { + if err := setHeadComment(cm, node.Values[0]); err != nil { + return nil, err + } + } + mapNode.Values = append(mapNode.Values, node.Values...) + if node.FootComment != nil { + mapNode.Values[len(mapNode.Values)-1].FootComment = node.FootComment + } + tk = ctx.currentToken() + } + if ctx.isComment() { + if keyTk.Column() <= ctx.currentToken().Column() { + // If the comment is in the same or deeper column as the last element column in map value, + // treat it as a footer comment for the last element. + if len(mapNode.Values) == 1 { + mapNode.Values[0].FootComment = p.parseFootComment(ctx, keyTk.Column()) + mapNode.Values[0].FootComment.SetPath(mapNode.Values[0].Key.GetPath()) + } else { + mapNode.FootComment = p.parseFootComment(ctx, keyTk.Column()) + mapNode.FootComment.SetPath(mapNode.GetPath()) + } + } + } + return mapNode, nil } -func (p *parser) validateMapValue(ctx *context, key, value ast.Node) error { - keyColumn := key.GetToken().Position.Column - valueColumn := value.GetToken().Position.Column - if keyColumn != valueColumn { +func (p *parser) validateMapKeyValueNextToken(ctx *context, keyTk, tk *Token) error { + if tk == nil { return nil } - if value.Type() != ast.StringType { + if tk.Column() <= keyTk.Column() { return nil } - ntk := ctx.nextToken() - if ntk == nil || (ntk.Type != token.MappingValueType && ntk.Type != token.SequenceEntryType) { - return errors.ErrSyntax("could not found expected ':' token", value.GetToken()) + if ctx.isFlow && tk.Type() == token.CollectEntryType { + return nil } - return nil + // a: b + // c <= this token is invalid. + return errors.ErrSyntax("value is not allowed in this context. map key-value is pre-defined", tk.RawToken()) } -func (p *parser) parseMappingValue(ctx *context) (ast.Node, error) { - key, err := p.parseMapKey(ctx) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse map key") +func (p *parser) isMapToken(tk *Token) bool { + if tk.Group == nil { + return tk.Type() == token.MappingStartType || tk.Type() == token.MappingEndType } - keyText := key.GetToken().Value - key.SetPath(ctx.withChild(keyText).path) - if err := p.validateMapKey(key.GetToken()); err != nil { - return nil, errors.Wrapf(err, "validate mapping key error") - } - ctx.progress(1) // progress to mapping value token - tk := ctx.currentToken() // get mapping value token - if tk == nil { - return nil, errors.ErrSyntax("unexpected map", key.GetToken()) - } - ctx.progress(1) // progress to value token - if err := p.setSameLineCommentIfExists(ctx.withChild(keyText), key); err != nil { - return nil, errors.Wrapf(err, "failed to set same line comment to node") + g := tk.Group + return g.Type == TokenGroupMapKey || g.Type == TokenGroupMapKeyValue +} + +func (p *parser) parseMapKeyValue(ctx *context, g *TokenGroup) (*ast.MappingValueNode, error) { + if g.Type != TokenGroupMapKeyValue { + return nil, errors.ErrSyntax("unexpected map key-value pair", g.RawToken()) } - if key.GetComment() != nil { - // if current token is comment, GetComment() is not nil. - // then progress to value token - ctx.progressIgnoreComment(1) + if g.First().Group == nil { + return nil, errors.ErrSyntax("unexpected map key", g.RawToken()) } - - value, err := p.parseMapValue(ctx.withChild(keyText), key, tk) + keyGroup := g.First().Group + key, err := p.parseMapKey(ctx.withGroup(keyGroup), keyGroup) if err != nil { - return nil, errors.Wrapf(err, "failed to parse map value") + return nil, err } - if err := p.validateMapValue(ctx, key, value); err != nil { - return nil, errors.Wrapf(err, "failed to validate map value") + value, err := p.parseToken(ctx.withChild(p.mapKeyText(key)), g.Last()) + if err != nil { + return nil, err } + return newMappingValueNode(ctx, keyGroup.Last(), key, value) +} - mvnode := ast.MappingValue(tk, key, value) - mvnode.SetPath(ctx.withChild(keyText).path) - node := ast.Mapping(tk, false, mvnode) - node.SetPath(ctx.withChild(keyText).path) +func (p *parser) parseMapKey(ctx *context, g *TokenGroup) (ast.MapKeyNode, error) { + if g.Type != TokenGroupMapKey { + return nil, errors.ErrSyntax("unexpected map key", g.RawToken()) + } + if g.First().Type() == token.MappingKeyType { + mapKeyTk := g.First() + if mapKeyTk.Group != nil { + ctx = ctx.withGroup(mapKeyTk.Group) + } + key, err := newMappingKeyNode(ctx, mapKeyTk) + if err != nil { + return nil, err + } + ctx.goNext() // skip mapping key token + if ctx.isTokenNotFound() { + return nil, errors.ErrSyntax("could not find value for mapping key", mapKeyTk.RawToken()) + } - ntk := ctx.nextNotCommentToken() - antk := ctx.afterNextNotCommentToken() - for antk != nil && antk.Type == token.MappingValueType && - ntk.Position.Column == key.GetToken().Position.Column { - ctx.progressIgnoreComment(1) - value, err := p.parseToken(ctx, ctx.currentToken()) + scalar, err := p.parseScalarValue(ctx, ctx.currentToken()) if err != nil { - return nil, errors.Wrapf(err, "failed to parse mapping node") - } - switch value.Type() { - case ast.MappingType: - c := value.(*ast.MappingNode) - comment := c.GetComment() - for idx, v := range c.Values { - if idx == 0 && comment != nil { - if err := v.SetComment(comment); err != nil { - return nil, errors.Wrapf(err, "failed to set comment token to node") - } - } - node.Values = append(node.Values, v) - } - case ast.MappingValueType: - node.Values = append(node.Values, value.(*ast.MappingValueNode)) - default: - return nil, xerrors.Errorf("failed to parse mapping value node node is %s", value.Type()) + return nil, err + } + key.Value = scalar + keyText := p.mapKeyText(scalar) + keyPath := ctx.withChild(keyText).path + key.SetPath(keyPath) + if err := p.validateMapKey(key.GetToken(), keyPath); err != nil { + return nil, err } - ntk = ctx.nextNotCommentToken() - antk = ctx.afterNextNotCommentToken() + p.pathMap[keyPath] = key + return key, nil } - if len(node.Values) == 1 { - mapKeyCol := mvnode.Key.GetToken().Position.Column - commentTk := ctx.nextToken() - if commentTk != nil && commentTk.Type == token.CommentType && mapKeyCol <= commentTk.Position.Column { - // If the comment is in the same or deeper column as the last element column in map value, - // treat it as a footer comment for the last element. - comment := p.parseFootComment(ctx, mapKeyCol) - mvnode.FootComment = comment + if g.Last().Type() != token.MappingValueType { + return nil, errors.ErrSyntax("expected map key-value delimiter ':'", g.Last().RawToken()) + } + + scalar, err := p.parseScalarValue(ctx, g.First()) + if err != nil { + return nil, err + } + key, ok := scalar.(ast.MapKeyNode) + if !ok { + return nil, errors.ErrSyntax("cannot take map-key node", scalar.GetToken()) + } + keyText := p.mapKeyText(key) + keyPath := ctx.withChild(keyText).path + key.SetPath(keyPath) + if err := p.validateMapKey(key.GetToken(), keyPath); err != nil { + return nil, err + } + p.pathMap[keyPath] = key + return key, nil +} + +func (p *parser) validateMapKey(tk *token.Token, keyPath string) error { + if !p.allowDuplicateMapKey { + if n, exists := p.pathMap[keyPath]; exists { + pos := n.GetToken().Position + return errors.ErrSyntax( + fmt.Sprintf("mapping key %q already defined at [%d:%d]", tk.Value, pos.Line, pos.Column), + tk, + ) } - return mvnode, nil } - mapCol := node.GetToken().Position.Column - commentTk := ctx.nextToken() - if commentTk != nil && commentTk.Type == token.CommentType && mapCol <= commentTk.Position.Column { - // If the comment is in the same or deeper column as the last element column in map value, - // treat it as a footer comment for the last element. - comment := p.parseFootComment(ctx, mapCol) - node.FootComment = comment + if tk.Type != token.StringType { + return nil } - return node, nil + origin := p.removeLeftSideNewLineCharacter(tk.Origin) + if p.existsNewLineCharacter(origin) { + return errors.ErrSyntax("unexpected key name", tk) + } + return nil +} + +func (p *parser) removeLeftSideNewLineCharacter(src string) string { + // CR or LF or CRLF + return strings.TrimLeft(strings.TrimLeft(strings.TrimLeft(src, "\r"), "\n"), "\r\n") +} + +func (p *parser) existsNewLineCharacter(src string) bool { + if strings.Index(src, "\n") > 0 { + return true + } + if strings.Index(src, "\r") > 0 { + return true + } + return false } -func (p *parser) parseSequenceEntry(ctx *context) (*ast.SequenceNode, error) { +func (p *parser) mapKeyText(n ast.Node) string { + if n == nil { + return "" + } + switch nn := n.(type) { + case *ast.MappingKeyNode: + return p.mapKeyText(nn.Value) + case *ast.TagNode: + return p.mapKeyText(nn.Value) + case *ast.AnchorNode: + return p.mapKeyText(nn.Value) + case *ast.AliasNode: + return p.mapKeyText(nn.Value) + } + return n.GetToken().Value +} + +func (p *parser) parseMapValue(ctx *context, key ast.MapKeyNode, colonTk *Token) (ast.Node, error) { tk := ctx.currentToken() - sequenceNode := ast.Sequence(tk, false) - sequenceNode.SetPath(ctx.path) - curColumn := tk.Position.Column - for tk.Type == token.SequenceEntryType { - ctx.progress(1) // skip sequence token - tk = ctx.currentToken() - if tk == nil { - return nil, errors.ErrSyntax("empty sequence entry", ctx.previousToken()) - } - var comment *ast.CommentGroupNode - if tk.Type == token.CommentType { - comment = p.parseCommentOnly(ctx) - tk = ctx.currentToken() - if tk.Type == token.SequenceEntryType { - ctx.progress(1) // skip sequence token - } + if tk == nil { + return newNullNode(ctx, ctx.insertNullToken(colonTk)) + } + + if ctx.isComment() { + tk = ctx.nextNotCommentToken() + } + keyCol := key.GetToken().Position.Column + keyLine := key.GetToken().Position.Line + + if tk.Column() != keyCol && tk.Line() == keyLine && (tk.GroupType() == TokenGroupMapKey || tk.GroupType() == TokenGroupMapKeyValue) { + // a: b: + // ^ + // + // a: b: c + // ^ + return nil, errors.ErrSyntax("mapping value is not allowed in this context", tk.RawToken()) + } + + if tk.Column() == keyCol && p.isMapToken(tk) { + // in this case, + // ---- + // key: + // next + return newNullNode(ctx, ctx.insertNullToken(colonTk)) + } + + if tk.Line() == keyLine && tk.GroupType() == TokenGroupAnchorName && + ctx.nextToken().Column() == keyCol && p.isMapToken(ctx.nextToken()) { + // in this case, + // ---- + // key: &anchor + // next + group := &TokenGroup{ + Type: TokenGroupAnchor, + Tokens: []*Token{tk, ctx.createNullToken(tk)}, } - value, err := p.parseToken(ctx.withIndex(uint(len(sequenceNode.Values))), ctx.currentToken()) + anchor, err := p.parseAnchor(ctx.withGroup(group), group) if err != nil { - return nil, errors.Wrapf(err, "failed to parse sequence") + return nil, err } - if comment != nil { - comment.SetPath(ctx.withIndex(uint(len(sequenceNode.Values))).path) - sequenceNode.ValueHeadComments = append(sequenceNode.ValueHeadComments, comment) - } else { - sequenceNode.ValueHeadComments = append(sequenceNode.ValueHeadComments, nil) - } - sequenceNode.Values = append(sequenceNode.Values, value) - tk = ctx.nextNotCommentToken() - if tk == nil { - break - } - if tk.Type != token.SequenceEntryType { - break + ctx.goNext() + return anchor, nil + } + + if tk.Column() <= keyCol && tk.GroupType() == TokenGroupAnchorName { + // key: + // &anchor + return nil, errors.ErrSyntax("anchor is not allowed in this context", tk.RawToken()) + } + + if tk.Column() < keyCol { + // in this case, + // ---- + // key: + // next + return newNullNode(ctx, ctx.insertNullToken(colonTk)) + } + + if tk.Line() == keyLine && tk.GroupType() == TokenGroupAnchorName && + ctx.nextToken().Column() < keyCol { + // in this case, + // ---- + // key: &anchor + // next + group := &TokenGroup{ + Type: TokenGroupAnchor, + Tokens: []*Token{tk, ctx.createNullToken(tk)}, } - if tk.Position.Column != curColumn { - break + anchor, err := p.parseAnchor(ctx.withGroup(group), group) + if err != nil { + return nil, err } - ctx.progressIgnoreComment(1) + ctx.goNext() + return anchor, nil } - commentTk := ctx.nextToken() - if commentTk != nil && commentTk.Type == token.CommentType && curColumn <= commentTk.Position.Column { - // If the comment is in the same or deeper column as the last element column in sequence value, - // treat it as a footer comment for the last element. - comment := p.parseFootComment(ctx, curColumn) - sequenceNode.FootComment = comment + + value, err := p.parseToken(ctx, ctx.currentToken()) + if err != nil { + return nil, err } - return sequenceNode, nil + return value, nil } -func (p *parser) parseAnchor(ctx *context) (*ast.AnchorNode, error) { - tk := ctx.currentToken() - anchor := ast.Anchor(tk) - anchor.SetPath(ctx.path) - ntk := ctx.nextToken() - if ntk == nil { - return nil, errors.ErrSyntax("unexpected anchor. anchor name is undefined", tk) - } - ctx.progress(1) // skip anchor token - name, err := p.parseToken(ctx, ctx.currentToken()) +func (p *parser) parseAnchor(ctx *context, g *TokenGroup) (*ast.AnchorNode, error) { + anchorNameGroup := g.First().Group + anchor, err := p.parseAnchorName(ctx.withGroup(anchorNameGroup)) if err != nil { - return nil, errors.Wrapf(err, "failed to parser anchor name node") + return nil, err } - anchor.Name = name - ntk = ctx.nextToken() - if ntk == nil { - return nil, errors.ErrSyntax("unexpected anchor. anchor value is undefined", ctx.currentToken()) + ctx.goNext() + if ctx.isTokenNotFound() { + return nil, errors.ErrSyntax("could not find anchor value", anchor.GetToken()) } - ctx.progress(1) + value, err := p.parseToken(ctx, ctx.currentToken()) if err != nil { - return nil, errors.Wrapf(err, "failed to parser anchor name node") + return nil, err } anchor.Value = value return anchor, nil } -func (p *parser) parseAlias(ctx *context) (*ast.AliasNode, error) { - tk := ctx.currentToken() - alias := ast.Alias(tk) - alias.SetPath(ctx.path) - ntk := ctx.nextToken() - if ntk == nil { - return nil, errors.ErrSyntax("unexpected alias. alias name is undefined", tk) - } - ctx.progress(1) // skip alias token - name, err := p.parseToken(ctx, ctx.currentToken()) +func (p *parser) parseAnchorName(ctx *context) (*ast.AnchorNode, error) { + anchor, err := newAnchorNode(ctx, ctx.currentToken()) if err != nil { - return nil, errors.Wrapf(err, "failed to parser alias name node") - } - alias.Value = name - return alias, nil -} - -func (p *parser) parseMapKey(ctx *context) (ast.MapKeyNode, error) { - tk := ctx.currentToken() - if value := p.parseScalarValue(tk); value != nil { - return value, nil + return nil, err } - switch tk.Type { - case token.MergeKeyType: - return ast.MergeKey(tk), nil - case token.MappingKeyType: - return p.parseMappingKey(ctx) - } - return nil, errors.ErrSyntax("unexpected mapping key", tk) -} - -func (p *parser) parseStringValue(tk *token.Token) *ast.StringNode { - switch tk.Type { - case token.StringType, - token.SingleQuoteType, - token.DoubleQuoteType: - return ast.String(tk) + ctx.goNext() + if ctx.isTokenNotFound() { + return nil, errors.ErrSyntax("could not find anchor value", anchor.GetToken()) } - return nil -} -func (p *parser) parseScalarValueWithComment(ctx *context, tk *token.Token) (ast.ScalarNode, error) { - node := p.parseScalarValue(tk) - if node == nil { - return nil, nil + anchorName, err := p.parseScalarValue(ctx, ctx.currentToken()) + if err != nil { + return nil, err } - node.SetPath(ctx.path) - if p.isSameLineComment(ctx.nextToken(), node) { - ctx.progress(1) - if err := p.setSameLineCommentIfExists(ctx, node); err != nil { - return nil, errors.Wrapf(err, "failed to set same line comment to node") - } + if anchorName == nil { + return nil, errors.ErrSyntax("unexpected anchor. anchor name is not scalar value", ctx.currentToken().RawToken()) } - return node, nil + anchor.Name = anchorName + return anchor, nil } -func (p *parser) parseScalarValue(tk *token.Token) ast.ScalarNode { - if node := p.parseStringValue(tk); node != nil { - return node +func (p *parser) parseAlias(ctx *context) (*ast.AliasNode, error) { + alias, err := newAliasNode(ctx, ctx.currentToken()) + if err != nil { + return nil, err } - switch tk.Type { - case token.NullType: - return ast.Null(tk) - case token.BoolType: - return ast.Bool(tk) - case token.IntegerType, - token.BinaryIntegerType, - token.OctetIntegerType, - token.HexIntegerType: - return ast.Integer(tk) - case token.FloatType: - return ast.Float(tk) - case token.InfinityType: - return ast.Infinity(tk) - case token.NanType: - return ast.Nan(tk) + ctx.goNext() + if ctx.isTokenNotFound() { + return nil, errors.ErrSyntax("could not find alias value", alias.GetToken()) } - return nil -} -func (p *parser) parseDirective(ctx *context) (*ast.DirectiveNode, error) { - node := ast.Directive(ctx.currentToken()) - ctx.progress(1) // skip directive token - value, err := p.parseToken(ctx, ctx.currentToken()) + aliasName, err := p.parseScalarValue(ctx, ctx.currentToken()) if err != nil { - return nil, errors.Wrapf(err, "failed to parse directive value") + return nil, err } - node.Value = value - ctx.progress(1) - tk := ctx.currentToken() - if tk == nil { - // Since current token is nil, use the previous token to specify - // the syntax error location. - return nil, errors.ErrSyntax("unexpected directive value. document not started", ctx.previousToken()) + if aliasName == nil { + return nil, errors.ErrSyntax("unexpected alias. alias name is not scalar value", ctx.currentToken().RawToken()) } - if tk.Type != token.DocumentHeaderType { - return nil, errors.ErrSyntax("unexpected directive value. document not started", ctx.currentToken()) - } - return node, nil + alias.Value = aliasName + return alias, nil } func (p *parser) parseLiteral(ctx *context) (*ast.LiteralNode, error) { - node := ast.Literal(ctx.currentToken()) - ctx.progress(1) // skip literal/folded token + node, err := newLiteralNode(ctx, ctx.currentToken()) + if err != nil { + return nil, err + } + ctx.goNext() // skip literal/folded token tk := ctx.currentToken() - var comment *ast.CommentGroupNode - if tk.Type == token.CommentType { - comment = p.parseCommentOnly(ctx) - comment.SetPath(ctx.path) - if err := node.SetComment(comment); err != nil { - return nil, errors.Wrapf(err, "failed to set comment to literal") + if tk == nil { + value, err := newStringNode(ctx, &Token{Token: token.New("", "", node.Start.Position)}) + if err != nil { + return nil, err } - tk = ctx.currentToken() + node.Value = value + return node, nil } value, err := p.parseToken(ctx, tk) if err != nil { - return nil, errors.Wrapf(err, "failed to parse literal/folded value") + return nil, err } - snode, ok := value.(*ast.StringNode) + str, ok := value.(*ast.StringNode) if !ok { return nil, errors.ErrSyntax("unexpected token. required string token", value.GetToken()) } - node.Value = snode + node.Value = str return node, nil } -func (p *parser) isSameLineComment(tk *token.Token, node ast.Node) bool { - if tk == nil { - return false +func (p *parser) parseScalarTag(ctx *context) (*ast.TagNode, error) { + tag, err := p.parseTag(ctx) + if err != nil { + return nil, err } - if tk.Type != token.CommentType { - return false + if tag.Value == nil { + return nil, errors.ErrSyntax("specified not scalar tag", tag.GetToken()) } - return tk.Position.Line == node.GetToken().Position.Line + if _, ok := tag.Value.(ast.ScalarNode); !ok { + return nil, errors.ErrSyntax("specified not scalar tag", tag.GetToken()) + } + return tag, nil } -func (p *parser) setSameLineCommentIfExists(ctx *context, node ast.Node) error { - tk := ctx.currentToken() - if !p.isSameLineComment(tk, node) { - return nil - } - comment := ast.CommentGroup([]*token.Token{tk}) - comment.SetPath(ctx.path) - if err := node.SetComment(comment); err != nil { - return errors.Wrapf(err, "failed to set comment token to ast.Node") +func (p *parser) parseTag(ctx *context) (*ast.TagNode, error) { + tagTk := ctx.currentToken() + tagRawTk := tagTk.RawToken() + node, err := newTagNode(ctx, tagTk) + if err != nil { + return nil, err } - return nil -} + ctx.goNext() -func (p *parser) parseDocument(ctx *context) (*ast.DocumentNode, error) { - startTk := ctx.currentToken() - ctx.progress(1) // skip document header token - body, err := p.parseToken(ctx, ctx.currentToken()) + comment := p.parseHeadComment(ctx) + value, err := p.parseTagValue(ctx, tagRawTk, ctx.currentToken()) if err != nil { - return nil, errors.Wrapf(err, "failed to parse document body") + return nil, err } - node := ast.Document(startTk, body) - if ntk := ctx.nextToken(); ntk != nil && ntk.Type == token.DocumentEndType { - node.End = ntk - ctx.progress(1) + if err := setHeadComment(comment, value); err != nil { + return nil, err } + node.Value = value return node, nil } -func (p *parser) parseCommentOnly(ctx *context) *ast.CommentGroupNode { - commentTokens := []*token.Token{} - for { - tk := ctx.currentToken() - if tk == nil { - break +func (p *parser) parseTagValue(ctx *context, tagRawTk *token.Token, tk *Token) (ast.Node, error) { + if tk == nil { + return newNullNode(ctx, ctx.createNullToken(&Token{Token: tagRawTk})) + } + switch token.ReservedTagKeyword(tagRawTk.Value) { + case token.MappingTag, token.SetTag: + if !p.isMapToken(tk) { + return nil, errors.ErrSyntax("could not find map", tk.RawToken()) } - if tk.Type != token.CommentType { - break + if tk.Type() == token.MappingStartType { + return p.parseFlowMap(ctx) + } + return p.parseMap(ctx) + case token.IntegerTag, token.FloatTag, token.StringTag, token.BinaryTag, token.TimestampTag, token.BooleanTag, token.NullTag: + if tk.GroupType() == TokenGroupLiteral || tk.GroupType() == TokenGroupFolded { + return p.parseLiteral(ctx.withGroup(tk.Group)) + } else if tk.Type() == token.CollectEntryType || tk.Type() == token.MappingValueType { + return newTagDefaultScalarValueNode(ctx, tagRawTk) } - commentTokens = append(commentTokens, tk) - ctx.progressIgnoreComment(1) // skip comment token + scalar, err := p.parseScalarValue(ctx, tk) + if err != nil { + return nil, err + } + ctx.goNext() + return scalar, nil + case token.SequenceTag, token.OrderedMapTag: + if tk.Type() == token.SequenceStartType { + return p.parseFlowSequence(ctx) + } + return p.parseSequence(ctx) } - return ast.CommentGroup(commentTokens) + if strings.HasPrefix(tagRawTk.Value, "!!") { + return nil, errors.ErrSyntax(fmt.Sprintf("unknown secondary tag name %q specified", tagRawTk.Value), tagRawTk) + } + return p.parseToken(ctx, tk) } -func (p *parser) parseFootComment(ctx *context, col int) *ast.CommentGroupNode { - commentTokens := []*token.Token{} - for { - ctx.progressIgnoreComment(1) - commentTokens = append(commentTokens, ctx.currentToken()) +func (p *parser) parseFlowSequence(ctx *context) (*ast.SequenceNode, error) { + node, err := newSequenceNode(ctx, ctx.currentToken(), true) + if err != nil { + return nil, err + } + ctx.goNext() // skip SequenceStart token - nextTk := ctx.nextToken() - if nextTk == nil { + isFirst := true + for ctx.next() { + tk := ctx.currentToken() + if tk.Type() == token.SequenceEndType { + node.End = tk.RawToken() break } - if nextTk.Type != token.CommentType { + + if tk.Type() == token.CollectEntryType { + ctx.goNext() + } else if !isFirst { + return nil, errors.ErrSyntax("',' or ']' must be specified", tk.RawToken()) + } + + if tk := ctx.currentToken(); tk.Type() == token.SequenceEndType { + // this case is here: "[ elem, ]". + // In this case, ignore the last element and break sequence parsing. + node.End = tk.RawToken() break } - if col > nextTk.Position.Column { + + if ctx.isTokenNotFound() { break } - } - return ast.CommentGroup(commentTokens) -} -func (p *parser) parseComment(ctx *context) (ast.Node, error) { - group := p.parseCommentOnly(ctx) - node, err := p.parseToken(ctx, ctx.currentToken()) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse node after comment") - } - if node == nil { - return group, nil + value, err := p.parseToken(ctx.withIndex(uint(len(node.Values))).withFlow(true), ctx.currentToken()) + if err != nil { + return nil, err + } + node.Values = append(node.Values, value) + isFirst = false } - group.SetPath(node.GetPath()) - if err := node.SetComment(group); err != nil { - return nil, errors.Wrapf(err, "failed to set comment token to node") + if node.End == nil { + return nil, errors.ErrSyntax("sequence end token ']' not found", node.Start) } + ctx.goNext() // skip sequence end token. return node, nil } -func (p *parser) parseMappingKey(ctx *context) (*ast.MappingKeyNode, error) { - keyTk := ctx.currentToken() - node := ast.MappingKey(keyTk) - node.SetPath(ctx.path) - ctx.progress(1) // skip mapping key token - value, err := p.parseToken(ctx.withChild(keyTk.Value), ctx.currentToken()) +func (p *parser) parseSequence(ctx *context) (*ast.SequenceNode, error) { + seqTk := ctx.currentToken() + seqNode, err := newSequenceNode(ctx, seqTk, false) if err != nil { - return nil, errors.Wrapf(err, "failed to parse map key") + return nil, err } - node.Value = value - return node, nil -} -func (p *parser) parseToken(ctx *context, tk *token.Token) (ast.Node, error) { - node, err := p.createNodeFromToken(ctx, tk) - if err != nil { - return nil, errors.Wrapf(err, "failed to create node from token") + tk := seqTk + for tk.Type() == token.SequenceEntryType && tk.Column() == seqTk.Column() { + seqTk := tk + comment := p.parseHeadComment(ctx) + ctx.goNext() // skip sequence entry token + + value, err := p.parseSequenceValue(ctx.withIndex(uint(len(seqNode.Values))), seqTk) + if err != nil { + return nil, err + } + seqNode.ValueHeadComments = append(seqNode.ValueHeadComments, comment) + seqNode.Values = append(seqNode.Values, value) + + if ctx.isComment() { + tk = ctx.nextNotCommentToken() + } else { + tk = ctx.currentToken() + } } - if node != nil && node.GetPath() == "" { - node.SetPath(ctx.path) + if ctx.isComment() { + if seqTk.Column() <= ctx.currentToken().Column() { + // If the comment is in the same or deeper column as the last element column in sequence value, + // treat it as a footer comment for the last element. + seqNode.FootComment = p.parseFootComment(ctx, seqTk.Column()) + if len(seqNode.Values) != 0 { + seqNode.FootComment.SetPath(seqNode.Values[len(seqNode.Values)-1].GetPath()) + } + } } - return node, nil + return seqNode, nil } -func (p *parser) createNodeFromToken(ctx *context, tk *token.Token) (ast.Node, error) { +func (p *parser) parseSequenceValue(ctx *context, seqTk *Token) (ast.Node, error) { + tk := ctx.currentToken() if tk == nil { - return nil, nil + return newNullNode(ctx, ctx.insertNullToken(seqTk)) } - if tk.NextType() == token.MappingValueType { - node, err := p.parseMappingValue(ctx) - return node, err - } - node, err := p.parseScalarValueWithComment(ctx, tk) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse scalar value") - } - if node != nil { - return node, nil + + if ctx.isComment() { + tk = ctx.nextNotCommentToken() } - switch tk.Type { - case token.CommentType: - return p.parseComment(ctx) - case token.MappingKeyType: - return p.parseMappingKey(ctx) - case token.DocumentHeaderType: - return p.parseDocument(ctx) - case token.MappingStartType: - return p.parseMapping(ctx) - case token.SequenceStartType: - return p.parseSequence(ctx) - case token.SequenceEntryType: - return p.parseSequenceEntry(ctx) - case token.AnchorType: - return p.parseAnchor(ctx) - case token.AliasType: - return p.parseAlias(ctx) - case token.DirectiveType: - return p.parseDirective(ctx) - case token.TagType: - return p.parseTag(ctx) - case token.LiteralType, token.FoldedType: - return p.parseLiteral(ctx) + seqCol := seqTk.Column() + seqLine := seqTk.Line() + + if tk.Column() == seqCol && tk.Type() == token.SequenceEntryType { + // in this case, + // ---- + // - + // - + return newNullNode(ctx, ctx.insertNullToken(seqTk)) } - return nil, nil -} -func (p *parser) parse(tokens token.Tokens, mode Mode) (*ast.File, error) { - ctx := newContext(tokens, mode) - file := &ast.File{Docs: []*ast.DocumentNode{}} - for ctx.next() { - node, err := p.parseToken(ctx, ctx.currentToken()) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse") - } - ctx.progressIgnoreComment(1) - if node == nil { - continue + if tk.Line() == seqLine && tk.GroupType() == TokenGroupAnchorName && + ctx.nextToken().Column() == seqCol && ctx.nextToken().Type() == token.SequenceEntryType { + // in this case, + // ---- + // - &anchor + // - + group := &TokenGroup{ + Type: TokenGroupAnchor, + Tokens: []*Token{tk, ctx.createNullToken(tk)}, } - if doc, ok := node.(*ast.DocumentNode); ok { - file.Docs = append(file.Docs, doc) - } else { - file.Docs = append(file.Docs, ast.Document(nil, node)) + anchor, err := p.parseAnchor(ctx.withGroup(group), group) + if err != nil { + return nil, err } + ctx.goNext() + return anchor, nil } - return file, nil -} -type Mode uint + if tk.Column() <= seqCol && tk.GroupType() == TokenGroupAnchorName { + // - + // &anchor + return nil, errors.ErrSyntax("anchor is not allowed in this sequence context", tk.RawToken()) + } -const ( - ParseComments Mode = 1 << iota // parse comments and add them to AST -) + if tk.Column() < seqCol { + // in this case, + // ---- + // - + // next + return newNullNode(ctx, ctx.insertNullToken(seqTk)) + } -// ParseBytes parse from byte slice, and returns ast.File -func ParseBytes(bytes []byte, mode Mode) (*ast.File, error) { - tokens := lexer.Tokenize(string(bytes)) - f, err := Parse(tokens, mode) + if tk.Line() == seqLine && tk.GroupType() == TokenGroupAnchorName && + ctx.nextToken().Column() < seqCol { + // in this case, + // ---- + // - &anchor + // next + group := &TokenGroup{ + Type: TokenGroupAnchor, + Tokens: []*Token{tk, ctx.createNullToken(tk)}, + } + anchor, err := p.parseAnchor(ctx.withGroup(group), group) + if err != nil { + return nil, err + } + ctx.goNext() + return anchor, nil + } + + value, err := p.parseToken(ctx, ctx.currentToken()) if err != nil { - return nil, errors.Wrapf(err, "failed to parse") + return nil, err } - return f, nil + return value, nil } -// Parse parse from token instances, and returns ast.File -func Parse(tokens token.Tokens, mode Mode) (*ast.File, error) { - var p parser - f, err := p.parse(tokens, mode) +func (p *parser) parseDirective(ctx *context, g *TokenGroup) (*ast.DirectiveNode, error) { + node, err := newDirectiveNode(ctx, g.First()) if err != nil { - return nil, errors.Wrapf(err, "failed to parse") + return nil, err } - return f, nil + value, err := p.parseToken(ctx, g.Last()) + if err != nil { + return nil, err + } + node.Value = value + return node, nil } -// Parse parse from filename, and returns ast.File -func ParseFile(filename string, mode Mode) (*ast.File, error) { - file, err := os.ReadFile(filename) +func (p *parser) parseComment(ctx *context) (ast.Node, error) { + cm := p.parseHeadComment(ctx) + node, err := p.parseToken(ctx, ctx.currentToken()) if err != nil { - return nil, errors.Wrapf(err, "failed to read file: %s", filename) + return nil, err } - f, err := ParseBytes(file, mode) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse") + if err := setHeadComment(cm, node); err != nil { + return nil, err } - f.Name = filename - return f, nil + return node, nil +} + +func (p *parser) parseHeadComment(ctx *context) *ast.CommentGroupNode { + tks := []*token.Token{} + for ctx.isComment() { + tks = append(tks, ctx.currentToken().RawToken()) + ctx.goNext() + } + if len(tks) == 0 { + return nil + } + return ast.CommentGroup(tks) +} + +func (p *parser) parseFootComment(ctx *context, col int) *ast.CommentGroupNode { + tks := []*token.Token{} + for ctx.isComment() && col <= ctx.currentToken().Column() { + tks = append(tks, ctx.currentToken().RawToken()) + ctx.goNext() + } + if len(tks) == 0 { + return nil + } + return ast.CommentGroup(tks) } diff --git a/vendor/github.com/goccy/go-yaml/parser/token.go b/vendor/github.com/goccy/go-yaml/parser/token.go new file mode 100644 index 0000000..c7bc5e8 --- /dev/null +++ b/vendor/github.com/goccy/go-yaml/parser/token.go @@ -0,0 +1,668 @@ +package parser + +import ( + "fmt" + "os" + + "github.com/goccy/go-yaml/internal/errors" + "github.com/goccy/go-yaml/token" +) + +type TokenGroupType int + +const ( + TokenGroupNone TokenGroupType = iota + TokenGroupDirective + TokenGroupDocument + TokenGroupDocumentBody + TokenGroupAnchor + TokenGroupAnchorName + TokenGroupAlias + TokenGroupLiteral + TokenGroupFolded + TokenGroupScalarTag + TokenGroupMapKey + TokenGroupMapKeyValue +) + +func (t TokenGroupType) String() string { + switch t { + case TokenGroupNone: + return "none" + case TokenGroupDirective: + return "directive" + case TokenGroupDocument: + return "document" + case TokenGroupDocumentBody: + return "document_body" + case TokenGroupAnchor: + return "anchor" + case TokenGroupAnchorName: + return "anchor_name" + case TokenGroupAlias: + return "alias" + case TokenGroupLiteral: + return "literal" + case TokenGroupFolded: + return "folded" + case TokenGroupScalarTag: + return "scalar_tag" + case TokenGroupMapKey: + return "map_key" + case TokenGroupMapKeyValue: + return "map_key_value" + } + return "none" +} + +type Token struct { + Token *token.Token + Group *TokenGroup + LineComment *token.Token +} + +func (t *Token) RawToken() *token.Token { + if t == nil { + return nil + } + if t.Token != nil { + return t.Token + } + return t.Group.RawToken() +} + +func (t *Token) Type() token.Type { + if t == nil { + return 0 + } + if t.Token != nil { + return t.Token.Type + } + return t.Group.TokenType() +} + +func (t *Token) GroupType() TokenGroupType { + if t == nil { + return TokenGroupNone + } + if t.Token != nil { + return TokenGroupNone + } + return t.Group.Type +} + +func (t *Token) Line() int { + if t == nil { + return 0 + } + if t.Token != nil { + return t.Token.Position.Line + } + return t.Group.Line() +} + +func (t *Token) Column() int { + if t == nil { + return 0 + } + if t.Token != nil { + return t.Token.Position.Column + } + return t.Group.Column() +} + +func (t *Token) SetGroupType(typ TokenGroupType) { + if t.Group == nil { + return + } + t.Group.Type = typ +} + +func (t *Token) Dump() { + ctx := new(groupTokenRenderContext) + if t.Token != nil { + fmt.Fprint(os.Stdout, t.Token.Value) + return + } + t.Group.dump(ctx) + fmt.Fprintf(os.Stdout, "\n") +} + +func (t *Token) dump(ctx *groupTokenRenderContext) { + if t.Token != nil { + fmt.Fprint(os.Stdout, t.Token.Value) + return + } + t.Group.dump(ctx) +} + +type groupTokenRenderContext struct { + num int +} + +type TokenGroup struct { + Type TokenGroupType + Tokens []*Token +} + +func (g *TokenGroup) First() *Token { + if len(g.Tokens) == 0 { + return nil + } + return g.Tokens[0] +} + +func (g *TokenGroup) Last() *Token { + if len(g.Tokens) == 0 { + return nil + } + return g.Tokens[len(g.Tokens)-1] +} + +func (g *TokenGroup) dump(ctx *groupTokenRenderContext) { + num := ctx.num + fmt.Fprint(os.Stdout, colorize(num, "(")) + ctx.num++ + for _, tk := range g.Tokens { + tk.dump(ctx) + } + fmt.Fprint(os.Stdout, colorize(num, ")")) +} + +func (g *TokenGroup) RawToken() *token.Token { + if len(g.Tokens) == 0 { + return nil + } + return g.Tokens[0].RawToken() +} + +func (g *TokenGroup) Line() int { + if len(g.Tokens) == 0 { + return 0 + } + return g.Tokens[0].Line() +} + +func (g *TokenGroup) Column() int { + if len(g.Tokens) == 0 { + return 0 + } + return g.Tokens[0].Column() +} + +func (g *TokenGroup) TokenType() token.Type { + if len(g.Tokens) == 0 { + return 0 + } + return g.Tokens[0].Type() +} + +func createGroupedTokens(tokens token.Tokens) ([]*Token, error) { + var err error + tks := newTokens(tokens) + tks = createLineCommentTokenGroups(tks) + tks, err = createLiteralAndFoldedTokenGroups(tks) + if err != nil { + return nil, err + } + tks, err = createAnchorAndAliasTokenGroups(tks) + if err != nil { + return nil, err + } + tks = createScalarTagTokenGroups(tks) + tks, err = createAnchorWithScalarTagTokenGroups(tks) + if err != nil { + return nil, err + } + tks, err = createMapKeyTokenGroups(tks) + if err != nil { + return nil, err + } + tks = createMapKeyValueTokenGroups(tks) + tks, err = createDirectiveTokenGroups(tks) + if err != nil { + return nil, err + } + tks, err = createDocumentTokens(tks) + if err != nil { + return nil, err + } + return tks, nil +} + +func newTokens(tks token.Tokens) []*Token { + ret := make([]*Token, 0, len(tks)) + for _, tk := range tks { + ret = append(ret, &Token{Token: tk}) + } + return ret +} + +func createLineCommentTokenGroups(tokens []*Token) []*Token { + ret := make([]*Token, 0, len(tokens)) + for i := 0; i < len(tokens); i++ { + tk := tokens[i] + switch tk.Type() { + case token.CommentType: + if i > 0 && tokens[i-1].Line() == tk.Line() { + tokens[i-1].LineComment = tk.RawToken() + } else { + ret = append(ret, tk) + } + default: + ret = append(ret, tk) + } + } + return ret +} + +func createLiteralAndFoldedTokenGroups(tokens []*Token) ([]*Token, error) { + ret := make([]*Token, 0, len(tokens)) + for i := 0; i < len(tokens); i++ { + tk := tokens[i] + switch tk.Type() { + case token.LiteralType: + tks := []*Token{tk} + if i+1 < len(tokens) { + tks = append(tks, tokens[i+1]) + } + ret = append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupLiteral, + Tokens: tks, + }, + }) + i++ + case token.FoldedType: + tks := []*Token{tk} + if i+1 < len(tokens) { + tks = append(tks, tokens[i+1]) + } + ret = append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupFolded, + Tokens: tks, + }, + }) + i++ + default: + ret = append(ret, tk) + } + } + return ret, nil +} + +func createAnchorAndAliasTokenGroups(tokens []*Token) ([]*Token, error) { + ret := make([]*Token, 0, len(tokens)) + for i := 0; i < len(tokens); i++ { + tk := tokens[i] + switch tk.Type() { + case token.AnchorType: + if i+1 >= len(tokens) { + return nil, errors.ErrSyntax("undefined anchor name", tk.RawToken()) + } + if i+2 >= len(tokens) { + return nil, errors.ErrSyntax("undefined anchor value", tk.RawToken()) + } + anchorName := &Token{ + Group: &TokenGroup{ + Type: TokenGroupAnchorName, + Tokens: []*Token{tk, tokens[i+1]}, + }, + } + valueTk := tokens[i+2] + if tk.Line() == valueTk.Line() && valueTk.Type() == token.SequenceEntryType { + return nil, errors.ErrSyntax("sequence entries are not allowed after anchor on the same line", valueTk.RawToken()) + } + if tk.Line() == valueTk.Line() && isScalarType(valueTk) { + ret = append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupAnchor, + Tokens: []*Token{anchorName, valueTk}, + }, + }) + i++ + } else { + ret = append(ret, anchorName) + } + i++ + case token.AliasType: + if i+1 == len(tokens) { + return nil, errors.ErrSyntax("undefined alias name", tk.RawToken()) + } + ret = append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupAlias, + Tokens: []*Token{tk, tokens[i+1]}, + }, + }) + i++ + default: + ret = append(ret, tk) + } + } + return ret, nil +} + +func createScalarTagTokenGroups(tokens []*Token) []*Token { + ret := make([]*Token, 0, len(tokens)) + for i := 0; i < len(tokens); i++ { + tk := tokens[i] + if tk.Type() != token.TagType { + ret = append(ret, tk) + continue + } + tag := tk.RawToken() + switch token.ReservedTagKeyword(tag.Value) { + case token.IntegerTag, token.FloatTag, token.StringTag, token.BinaryTag, token.TimestampTag, token.BooleanTag, token.NullTag: + if len(tokens) <= i+1 { + ret = append(ret, tk) + continue + } + if tk.Line() != tokens[i+1].Line() { + ret = append(ret, tk) + continue + } + if tokens[i+1].GroupType() == TokenGroupAnchorName { + ret = append(ret, tk) + continue + } + if isScalarType(tokens[i+1]) { + ret = append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupScalarTag, + Tokens: []*Token{tk, tokens[i+1]}, + }, + }) + i++ + } else { + ret = append(ret, tk) + } + default: + ret = append(ret, tk) + } + } + return ret +} + +func createAnchorWithScalarTagTokenGroups(tokens []*Token) ([]*Token, error) { + ret := make([]*Token, 0, len(tokens)) + for i := 0; i < len(tokens); i++ { + tk := tokens[i] + switch tk.GroupType() { + case TokenGroupAnchorName: + if i+1 >= len(tokens) { + return nil, errors.ErrSyntax("undefined anchor value", tk.RawToken()) + } + valueTk := tokens[i+1] + if tk.Line() == valueTk.Line() && valueTk.GroupType() == TokenGroupScalarTag { + ret = append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupAnchor, + Tokens: []*Token{tk, tokens[i+1]}, + }, + }) + i++ + } else { + ret = append(ret, tk) + } + default: + ret = append(ret, tk) + } + } + return ret, nil +} + +func createMapKeyTokenGroups(tokens []*Token) ([]*Token, error) { + tks, err := createMapKeyByMappingKey(tokens) + if err != nil { + return nil, err + } + return createMapKeyByMappingValue(tks) +} + +func createMapKeyByMappingKey(tokens []*Token) ([]*Token, error) { + ret := make([]*Token, 0, len(tokens)) + for i := 0; i < len(tokens); i++ { + tk := tokens[i] + switch tk.Type() { + case token.MappingKeyType: + if i+1 >= len(tokens) { + return nil, errors.ErrSyntax("undefined map key", tk.RawToken()) + } + ret = append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupMapKey, + Tokens: []*Token{tk, tokens[i+1]}, + }, + }) + i++ + default: + ret = append(ret, tk) + } + } + return ret, nil +} + +func createMapKeyByMappingValue(tokens []*Token) ([]*Token, error) { + ret := make([]*Token, 0, len(tokens)) + for i := 0; i < len(tokens); i++ { + tk := tokens[i] + switch tk.Type() { + case token.MappingValueType: + if i == 0 { + return nil, errors.ErrSyntax("unexpected key name", tk.RawToken()) + } + mapKeyTk := tokens[i-1] + if isNotMapKeyType(mapKeyTk) { + return nil, errors.ErrSyntax("found an invalid key for this map", tokens[i].RawToken()) + } + newTk := &Token{Token: mapKeyTk.Token, Group: mapKeyTk.Group} + mapKeyTk.Token = nil + mapKeyTk.Group = &TokenGroup{ + Type: TokenGroupMapKey, + Tokens: []*Token{newTk, tk}, + } + default: + ret = append(ret, tk) + } + } + return ret, nil +} + +func createMapKeyValueTokenGroups(tokens []*Token) []*Token { + ret := make([]*Token, 0, len(tokens)) + for i := 0; i < len(tokens); i++ { + tk := tokens[i] + switch tk.GroupType() { + case TokenGroupMapKey: + if len(tokens) <= i+1 { + ret = append(ret, tk) + continue + } + valueTk := tokens[i+1] + if tk.Line() != valueTk.Line() { + ret = append(ret, tk) + continue + } + if valueTk.GroupType() == TokenGroupAnchorName { + ret = append(ret, tk) + continue + } + if valueTk.Type() == token.TagType && valueTk.GroupType() != TokenGroupScalarTag { + ret = append(ret, tk) + continue + } + + if isScalarType(valueTk) || valueTk.Type() == token.TagType { + ret = append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupMapKeyValue, + Tokens: []*Token{tk, valueTk}, + }, + }) + i++ + } else { + ret = append(ret, tk) + continue + } + default: + ret = append(ret, tk) + } + } + return ret +} + +func createDirectiveTokenGroups(tokens []*Token) ([]*Token, error) { + ret := make([]*Token, 0, len(tokens)) + for i := 0; i < len(tokens); i++ { + tk := tokens[i] + switch tk.Type() { + case token.DirectiveType: + if i+1 >= len(tokens) { + return nil, errors.ErrSyntax("undefined directive value", tk.RawToken()) + } + if i+2 >= len(tokens) { + return nil, errors.ErrSyntax("unexpected directive value. document not started", tk.RawToken()) + } + if tokens[i+2].Type() != token.DocumentHeaderType { + return nil, errors.ErrSyntax("unexpected directive value. document not started", tk.RawToken()) + } + if tk.Line() != tokens[i+1].Line() { + return nil, errors.ErrSyntax("undefined directive value", tk.RawToken()) + } + ret = append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupDirective, + Tokens: []*Token{tk, tokens[i+1]}, + }, + }) + i++ + default: + ret = append(ret, tk) + } + } + return ret, nil +} + +func createDocumentTokens(tokens []*Token) ([]*Token, error) { + var ret []*Token + for i := 0; i < len(tokens); i++ { + tk := tokens[i] + switch tk.Type() { + case token.DocumentHeaderType: + if i != 0 { + ret = append(ret, &Token{ + Group: &TokenGroup{Tokens: tokens[:i]}, + }) + } + if i+1 == len(tokens) { + // if current token is last token, add DocumentHeader only tokens to ret. + return append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupDocument, + Tokens: []*Token{tk}, + }, + }), nil + } + if tokens[i+1].Type() == token.DocumentHeaderType { + return append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupDocument, + Tokens: []*Token{tk}, + }, + }), nil + } + if tokens[i].Line() == tokens[i+1].Line() { + switch tokens[i+1].GroupType() { + case TokenGroupMapKey, TokenGroupMapKeyValue: + return nil, errors.ErrSyntax("value cannot be placed after document separator", tokens[i+1].RawToken()) + } + switch tokens[i+1].Type() { + case token.SequenceEntryType: + return nil, errors.ErrSyntax("value cannot be placed after document separator", tokens[i+1].RawToken()) + } + } + tks, err := createDocumentTokens(tokens[i+1:]) + if err != nil { + return nil, err + } + if len(tks) != 0 { + tks[0].SetGroupType(TokenGroupDocument) + tks[0].Group.Tokens = append([]*Token{tk}, tks[0].Group.Tokens...) + return append(ret, tks...), nil + } + return append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupDocument, + Tokens: []*Token{tk}, + }, + }), nil + case token.DocumentEndType: + if i != 0 { + ret = append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupDocument, + Tokens: tokens[0 : i+1], + }, + }) + } + if i+1 == len(tokens) { + return ret, nil + } + if isScalarType(tokens[i+1]) { + return nil, errors.ErrSyntax("unexpected end content", tokens[i+1].RawToken()) + } + + tks, err := createDocumentTokens(tokens[i+1:]) + if err != nil { + return nil, err + } + return append(ret, tks...), nil + } + } + return append(ret, &Token{ + Group: &TokenGroup{ + Type: TokenGroupDocument, + Tokens: tokens, + }, + }), nil +} + +func isScalarType(tk *Token) bool { + switch tk.GroupType() { + case TokenGroupMapKey, TokenGroupMapKeyValue: + return false + } + typ := tk.Type() + return typ == token.AnchorType || + typ == token.AliasType || + typ == token.LiteralType || + typ == token.FoldedType || + typ == token.NullType || + typ == token.BoolType || + typ == token.IntegerType || + typ == token.BinaryIntegerType || + typ == token.OctetIntegerType || + typ == token.HexIntegerType || + typ == token.FloatType || + typ == token.InfinityType || + typ == token.NanType || + typ == token.StringType || + typ == token.SingleQuoteType || + typ == token.DoubleQuoteType +} + +func isNotMapKeyType(tk *Token) bool { + typ := tk.Type() + return typ == token.DirectiveType || + typ == token.DocumentHeaderType || + typ == token.DocumentEndType || + typ == token.CollectEntryType || + typ == token.MappingStartType || + typ == token.MappingValueType || + typ == token.MappingEndType || + typ == token.SequenceStartType || + typ == token.SequenceEntryType || + typ == token.SequenceEndType +} diff --git a/vendor/github.com/goccy/go-yaml/path.go b/vendor/github.com/goccy/go-yaml/path.go index b79c666..fcb5681 100644 --- a/vendor/github.com/goccy/go-yaml/path.go +++ b/vendor/github.com/goccy/go-yaml/path.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/goccy/go-yaml/ast" - "github.com/goccy/go-yaml/internal/errors" "github.com/goccy/go-yaml/parser" "github.com/goccy/go-yaml/printer" ) @@ -39,7 +38,7 @@ func PathString(s string) (*Path, error) { case '.': b, buf, c, err := parsePathDot(builder, buf, cursor) if err != nil { - return nil, errors.Wrapf(err, "failed to parse path of dot") + return nil, err } length = len(buf) builder = b @@ -47,13 +46,13 @@ func PathString(s string) (*Path, error) { case '[': b, buf, c, err := parsePathIndex(builder, buf, cursor) if err != nil { - return nil, errors.Wrapf(err, "failed to parse path of index") + return nil, err } length = len(buf) builder = b cursor = c default: - return nil, errors.Wrapf(ErrInvalidPathString, "invalid path at %d", cursor) + return nil, fmt.Errorf("invalid path at %d: %w", cursor, ErrInvalidPathString) } } return builder.Build(), nil @@ -67,18 +66,18 @@ func parsePathRecursive(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, [ c := buf[cursor] switch c { case '$': - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '$' after '..' character") + return nil, nil, 0, fmt.Errorf("specified '$' after '..' character: %w", ErrInvalidPathString) case '*': - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '*' after '..' character") + return nil, nil, 0, fmt.Errorf("specified '*' after '..' character: %w", ErrInvalidPathString) case '.', '[': goto end case ']': - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified ']' after '..' character") + return nil, nil, 0, fmt.Errorf("specified ']' after '..' character: %w", ErrInvalidPathString) } } end: if start == cursor { - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "not found recursive selector") + return nil, nil, 0, fmt.Errorf("not found recursive selector: %w", ErrInvalidPathString) } return b.Recursive(string(buf[start:cursor])), buf, cursor, nil } @@ -88,7 +87,7 @@ func parsePathDot(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, []rune, if cursor+1 < length && buf[cursor+1] == '.' { b, buf, c, err := parsePathRecursive(b, buf, cursor) if err != nil { - return nil, nil, 0, errors.Wrapf(err, "failed to parse path of recursive") + return nil, nil, 0, err } return b, buf, c, nil } @@ -103,18 +102,18 @@ func parsePathDot(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, []rune, c := buf[cursor] switch c { case '$': - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '$' after '.' character") + return nil, nil, 0, fmt.Errorf("specified '$' after '.' character: %w", ErrInvalidPathString) case '*': - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '*' after '.' character") + return nil, nil, 0, fmt.Errorf("specified '*' after '.' character: %w", ErrInvalidPathString) case '.', '[': goto end case ']': - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified ']' after '.' character") + return nil, nil, 0, fmt.Errorf("specified ']' after '.' character: %w", ErrInvalidPathString) } } end: if start == cursor { - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "cloud not find by empty key") + return nil, nil, 0, fmt.Errorf("cloud not find by empty key: %w", ErrInvalidPathString) } return b.child(string(buf[start:cursor])), buf, cursor, nil } @@ -136,21 +135,21 @@ func parseQuotedKey(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, []run } end: if !foundEndDelim { - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "could not find end delimiter for key") + return nil, nil, 0, fmt.Errorf("could not find end delimiter for key: %w", ErrInvalidPathString) } if start == cursor { - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "could not find by empty key") + return nil, nil, 0, fmt.Errorf("could not find by empty key: %w", ErrInvalidPathString) } selector := buf[start:cursor] cursor++ if cursor < length { switch buf[cursor] { case '$': - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '$' after '.' character") + return nil, nil, 0, fmt.Errorf("specified '$' after '.' character: %w", ErrInvalidPathString) case '*': - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified '*' after '.' character") + return nil, nil, 0, fmt.Errorf("specified '*' after '.' character: %w", ErrInvalidPathString) case ']': - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "specified ']' after '.' character") + return nil, nil, 0, fmt.Errorf("specified ']' after '.' character: %w", ErrInvalidPathString) } } return b.child(string(selector)), buf, cursor, nil @@ -160,7 +159,7 @@ func parsePathIndex(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, []run length := len(buf) cursor++ // skip '[' character if length <= cursor { - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "unexpected end of YAML Path") + return nil, nil, 0, fmt.Errorf("unexpected end of YAML Path: %w", ErrInvalidPathString) } c := buf[cursor] switch c { @@ -176,7 +175,7 @@ func parsePathIndex(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, []run break } if buf[cursor] != ']' { - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "invalid character %s at %d", string(buf[cursor]), cursor) + return nil, nil, 0, fmt.Errorf("invalid character %s at %d: %w", string(buf[cursor]), cursor, ErrInvalidPathString) } numOrAll := string(buf[start:cursor]) if numOrAll == "*" { @@ -184,11 +183,11 @@ func parsePathIndex(b *PathBuilder, buf []rune, cursor int) (*PathBuilder, []run } num, err := strconv.ParseInt(numOrAll, 10, 64) if err != nil { - return nil, nil, 0, errors.Wrapf(err, "failed to parse number") + return nil, nil, 0, err } return b.Index(uint(num)), buf, cursor + 1, nil } - return nil, nil, 0, errors.Wrapf(ErrInvalidPathString, "invalid character %s at %d", c, cursor) + return nil, nil, 0, fmt.Errorf("invalid character %q at %d: %w", c, cursor, ErrInvalidPathString) } // Path represent YAMLPath ( like a JSONPath ). @@ -205,10 +204,10 @@ func (p *Path) String() string { func (p *Path) Read(r io.Reader, v interface{}) error { node, err := p.ReadNode(r) if err != nil { - return errors.Wrapf(err, "failed to read node") + return err } if err := Unmarshal([]byte(node.String()), v); err != nil { - return errors.Wrapf(err, "failed to unmarshal") + return err } return nil } @@ -220,15 +219,15 @@ func (p *Path) ReadNode(r io.Reader) (ast.Node, error) { } var buf bytes.Buffer if _, err := io.Copy(&buf, r); err != nil { - return nil, errors.Wrapf(err, "failed to copy from reader") + return nil, err } f, err := parser.ParseBytes(buf.Bytes(), 0) if err != nil { - return nil, errors.Wrapf(err, "failed to parse yaml") + return nil, err } node, err := p.FilterFile(f) if err != nil { - return nil, errors.Wrapf(err, "failed to filter from ast.File") + return nil, err } return node, nil } @@ -237,10 +236,10 @@ func (p *Path) ReadNode(r io.Reader) (ast.Node, error) { func (p *Path) Filter(target, v interface{}) error { b, err := Marshal(target) if err != nil { - return errors.Wrapf(err, "failed to marshal target value") + return err } if err := p.Read(bytes.NewBuffer(b), v); err != nil { - return errors.Wrapf(err, "failed to read") + return err } return nil } @@ -250,20 +249,20 @@ func (p *Path) FilterFile(f *ast.File) (ast.Node, error) { for _, doc := range f.Docs { node, err := p.FilterNode(doc.Body) if err != nil { - return nil, errors.Wrapf(err, "failed to filter node by path ( %s )", p.node) + return nil, err } if node != nil { return node, nil } } - return nil, errors.Wrapf(ErrNotFoundNode, "failed to find path ( %s )", p.node) + return nil, fmt.Errorf("failed to find path ( %s ): %w", p.node, ErrNotFoundNode) } // FilterNode filter from node by YAMLPath. func (p *Path) FilterNode(node ast.Node) (ast.Node, error) { n, err := p.node.filter(node) if err != nil { - return nil, errors.Wrapf(err, "failed to filter node by path ( %s )", p.node) + return nil, err } return n, nil } @@ -272,14 +271,14 @@ func (p *Path) FilterNode(node ast.Node) (ast.Node, error) { func (p *Path) MergeFromReader(dst *ast.File, src io.Reader) error { var buf bytes.Buffer if _, err := io.Copy(&buf, src); err != nil { - return errors.Wrapf(err, "failed to copy from reader") + return err } file, err := parser.ParseBytes(buf.Bytes(), 0) if err != nil { - return errors.Wrapf(err, "failed to parse") + return err } if err := p.MergeFromFile(dst, file); err != nil { - return errors.Wrapf(err, "failed to merge file") + return err } return nil } @@ -288,11 +287,11 @@ func (p *Path) MergeFromReader(dst *ast.File, src io.Reader) error { func (p *Path) MergeFromFile(dst *ast.File, src *ast.File) error { base, err := p.FilterFile(dst) if err != nil { - return errors.Wrapf(err, "failed to filter file") + return err } for _, doc := range src.Docs { if err := ast.Merge(base, doc); err != nil { - return errors.Wrapf(err, "failed to merge") + return err } } return nil @@ -302,10 +301,10 @@ func (p *Path) MergeFromFile(dst *ast.File, src *ast.File) error { func (p *Path) MergeFromNode(dst *ast.File, src ast.Node) error { base, err := p.FilterFile(dst) if err != nil { - return errors.Wrapf(err, "failed to filter file") + return err } if err := ast.Merge(base, src); err != nil { - return errors.Wrapf(err, "failed to merge") + return err } return nil } @@ -314,14 +313,14 @@ func (p *Path) MergeFromNode(dst *ast.File, src ast.Node) error { func (p *Path) ReplaceWithReader(dst *ast.File, src io.Reader) error { var buf bytes.Buffer if _, err := io.Copy(&buf, src); err != nil { - return errors.Wrapf(err, "failed to copy from reader") + return err } file, err := parser.ParseBytes(buf.Bytes(), 0) if err != nil { - return errors.Wrapf(err, "failed to parse") + return err } if err := p.ReplaceWithFile(dst, file); err != nil { - return errors.Wrapf(err, "failed to replace file") + return err } return nil } @@ -330,7 +329,7 @@ func (p *Path) ReplaceWithReader(dst *ast.File, src io.Reader) error { func (p *Path) ReplaceWithFile(dst *ast.File, src *ast.File) error { for _, doc := range src.Docs { if err := p.ReplaceWithNode(dst, doc); err != nil { - return errors.Wrapf(err, "failed to replace file by path ( %s )", p.node) + return err } } return nil @@ -343,7 +342,7 @@ func (p *Path) ReplaceWithNode(dst *ast.File, node ast.Node) error { node = node.(*ast.DocumentNode).Body } if err := p.node.replace(doc.Body, node); err != nil { - return errors.Wrapf(err, "failed to replace node by path ( %s )", p.node) + return err } } return nil @@ -472,7 +471,7 @@ func (n *rootNode) filter(node ast.Node) (ast.Node, error) { } filtered, err := n.child.filter(node) if err != nil { - return nil, errors.Wrapf(err, "failed to filter") + return nil, err } return filtered, nil } @@ -482,7 +481,7 @@ func (n *rootNode) replace(node ast.Node, target ast.Node) error { return nil } if err := n.child.replace(node, target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } return nil } @@ -514,7 +513,7 @@ func (n *selectorNode) filter(node ast.Node) (ast.Node, error) { var err error key, err = strconv.Unquote(key) if err != nil { - return nil, errors.Wrapf(err, "failed to unquote") + return nil, err } case '\'': if len(key) > 1 && key[len(key)-1] == '\'' { @@ -528,13 +527,13 @@ func (n *selectorNode) filter(node ast.Node) (ast.Node, error) { } filtered, err := n.child.filter(value.Value) if err != nil { - return nil, errors.Wrapf(err, "failed to filter") + return nil, err } return filtered, nil } } case ast.MappingValueType: - value := node.(*ast.MappingValueNode) + value, _ := node.(*ast.MappingValueNode) key := value.Key.GetToken().Value if key == selector { if n.child == nil { @@ -542,12 +541,12 @@ func (n *selectorNode) filter(node ast.Node) (ast.Node, error) { } filtered, err := n.child.filter(value.Value) if err != nil { - return nil, errors.Wrapf(err, "failed to filter") + return nil, err } return filtered, nil } default: - return nil, errors.Wrapf(ErrInvalidQuery, "expected node type is map or map value. but got %s", node.Type()) + return nil, fmt.Errorf("expected node type is map or map value. but got %s: %w", node.Type(), ErrInvalidQuery) } return nil, nil } @@ -559,11 +558,11 @@ func (n *selectorNode) replaceMapValue(value *ast.MappingValueNode, target ast.N } if n.child == nil { if err := value.Replace(target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } } else { if err := n.child.replace(value.Value, target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } } return nil @@ -574,16 +573,16 @@ func (n *selectorNode) replace(node ast.Node, target ast.Node) error { case ast.MappingType: for _, value := range node.(*ast.MappingNode).Values { if err := n.replaceMapValue(value, target); err != nil { - return errors.Wrapf(err, "failed to replace map value") + return err } } case ast.MappingValueType: - value := node.(*ast.MappingValueNode) + value, _ := node.(*ast.MappingValueNode) if err := n.replaceMapValue(value, target); err != nil { - return errors.Wrapf(err, "failed to replace map value") + return err } default: - return errors.Wrapf(ErrInvalidQuery, "expected node type is map or map value. but got %s", node.Type()) + return fmt.Errorf("expected node type is map or map value. but got %s: %w", node.Type(), ErrInvalidQuery) } return nil } @@ -612,11 +611,11 @@ func newIndexNode(selector uint) *indexNode { func (n *indexNode) filter(node ast.Node) (ast.Node, error) { if node.Type() != ast.SequenceType { - return nil, errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type()) + return nil, fmt.Errorf("expected sequence type node. but got %s: %w", node.Type(), ErrInvalidQuery) } - sequence := node.(*ast.SequenceNode) + sequence, _ := node.(*ast.SequenceNode) if n.selector >= uint(len(sequence.Values)) { - return nil, errors.Wrapf(ErrInvalidQuery, "expected index is %d. but got sequences has %d items", n.selector, sequence.Values) + return nil, fmt.Errorf("expected index is %d. but got sequences has %d items: %w", n.selector, sequence.Values, ErrInvalidQuery) } value := sequence.Values[n.selector] if n.child == nil { @@ -624,27 +623,27 @@ func (n *indexNode) filter(node ast.Node) (ast.Node, error) { } filtered, err := n.child.filter(value) if err != nil { - return nil, errors.Wrapf(err, "failed to filter") + return nil, err } return filtered, nil } func (n *indexNode) replace(node ast.Node, target ast.Node) error { if node.Type() != ast.SequenceType { - return errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type()) + return fmt.Errorf("expected sequence type node. but got %s: %w", node.Type(), ErrInvalidQuery) } - sequence := node.(*ast.SequenceNode) + sequence, _ := node.(*ast.SequenceNode) if n.selector >= uint(len(sequence.Values)) { - return errors.Wrapf(ErrInvalidQuery, "expected index is %d. but got sequences has %d items", n.selector, sequence.Values) + return fmt.Errorf("expected index is %d. but got sequences has %d items: %w", n.selector, sequence.Values, ErrInvalidQuery) } if n.child == nil { if err := sequence.Replace(int(n.selector), target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } return nil } if err := n.child.replace(sequence.Values[n.selector], target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } return nil } @@ -677,9 +676,9 @@ func (n *indexAllNode) String() string { func (n *indexAllNode) filter(node ast.Node) (ast.Node, error) { if node.Type() != ast.SequenceType { - return nil, errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type()) + return nil, fmt.Errorf("expected sequence type node. but got %s: %w", node.Type(), ErrInvalidQuery) } - sequence := node.(*ast.SequenceNode) + sequence, _ := node.(*ast.SequenceNode) if n.child == nil { return sequence, nil } @@ -688,7 +687,7 @@ func (n *indexAllNode) filter(node ast.Node) (ast.Node, error) { for _, value := range sequence.Values { filtered, err := n.child.filter(value) if err != nil { - return nil, errors.Wrapf(err, "failed to filter") + return nil, err } out.Values = append(out.Values, filtered) } @@ -697,20 +696,20 @@ func (n *indexAllNode) filter(node ast.Node) (ast.Node, error) { func (n *indexAllNode) replace(node ast.Node, target ast.Node) error { if node.Type() != ast.SequenceType { - return errors.Wrapf(ErrInvalidQuery, "expected sequence type node. but got %s", node.Type()) + return fmt.Errorf("expected sequence type node. but got %s: %w", node.Type(), ErrInvalidQuery) } - sequence := node.(*ast.SequenceNode) + sequence, _ := node.(*ast.SequenceNode) if n.child == nil { for idx := range sequence.Values { if err := sequence.Replace(idx, target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } } return nil } for _, value := range sequence.Values { if err := n.child.replace(value, target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } } return nil @@ -743,7 +742,7 @@ func (n *recursiveNode) filterNode(node ast.Node) (*ast.SequenceNode, error) { for _, value := range typedNode.Values { seq, err := n.filterNode(value) if err != nil { - return nil, errors.Wrapf(err, "failed to filter") + return nil, err } sequence.Values = append(sequence.Values, seq.Values...) } @@ -754,14 +753,14 @@ func (n *recursiveNode) filterNode(node ast.Node) (*ast.SequenceNode, error) { } seq, err := n.filterNode(typedNode.Value) if err != nil { - return nil, errors.Wrapf(err, "failed to filter") + return nil, err } sequence.Values = append(sequence.Values, seq.Values...) case *ast.SequenceNode: for _, value := range typedNode.Values { seq, err := n.filterNode(value) if err != nil { - return nil, errors.Wrapf(err, "failed to filter") + return nil, err } sequence.Values = append(sequence.Values, seq.Values...) } @@ -772,7 +771,7 @@ func (n *recursiveNode) filterNode(node ast.Node) (*ast.SequenceNode, error) { func (n *recursiveNode) filter(node ast.Node) (ast.Node, error) { sequence, err := n.filterNode(node) if err != nil { - return nil, errors.Wrapf(err, "failed to filter") + return nil, err } sequence.Start = node.GetToken() return sequence, nil @@ -783,23 +782,23 @@ func (n *recursiveNode) replaceNode(node ast.Node, target ast.Node) error { case *ast.MappingNode: for _, value := range typedNode.Values { if err := n.replaceNode(value, target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } } case *ast.MappingValueNode: key := typedNode.Key.GetToken().Value if n.selector == key { if err := typedNode.Replace(target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } } if err := n.replaceNode(typedNode.Value, target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } case *ast.SequenceNode: for _, value := range typedNode.Values { if err := n.replaceNode(value, target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } } } @@ -808,7 +807,7 @@ func (n *recursiveNode) replaceNode(node ast.Node, target ast.Node) error { func (n *recursiveNode) replace(node ast.Node, target ast.Node) error { if err := n.replaceNode(node, target); err != nil { - return errors.Wrapf(err, "failed to replace") + return err } return nil } diff --git a/vendor/github.com/goccy/go-yaml/printer/color.go b/vendor/github.com/goccy/go-yaml/printer/color.go new file mode 100644 index 0000000..79d7d7c --- /dev/null +++ b/vendor/github.com/goccy/go-yaml/printer/color.go @@ -0,0 +1,83 @@ +// This source inspired by https://github.com/fatih/color. +package printer + +import ( + "fmt" + "strings" +) + +type ColorAttribute int + +const ( + ColorReset ColorAttribute = iota + ColorBold + ColorFaint + ColorItalic + ColorUnderline + ColorBlinkSlow + ColorBlinkRapid + ColorReverseVideo + ColorConcealed + ColorCrossedOut +) + +const ( + ColorFgHiBlack ColorAttribute = iota + 90 + ColorFgHiRed + ColorFgHiGreen + ColorFgHiYellow + ColorFgHiBlue + ColorFgHiMagenta + ColorFgHiCyan + ColorFgHiWhite +) + +const ( + ColorResetBold ColorAttribute = iota + 22 + ColorResetItalic + ColorResetUnderline + ColorResetBlinking + + ColorResetReversed + ColorResetConcealed + ColorResetCrossedOut +) + +const escape = "\x1b" + +var colorResetMap = map[ColorAttribute]ColorAttribute{ + ColorBold: ColorResetBold, + ColorFaint: ColorResetBold, + ColorItalic: ColorResetItalic, + ColorUnderline: ColorResetUnderline, + ColorBlinkSlow: ColorResetBlinking, + ColorBlinkRapid: ColorResetBlinking, + ColorReverseVideo: ColorResetReversed, + ColorConcealed: ColorResetConcealed, + ColorCrossedOut: ColorResetCrossedOut, +} + +func format(attrs ...ColorAttribute) string { + format := make([]string, 0, len(attrs)) + for _, attr := range attrs { + format = append(format, fmt.Sprint(attr)) + } + return fmt.Sprintf("%s[%sm", escape, strings.Join(format, ";")) +} + +func unformat(attrs ...ColorAttribute) string { + format := make([]string, len(attrs)) + for _, attr := range attrs { + v := fmt.Sprint(ColorReset) + reset, exists := colorResetMap[attr] + if exists { + v = fmt.Sprint(reset) + } + format = append(format, v) + } + return fmt.Sprintf("%s[%sm", escape, strings.Join(format, ";")) +} + +func colorize(msg string, attrs ...ColorAttribute) string { + return format(attrs...) + msg + unformat(attrs...) +} diff --git a/vendor/github.com/goccy/go-yaml/printer/printer.go b/vendor/github.com/goccy/go-yaml/printer/printer.go index d5e25dc..e2a7c3c 100644 --- a/vendor/github.com/goccy/go-yaml/printer/printer.go +++ b/vendor/github.com/goccy/go-yaml/printer/printer.go @@ -5,7 +5,6 @@ import ( "math" "strings" - "github.com/fatih/color" "github.com/goccy/go-yaml/ast" "github.com/goccy/go-yaml/token" ) @@ -29,6 +28,7 @@ type Printer struct { Bool PrintFunc String PrintFunc Number PrintFunc + Comment PrintFunc } func defaultLineNumberFormat(num int) string { @@ -82,6 +82,11 @@ func (p *Printer) property(tk *token.Token) *Property { return p.Number() } return prop + case token.CommentType: + if p.Comment != nil { + return p.Comment() + } + return prop default: } return prop @@ -144,47 +149,47 @@ func (p *Printer) PrintNode(node ast.Node) []byte { return []byte(fmt.Sprintf("%+v\n", node)) } -const escape = "\x1b" - -func format(attr color.Attribute) string { - return fmt.Sprintf("%s[%dm", escape, attr) -} - func (p *Printer) setDefaultColorSet() { p.Bool = func() *Property { return &Property{ - Prefix: format(color.FgHiMagenta), - Suffix: format(color.Reset), + Prefix: format(ColorFgHiMagenta), + Suffix: format(ColorReset), } } p.Number = func() *Property { return &Property{ - Prefix: format(color.FgHiMagenta), - Suffix: format(color.Reset), + Prefix: format(ColorFgHiMagenta), + Suffix: format(ColorReset), } } p.MapKey = func() *Property { return &Property{ - Prefix: format(color.FgHiCyan), - Suffix: format(color.Reset), + Prefix: format(ColorFgHiCyan), + Suffix: format(ColorReset), } } p.Anchor = func() *Property { return &Property{ - Prefix: format(color.FgHiYellow), - Suffix: format(color.Reset), + Prefix: format(ColorFgHiYellow), + Suffix: format(ColorReset), } } p.Alias = func() *Property { return &Property{ - Prefix: format(color.FgHiYellow), - Suffix: format(color.Reset), + Prefix: format(ColorFgHiYellow), + Suffix: format(ColorReset), } } p.String = func() *Property { return &Property{ - Prefix: format(color.FgHiGreen), - Suffix: format(color.Reset), + Prefix: format(ColorFgHiGreen), + Suffix: format(ColorReset), + } + } + p.Comment = func() *Property { + return &Property{ + Prefix: format(ColorFgHiBlack), + Suffix: format(ColorReset), } } } @@ -192,9 +197,9 @@ func (p *Printer) setDefaultColorSet() { func (p *Printer) PrintErrorMessage(msg string, isColored bool) string { if isColored { return fmt.Sprintf("%s%s%s", - format(color.FgHiRed), + format(ColorFgHiRed), msg, - format(color.Reset), + format(ColorReset), ) } return msg @@ -317,8 +322,7 @@ func (p *Printer) setupErrorTokenFormat(annotateLine int, isColored bool) { p.LineNumber = true p.LineNumberFormat = func(num int) string { if isColored { - fn := color.New(color.Bold, color.FgHiWhite).SprintFunc() - return fn(prefix(annotateLine, num)) + return colorize(prefix(annotateLine, num), ColorBold, ColorFgHiWhite) } return prefix(annotateLine, num) } diff --git a/vendor/github.com/goccy/go-yaml/scanner/context.go b/vendor/github.com/goccy/go-yaml/scanner/context.go index 3aaec56..2529713 100644 --- a/vendor/github.com/goccy/go-yaml/scanner/context.go +++ b/vendor/github.com/goccy/go-yaml/scanner/context.go @@ -1,28 +1,32 @@ package scanner import ( + "fmt" + "strconv" + "strings" "sync" "github.com/goccy/go-yaml/token" ) -const whitespace = ' ' - // Context context at scanning type Context struct { - idx int - size int - notSpaceCharPos int - notSpaceOrgCharPos int - src []rune - buf []rune - obuf []rune - tokens token.Tokens - isRawFolded bool - isLiteral bool - isFolded bool - isSingleLine bool - literalOpt string + idx int + size int + notSpaceCharPos int + notSpaceOrgCharPos int + src []rune + buf []rune + obuf []rune + tokens token.Tokens + isRawFolded bool + isLiteral bool + isFolded bool + docOpt string + docFirstLineIndentColumn int + docPrevLineIndentColumn int + docLineIndentColumn int + docFoldedNewLine bool } var ( @@ -35,14 +39,13 @@ var ( func createContext() *Context { return &Context{ - idx: 0, - tokens: token.Tokens{}, - isSingleLine: true, + idx: 0, + tokens: token.Tokens{}, } } func newContext(src []rune) *Context { - ctx := ctxPool.Get().(*Context) + ctx, _ := ctxPool.Get().(*Context) ctx.reset(src) return ctx } @@ -51,6 +54,18 @@ func (c *Context) release() { ctxPool.Put(c) } +func (c *Context) clear() { + c.resetBuffer() + c.isRawFolded = false + c.isLiteral = false + c.isFolded = false + c.docOpt = "" + c.docFirstLineIndentColumn = 0 + c.docLineIndentColumn = 0 + c.docPrevLineIndentColumn = 0 + c.docFoldedNewLine = false +} + func (c *Context) reset(src []rune) { c.idx = 0 c.size = len(src) @@ -58,10 +73,9 @@ func (c *Context) reset(src []rune) { c.tokens = c.tokens[:0] c.resetBuffer() c.isRawFolded = false - c.isSingleLine = true c.isLiteral = false c.isFolded = false - c.literalOpt = "" + c.docOpt = "" } func (c *Context) resetBuffer() { @@ -71,15 +85,101 @@ func (c *Context) resetBuffer() { c.notSpaceOrgCharPos = 0 } -func (c *Context) isSaveIndentMode() bool { - return c.isLiteral || c.isFolded || c.isRawFolded -} - -func (c *Context) breakLiteral() { +func (c *Context) breakDocument() { c.isLiteral = false c.isRawFolded = false c.isFolded = false - c.literalOpt = "" + c.docOpt = "" + c.docFirstLineIndentColumn = 0 + c.docLineIndentColumn = 0 + c.docPrevLineIndentColumn = 0 + c.docFoldedNewLine = false +} + +func (c *Context) updateDocumentIndentColumn() { + indent := c.docFirstLineIndentColumnByDocOpt() + if indent > 0 { + c.docFirstLineIndentColumn = indent + 1 + } +} + +func (c *Context) docFirstLineIndentColumnByDocOpt() int { + opt := c.docOpt + opt = strings.TrimPrefix(opt, "-") + opt = strings.TrimPrefix(opt, "+") + opt = strings.TrimSuffix(opt, "-") + opt = strings.TrimSuffix(opt, "+") + i, _ := strconv.ParseInt(opt, 10, 64) + return int(i) +} + +func (c *Context) updateDocumentLineIndentColumn(column int) { + if c.docFirstLineIndentColumn == 0 { + c.docFirstLineIndentColumn = column + } + if c.docLineIndentColumn == 0 { + c.docLineIndentColumn = column + } +} + +func (c *Context) validateDocumentLineIndentColumn() error { + if c.docFirstLineIndentColumnByDocOpt() == 0 { + return nil + } + if c.docFirstLineIndentColumn > c.docLineIndentColumn { + return fmt.Errorf("invalid number of indent is specified in the document header") + } + return nil +} + +func (c *Context) updateDocumentNewLineState() { + c.docPrevLineIndentColumn = c.docLineIndentColumn + c.docFoldedNewLine = true + c.docLineIndentColumn = 0 +} + +func (c *Context) isIndentColumn(column int) bool { + if c.docFirstLineIndentColumn == 0 { + return column == 1 + } + return c.docFirstLineIndentColumn > column +} + +func (c *Context) addDocumentIndent(column int) { + if c.docFirstLineIndentColumn == 0 { + return + } + + // If the first line of the document has already been evaluated, the number is treated as the threshold, since the `docFirstLineIndentColumn` is a positive number. + if c.docFirstLineIndentColumn <= column { + // `c.docFoldedNewLine` is a variable that is set to true for every newline. + if (c.isFolded || c.isRawFolded) && c.docFoldedNewLine { + c.docFoldedNewLine = false + } + // Since addBuf ignore space character, add to the buffer directly. + c.buf = append(c.buf, ' ') + c.notSpaceCharPos = len(c.buf) + } +} + +// updateDocumentNewLineInFolded if Folded or RawFolded context and the content on the current line starts at the same column as the previous line, +// treat the new-line-char as a space. +func (c *Context) updateDocumentNewLineInFolded(column int) { + if c.isLiteral { + return + } + + // Folded or RawFolded. + + if !c.docFoldedNewLine { + return + } + if c.docLineIndentColumn == c.docPrevLineIndentColumn { + if len(c.buf) != 0 && c.buf[len(c.buf)-1] == '\n' { + c.buf[len(c.buf)-1] = ' ' + } + } + c.docFoldedNewLine = false } func (c *Context) addToken(tk *token.Token) { @@ -90,7 +190,7 @@ func (c *Context) addToken(tk *token.Token) { } func (c *Context) addBuf(r rune) { - if len(c.buf) == 0 && r == ' ' { + if len(c.buf) == 0 && (r == ' ' || r == '\t') { return } c.buf = append(c.buf, r) @@ -99,6 +199,16 @@ func (c *Context) addBuf(r rune) { } } +func (c *Context) addBufWithTab(r rune) { + if len(c.buf) == 0 && r == ' ' { + return + } + c.buf = append(c.buf, r) + if r != ' ' { + c.notSpaceCharPos = len(c.buf) + } +} + func (c *Context) addOriginBuf(r rune) { c.obuf = append(c.obuf, r) if r != ' ' && r != '\t' { @@ -106,7 +216,7 @@ func (c *Context) addOriginBuf(r rune) { } } -func (c *Context) removeRightSpaceFromBuf() int { +func (c *Context) removeRightSpaceFromBuf() { trimmedBuf := c.obuf[:c.notSpaceOrgCharPos] buflen := len(trimmedBuf) diff := len(c.obuf) - buflen @@ -114,7 +224,6 @@ func (c *Context) removeRightSpaceFromBuf() int { c.obuf = c.obuf[:buflen] c.buf = c.bufferedSrc() } - return diff } func (c *Context) isDocument() bool { @@ -126,7 +235,7 @@ func (c *Context) isEOS() bool { } func (c *Context) isNextEOS() bool { - return len(c.src)-1 <= c.idx+1 + return len(c.src) <= c.idx+1 } func (c *Context) next() bool { @@ -151,18 +260,6 @@ func (c *Context) currentChar() rune { return rune(0) } -func (c *Context) currentCharWithSkipWhitespace() rune { - idx := c.idx - for c.size > idx { - ch := c.src[idx] - if ch != whitespace { - return ch - } - idx++ - } - return rune(0) -} - func (c *Context) nextChar() rune { if c.size > c.idx+1 { return c.src[c.idx+1] @@ -186,36 +283,67 @@ func (c *Context) progress(num int) { c.idx += num } -func (c *Context) nextPos() int { - return c.idx + 1 -} - func (c *Context) existsBuffer() bool { return len(c.bufferedSrc()) != 0 } func (c *Context) bufferedSrc() []rune { src := c.buf[:c.notSpaceCharPos] - if c.isDocument() && c.literalOpt == "-" { - // remove end '\n' character and trailing empty lines + if c.isDocument() { + // remove end '\n' character and trailing empty lines. // https://yaml.org/spec/1.2.2/#8112-block-chomping-indicator - for { - if len(src) > 0 && src[len(src)-1] == '\n' { - src = src[:len(src)-1] - continue + if c.hasTrimAllEndNewlineOpt() { + // If the '-' flag is specified, all trailing newline characters will be removed. + src = []rune(strings.TrimRight(string(src), "\n")) + } else if !c.hasKeepAllEndNewlineOpt() { + // Normally, all but one of the trailing newline characters are removed. + var newLineCharCount int + for i := len(src) - 1; i >= 0; i-- { + if src[i] == '\n' { + newLineCharCount++ + continue + } + break + } + removedNewLineCharCount := newLineCharCount - 1 + for removedNewLineCharCount > 0 { + src = []rune(strings.TrimSuffix(string(src), "\n")) + removedNewLineCharCount-- } - break + } + + // If the text ends with a space character, remove all of them. + if c.hasTrimAllEndNewlineOpt() { + src = []rune(strings.TrimRight(string(src), " ")) + } + if string(src) == "\n" { + // If the content consists only of a newline, + // it can be considered as the document ending without any specified value, + // so it is treated as an empty string. + src = []rune{} + } + if c.hasKeepAllEndNewlineOpt() && len(src) == 0 { + src = []rune{'\n'} } } return src } +func (c *Context) hasTrimAllEndNewlineOpt() bool { + return strings.HasPrefix(c.docOpt, "-") || strings.HasSuffix(c.docOpt, "-") || c.isRawFolded +} + +func (c *Context) hasKeepAllEndNewlineOpt() bool { + return strings.HasPrefix(c.docOpt, "+") || strings.HasSuffix(c.docOpt, "+") +} + func (c *Context) bufferedToken(pos *token.Position) *token.Token { if c.idx == 0 { return nil } source := c.bufferedSrc() if len(source) == 0 { + c.buf = c.buf[:0] // clear value's buffer only. return nil } var tk *token.Token @@ -224,10 +352,25 @@ func (c *Context) bufferedToken(pos *token.Position) *token.Token { } else { tk = token.New(string(source), string(c.obuf), pos) } + c.setTokenTypeByPrevTag(tk) c.resetBuffer() return tk } +func (c *Context) setTokenTypeByPrevTag(tk *token.Token) { + lastTk := c.lastToken() + if lastTk == nil { + return + } + if lastTk.Type != token.TagType { + return + } + tag := token.ReservedTagKeyword(lastTk.Value) + if _, exists := token.ReservedTagKeywordMap[tag]; !exists { + tk.Type = token.StringType + } +} + func (c *Context) lastToken() *token.Token { if len(c.tokens) != 0 { return c.tokens[len(c.tokens)-1] diff --git a/vendor/github.com/goccy/go-yaml/scanner/error.go b/vendor/github.com/goccy/go-yaml/scanner/error.go new file mode 100644 index 0000000..3f5419a --- /dev/null +++ b/vendor/github.com/goccy/go-yaml/scanner/error.go @@ -0,0 +1,17 @@ +package scanner + +import "github.com/goccy/go-yaml/token" + +type InvalidTokenError struct { + Token *token.Token +} + +func (e *InvalidTokenError) Error() string { + return e.Token.Error +} + +func ErrInvalidToken(tk *token.Token) *InvalidTokenError { + return &InvalidTokenError{ + Token: tk, + } +} diff --git a/vendor/github.com/goccy/go-yaml/scanner/scanner.go b/vendor/github.com/goccy/go-yaml/scanner/scanner.go index 77acb41..a82ee6b 100644 --- a/vendor/github.com/goccy/go-yaml/scanner/scanner.go +++ b/vendor/github.com/goccy/go-yaml/scanner/scanner.go @@ -1,11 +1,12 @@ package scanner import ( + "errors" + "fmt" "io" + "strconv" "strings" - "golang.org/x/xerrors" - "github.com/goccy/go-yaml/token" ) @@ -26,20 +27,27 @@ const ( // Scanner holds the scanner's internal state while processing a given text. // It can be allocated as part of another data structure but must be initialized via Init before use. type Scanner struct { - source []rune - sourcePos int - sourceSize int - line int - column int - offset int - prevIndentLevel int - prevIndentNum int - prevIndentColumn int - docStartColumn int + source []rune + sourcePos int + sourceSize int + // line number. This number starts from 1. + line int + // column number. This number starts from 1. + column int + // offset represents the offset from the beginning of the source. + offset int + // lastDelimColumn is the last column needed to compare indent is retained. + lastDelimColumn int + // indentNum indicates the number of spaces used for indentation. + indentNum int + // prevLineIndentNum indicates the number of spaces used for indentation at previous line. + prevLineIndentNum int + // indentLevel indicates the level of indent depth. This value does not match the column value. indentLevel int - indentNum int isFirstCharAtLine bool isAnchor bool + isAlias bool + isDirective bool startedFlowSequenceNum int startedFlowMapNum int indentState IndentState @@ -65,7 +73,7 @@ func (s *Scanner) bufferedToken(ctx *Context) *token.Token { line := s.line column := s.column - len(ctx.buf) level := s.indentLevel - if ctx.isSaveIndentMode() { + if ctx.isDocument() { line -= s.newLineCount(ctx.buf) column = strings.Index(string(ctx.obuf), string(ctx.buf)) + 1 // Since we are in a literal, folded or raw folded @@ -87,30 +95,25 @@ func (s *Scanner) bufferedToken(ctx *Context) *token.Token { func (s *Scanner) progressColumn(ctx *Context, num int) { s.column += num s.offset += num - ctx.progress(num) + s.progress(ctx, num) } func (s *Scanner) progressLine(ctx *Context) { + s.prevLineIndentNum = s.indentNum s.column = 1 s.line++ s.offset++ s.indentNum = 0 s.isFirstCharAtLine = true s.isAnchor = false - ctx.progress(1) + s.isAlias = false + s.isDirective = false + s.progress(ctx, 1) } -func (s *Scanner) isNeededKeepPreviousIndentNum(ctx *Context, c rune) bool { - if !s.isChangedToIndentStateUp() { - return false - } - if ctx.isDocument() { - return true - } - if c == '-' && ctx.existsBuffer() { - return true - } - return false +func (s *Scanner) progress(ctx *Context, num int) { + ctx.progress(num) + s.sourcePos += num } func (s *Scanner) isNewLineChar(c rune) bool { @@ -141,67 +144,61 @@ func (s *Scanner) newLineCount(src []rune) int { return cnt } -func (s *Scanner) updateIndentState(ctx *Context) { - indentNumBasedIndentState := s.indentState - if s.prevIndentNum < s.indentNum { - s.indentLevel = s.prevIndentLevel + 1 - indentNumBasedIndentState = IndentStateUp - } else if s.prevIndentNum == s.indentNum { - s.indentLevel = s.prevIndentLevel - indentNumBasedIndentState = IndentStateEqual - } else { - indentNumBasedIndentState = IndentStateDown - if s.prevIndentLevel > 0 { - s.indentLevel = s.prevIndentLevel - 1 +func (s *Scanner) updateIndentLevel() { + if s.prevLineIndentNum < s.indentNum { + s.indentLevel++ + } else if s.prevLineIndentNum > s.indentNum { + if s.indentLevel > 0 { + s.indentLevel-- } } +} - if s.prevIndentColumn > 0 { - if s.prevIndentColumn < s.column { +func (s *Scanner) updateIndentState(ctx *Context) { + if s.lastDelimColumn > 0 { + if s.lastDelimColumn < s.column { s.indentState = IndentStateUp - } else if s.prevIndentColumn != s.column || indentNumBasedIndentState != IndentStateEqual { - // The following case ( current position is 'd' ), some variables becomes like here - // - prevIndentColumn: 1 of 'a' - // - indentNumBasedIndentState: IndentStateDown because d's indentNum(1) is less than c's indentNum(3). - // Therefore, s.prevIndentColumn(1) == s.column(1) is true, but we want to treat this as IndentStateDown. - // So, we look also current indentState value by the above prevIndentNum based logic, and determins finally indentState. - // --- - // a: - // b - // c - // d: e - // ^ - s.indentState = IndentStateDown } else { - s.indentState = IndentStateEqual + // If lastDelimColumn and s.column are the same, + // treat as Down state since it is the same column as delimiter. + s.indentState = IndentStateDown } } else { - s.indentState = indentNumBasedIndentState + s.indentState = s.indentStateFromIndentNumDifference() + } +} + +func (s *Scanner) indentStateFromIndentNumDifference() IndentState { + switch { + case s.prevLineIndentNum < s.indentNum: + return IndentStateUp + case s.prevLineIndentNum == s.indentNum: + return IndentStateEqual + default: + return IndentStateDown } } func (s *Scanner) updateIndent(ctx *Context, c rune) { - if s.isFirstCharAtLine && s.isNewLineChar(c) && ctx.isDocument() { + if s.isFirstCharAtLine && s.isNewLineChar(c) { return } if s.isFirstCharAtLine && c == ' ' { s.indentNum++ return } + if s.isFirstCharAtLine && c == '\t' { + // found tab indent. + // In this case, scanTab returns error. + return + } if !s.isFirstCharAtLine { s.indentState = IndentStateKeep return } + s.updateIndentLevel() s.updateIndentState(ctx) s.isFirstCharAtLine = false - if s.isNeededKeepPreviousIndentNum(ctx, c) { - return - } - if s.indentState != IndentStateUp { - s.prevIndentColumn = 0 - } - s.prevIndentNum = s.indentNum - s.prevIndentLevel = s.indentLevel } func (s *Scanner) isChangedToIndentStateDown() bool { @@ -212,20 +209,15 @@ func (s *Scanner) isChangedToIndentStateUp() bool { return s.indentState == IndentStateUp } -func (s *Scanner) isChangedToIndentStateEqual() bool { - return s.indentState == IndentStateEqual -} - func (s *Scanner) addBufferedTokenIfExists(ctx *Context) { ctx.addToken(s.bufferedToken(ctx)) } -func (s *Scanner) breakLiteral(ctx *Context) { - s.docStartColumn = 0 - ctx.breakLiteral() +func (s *Scanner) breakDocument(ctx *Context) { + ctx.breakDocument() } -func (s *Scanner) scanSingleQuote(ctx *Context) (tk *token.Token, pos int) { +func (s *Scanner) scanSingleQuote(ctx *Context) (*token.Token, error) { ctx.addOriginBuf('\'') srcpos := s.pos() startIndex := ctx.idx + 1 @@ -234,6 +226,7 @@ func (s *Scanner) scanSingleQuote(ctx *Context) (tk *token.Token, pos int) { value := []rune{} isFirstLineChar := false isNewLine := false + for idx := startIndex; idx < size; idx++ { if !isNewLine { s.progressColumn(ctx, 1) @@ -241,34 +234,57 @@ func (s *Scanner) scanSingleQuote(ctx *Context) (tk *token.Token, pos int) { isNewLine = false } c := src[idx] - pos = idx + 1 ctx.addOriginBuf(c) if s.isNewLineChar(c) { - value = append(value, ' ') + notSpaceIdx := -1 + for i := len(value) - 1; i >= 0; i-- { + if value[i] == ' ' { + continue + } + notSpaceIdx = i + break + } + if len(value) > notSpaceIdx { + value = value[:notSpaceIdx+1] + } + if isFirstLineChar { + value = append(value, '\n') + } else { + value = append(value, ' ') + } isFirstLineChar = true isNewLine = true s.progressLine(ctx) + if idx+1 < size { + if err := s.validateDocumentSeparatorMarker(ctx, src[idx+1:]); err != nil { + return nil, err + } + } continue - } else if c == ' ' && isFirstLineChar { + } else if isFirstLineChar && (c == ' ' || c == '\t') { continue } else if c != '\'' { value = append(value, c) isFirstLineChar = false continue - } - if idx+1 < len(ctx.src) && ctx.src[idx+1] == '\'' { + } else if idx+1 < len(ctx.src) && ctx.src[idx+1] == '\'' { // '' handle as ' character value = append(value, c) ctx.addOriginBuf(c) idx++ + s.progressColumn(ctx, 1) continue } s.progressColumn(ctx, 1) - tk = token.SingleQuote(string(value), string(ctx.obuf), srcpos) - pos = idx - startIndex + 1 - return + return token.SingleQuote(string(value), string(ctx.obuf), srcpos), nil } - return + s.progressColumn(ctx, 1) + return nil, ErrInvalidToken( + token.Invalid( + "could not find end character of single-quoted text", + string(ctx.obuf), srcpos, + ), + ) } func hexToInt(b rune) int { @@ -289,7 +305,7 @@ func hexRunesToInt(b []rune) int { return sum } -func (s *Scanner) scanDoubleQuote(ctx *Context) (tk *token.Token, pos int) { +func (s *Scanner) scanDoubleQuote(ctx *Context) (*token.Token, error) { ctx.addOriginBuf('"') srcpos := s.pos() startIndex := ctx.idx + 1 @@ -298,6 +314,7 @@ func (s *Scanner) scanDoubleQuote(ctx *Context) (tk *token.Token, pos int) { value := []rune{} isFirstLineChar := false isNewLine := false + for idx := startIndex; idx < size; idx++ { if !isNewLine { s.progressColumn(ctx, 1) @@ -305,15 +322,34 @@ func (s *Scanner) scanDoubleQuote(ctx *Context) (tk *token.Token, pos int) { isNewLine = false } c := src[idx] - pos = idx + 1 ctx.addOriginBuf(c) if s.isNewLineChar(c) { - value = append(value, ' ') + notSpaceIdx := -1 + for i := len(value) - 1; i >= 0; i-- { + if value[i] == ' ' { + continue + } + notSpaceIdx = i + break + } + if len(value) > notSpaceIdx { + value = value[:notSpaceIdx+1] + } + if isFirstLineChar { + value = append(value, '\n') + } else { + value = append(value, ' ') + } isFirstLineChar = true isNewLine = true s.progressLine(ctx) + if idx+1 < size { + if err := s.validateDocumentSeparatorMarker(ctx, src[idx+1:]); err != nil { + return nil, err + } + } continue - } else if c == ' ' && isFirstLineChar { + } else if isFirstLineChar && (c == ' ' || c == '\t') { continue } else if c == '\\' { isFirstLineChar = false @@ -324,105 +360,275 @@ func (s *Scanner) scanDoubleQuote(ctx *Context) (tk *token.Token, pos int) { nextChar := src[idx+1] progress := 0 switch nextChar { - case 'b': + case '0': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, '\b') - case 'e': + value = append(value, 0x00) + case 'a': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, '\x1B') - case 'f': + value = append(value, 0x07) + case 'b': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, '\f') - case 'n': + value = append(value, 0x08) + case 't': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, '\n') - case 'r': + value = append(value, 0x09) + case 'n': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, '\r') + value = append(value, 0x0A) case 'v': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, '\v') - case 'L': // LS (#x2028) + value = append(value, 0x0B) + case 'f': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, []rune{'\xE2', '\x80', '\xA8'}...) - case 'N': // NEL (#x85) + value = append(value, 0x0C) + case 'r': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, []rune{'\xC2', '\x85'}...) - case 'P': // PS (#x2029) + value = append(value, 0x0D) + case 'e': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, []rune{'\xE2', '\x80', '\xA9'}...) - case '_': // #xA0 + value = append(value, 0x1B) + case ' ': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, []rune{'\xC2', '\xA0'}...) + value = append(value, 0x20) case '"': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, nextChar) + value = append(value, 0x22) + case '/': + progress = 1 + ctx.addOriginBuf(nextChar) + value = append(value, 0x2F) + case '\\': + progress = 1 + ctx.addOriginBuf(nextChar) + value = append(value, 0x5C) + case 'N': + progress = 1 + ctx.addOriginBuf(nextChar) + value = append(value, 0x85) + case '_': + progress = 1 + ctx.addOriginBuf(nextChar) + value = append(value, 0xA0) + case 'L': + progress = 1 + ctx.addOriginBuf(nextChar) + value = append(value, 0x2028) + case 'P': + progress = 1 + ctx.addOriginBuf(nextChar) + value = append(value, 0x2029) case 'x': - progress = 3 - if idx+progress >= size { - // TODO: need to return error - //err = xerrors.New("invalid escape character \\x") - return + if idx+3 >= size { + progress = 1 + ctx.addOriginBuf(nextChar) + value = append(value, nextChar) + } else { + progress = 3 + codeNum := hexRunesToInt(src[idx+2 : idx+progress+1]) + value = append(value, rune(codeNum)) } - codeNum := hexRunesToInt(src[idx+2 : idx+progress+1]) - value = append(value, rune(codeNum)) case 'u': + // \u0000 style must have 5 characters at least. + if idx+5 >= size { + return nil, ErrInvalidToken( + token.Invalid( + "not enough length for escaped UTF-16 character", + string(ctx.obuf), s.pos(), + ), + ) + } progress = 5 - if idx+progress >= size { - // TODO: need to return error - //err = xerrors.New("invalid escape character \\u") - return + codeNum := hexRunesToInt(src[idx+2 : idx+6]) + + // handle surrogate pairs. + if codeNum >= 0xD800 && codeNum <= 0xDBFF { + high := codeNum + + // \u0000\u0000 style must have 11 characters at least. + if idx+11 >= size { + return nil, ErrInvalidToken( + token.Invalid( + "not enough length for escaped UTF-16 surrogate pair", + string(ctx.obuf), s.pos(), + ), + ) + } + + if src[idx+6] != '\\' || src[idx+7] != 'u' { + return nil, ErrInvalidToken( + token.Invalid( + "found unexpected character after high surrogate for UTF-16 surrogate pair", + string(ctx.obuf), s.pos(), + ), + ) + } + + low := hexRunesToInt(src[idx+8 : idx+12]) + if low < 0xDC00 || low > 0xDFFF { + return nil, ErrInvalidToken( + token.Invalid( + "found unexpected low surrogate after high surrogate", + string(ctx.obuf), s.pos(), + ), + ) + } + codeNum = ((high - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000 + progress += 6 } - codeNum := hexRunesToInt(src[idx+2 : idx+progress+1]) value = append(value, rune(codeNum)) case 'U': - progress = 9 - if idx+progress >= size { - // TODO: need to return error - //err = xerrors.New("invalid escape character \\U") - return + // \U00000000 style must have 9 characters at least. + if idx+9 >= size { + return nil, ErrInvalidToken( + token.Invalid( + "not enough length for escaped UTF-32 character", + string(ctx.obuf), s.pos(), + ), + ) } - codeNum := hexRunesToInt(src[idx+2 : idx+progress+1]) + progress = 9 + codeNum := hexRunesToInt(src[idx+2 : idx+10]) value = append(value, rune(codeNum)) - case '\\': + case '\n': + isFirstLineChar = true + isNewLine = true + ctx.addOriginBuf(nextChar) + s.progressColumn(ctx, 1) + s.progressLine(ctx) + idx++ + continue + case '\t': progress = 1 ctx.addOriginBuf(nextChar) - value = append(value, c) + value = append(value, nextChar) default: - value = append(value, c) + s.progressColumn(ctx, 1) + return nil, ErrInvalidToken( + token.Invalid( + fmt.Sprintf("found unknown escape character %q", nextChar), + string(ctx.obuf), s.pos(), + ), + ) } idx += progress s.progressColumn(ctx, progress) continue + } else if c == '\t' { + var ( + foundNotSpaceChar bool + progress int + ) + for i := idx + 1; i < size; i++ { + if src[i] == ' ' || src[i] == '\t' { + progress++ + continue + } + if s.isNewLineChar(src[i]) { + break + } + foundNotSpaceChar = true + } + if foundNotSpaceChar { + value = append(value, c) + if src[idx+1] != '"' { + s.progressColumn(ctx, 1) + } + } else { + idx += progress + s.progressColumn(ctx, progress) + } + continue } else if c != '"' { value = append(value, c) isFirstLineChar = false continue } s.progressColumn(ctx, 1) - tk = token.DoubleQuote(string(value), string(ctx.obuf), srcpos) - pos = idx - startIndex + 1 - return + return token.DoubleQuote(string(value), string(ctx.obuf), srcpos), nil } - return + s.progressColumn(ctx, 1) + return nil, ErrInvalidToken( + token.Invalid( + "could not find end character of double-quoted text", + string(ctx.obuf), srcpos, + ), + ) } -func (s *Scanner) scanQuote(ctx *Context, ch rune) (tk *token.Token, pos int) { +func (s *Scanner) validateDocumentSeparatorMarker(ctx *Context, src []rune) error { + if s.foundDocumentSeparatorMarker(src) { + return ErrInvalidToken( + token.Invalid("found unexpected document separator", string(ctx.obuf), s.pos()), + ) + } + return nil +} + +func (s *Scanner) foundDocumentSeparatorMarker(src []rune) bool { + if len(src) < 3 { + return false + } + var marker string + if len(src) == 3 { + marker = string(src) + } else { + marker = strings.TrimRightFunc(string(src[:4]), func(r rune) bool { + return r == ' ' || r == '\t' || r == '\n' || r == '\r' + }) + } + return marker == "---" || marker == "..." +} + +func (s *Scanner) scanQuote(ctx *Context, ch rune) (bool, error) { + if ctx.existsBuffer() { + return false, nil + } if ch == '\'' { - return s.scanSingleQuote(ctx) + tk, err := s.scanSingleQuote(ctx) + if err != nil { + return false, err + } + ctx.addToken(tk) + } else { + tk, err := s.scanDoubleQuote(ctx) + if err != nil { + return false, err + } + ctx.addToken(tk) + } + ctx.clear() + return true, nil +} + +func (s *Scanner) scanWhiteSpace(ctx *Context) bool { + if ctx.isDocument() { + return false + } + if !s.isAnchor && !s.isAlias && !s.isFirstCharAtLine { + return false } - return s.scanDoubleQuote(ctx) + + if s.isFirstCharAtLine { + s.progressColumn(ctx, 1) + ctx.addOriginBuf(' ') + return true + } + + s.addBufferedTokenIfExists(ctx) + s.isAnchor = false + s.isAlias = false + return true } func (s *Scanner) isMergeKey(ctx *Context) bool { @@ -449,28 +655,61 @@ func (s *Scanner) isMergeKey(ctx *Context) bool { return false } -func (s *Scanner) scanTag(ctx *Context) (tk *token.Token, pos int) { +func (s *Scanner) scanTag(ctx *Context) bool { + if ctx.existsBuffer() { + return false + } + ctx.addOriginBuf('!') - ctx.progress(1) // skip '!' character + s.progress(ctx, 1) // skip '!' character + + var progress int for idx, c := range ctx.src[ctx.idx:] { - pos = idx + 1 - ctx.addOriginBuf(c) + progress = idx + 1 switch c { - case ' ', '\n', '\r': + case ' ': + ctx.addOriginBuf(c) + value := ctx.source(ctx.idx-1, ctx.idx+idx) + ctx.addToken(token.Tag(value, string(ctx.obuf), s.pos())) + s.progressColumn(ctx, len([]rune(value))) + ctx.clear() + return true + case ',': + if s.startedFlowSequenceNum > 0 || s.startedFlowMapNum > 0 { + value := ctx.source(ctx.idx-1, ctx.idx+idx) + ctx.addToken(token.Tag(value, string(ctx.obuf), s.pos())) + s.progressColumn(ctx, len([]rune(value))-1) // progress column before collect-entry for scanning it at scanFlowEntry function. + ctx.clear() + return true + } else { + ctx.addOriginBuf(c) + } + case '\n', '\r': + ctx.addOriginBuf(c) value := ctx.source(ctx.idx-1, ctx.idx+idx) - tk = token.Tag(value, string(ctx.obuf), s.pos()) - pos = len([]rune(value)) - return + ctx.addToken(token.Tag(value, string(ctx.obuf), s.pos())) + s.progressColumn(ctx, len([]rune(value))-1) // progress column before new-line-char for scanning new-line-char at scanNewLine function. + ctx.clear() + return true + default: + ctx.addOriginBuf(c) } } - return + s.progressColumn(ctx, progress) + ctx.clear() + return true } -func (s *Scanner) scanComment(ctx *Context) (tk *token.Token, pos int) { +func (s *Scanner) scanComment(ctx *Context) bool { + if ctx.existsBuffer() && (ctx.previousChar() != ' ' && ctx.previousChar() != '\t') { + return false + } + + s.addBufferedTokenIfExists(ctx) ctx.addOriginBuf('#') - ctx.progress(1) // skip '#' character + s.progress(ctx, 1) // skip '#' character + for idx, c := range ctx.src[ctx.idx:] { - pos = idx + 1 ctx.addOriginBuf(c) switch c { case '\n', '\r': @@ -478,127 +717,89 @@ func (s *Scanner) scanComment(ctx *Context) (tk *token.Token, pos int) { continue } value := ctx.source(ctx.idx, ctx.idx+idx) - tk = token.Comment(value, string(ctx.obuf), s.pos()) - pos = len([]rune(value)) + 1 - return + progress := len([]rune(value)) + ctx.addToken(token.Comment(value, string(ctx.obuf), s.pos())) + s.progressColumn(ctx, progress) + s.progressLine(ctx) + ctx.clear() + return true } } // document ends with comment. value := string(ctx.src[ctx.idx:]) - tk = token.Comment(value, string(ctx.obuf), s.pos()) - pos = len([]rune(value)) + 1 - return -} - -func trimCommentFromLiteralOpt(text string) (string, error) { - idx := strings.Index(text, "#") - if idx < 0 { - return text, nil - } - if idx == 0 { - return "", xerrors.New("invalid literal header") - } - return text[:idx-1], nil + ctx.addToken(token.Comment(value, string(ctx.obuf), s.pos())) + progress := len([]rune(value)) + s.progressColumn(ctx, progress) + s.progressLine(ctx) + ctx.clear() + return true } -func (s *Scanner) scanLiteral(ctx *Context, c rune) { +func (s *Scanner) scanDocument(ctx *Context, c rune) error { ctx.addOriginBuf(c) if ctx.isEOS() { - if ctx.isLiteral { + if s.isFirstCharAtLine && c == ' ' { + ctx.addDocumentIndent(s.column) + } else { ctx.addBuf(c) } + ctx.updateDocumentLineIndentColumn(s.column) + if err := ctx.validateDocumentLineIndentColumn(); err != nil { + invalidTk := token.Invalid(err.Error(), string(ctx.obuf), s.pos()) + s.progressColumn(ctx, 1) + return ErrInvalidToken(invalidTk) + } value := ctx.bufferedSrc() ctx.addToken(token.String(string(value), string(ctx.obuf), s.pos())) - ctx.resetBuffer() + ctx.clear() s.progressColumn(ctx, 1) } else if s.isNewLineChar(c) { - if ctx.isLiteral { - ctx.addBuf(c) - } else { - ctx.addBuf(' ') - } + ctx.addBuf(c) + ctx.updateDocumentNewLineState() s.progressLine(ctx) - } else if s.isFirstCharAtLine && c == ' ' { - if 0 < s.docStartColumn && s.docStartColumn <= s.column { - ctx.addBuf(c) + if ctx.next() { + if s.foundDocumentSeparatorMarker(ctx.src[ctx.idx:]) { + value := ctx.bufferedSrc() + ctx.addToken(token.String(string(value), string(ctx.obuf), s.pos())) + ctx.clear() + s.breakDocument(ctx) + } } + } else if s.isFirstCharAtLine && c == ' ' { + ctx.addDocumentIndent(s.column) + s.progressColumn(ctx, 1) + } else if s.isFirstCharAtLine && c == '\t' && ctx.isIndentColumn(s.column) { + err := ErrInvalidToken( + token.Invalid( + "found a tab character where an indentation space is expected", + string(ctx.obuf), s.pos(), + ), + ) s.progressColumn(ctx, 1) + return err } else { - if s.docStartColumn == 0 { - s.docStartColumn = s.column + ctx.updateDocumentLineIndentColumn(s.column) + if ctx.docFirstLineIndentColumn > 0 { + s.lastDelimColumn = ctx.docFirstLineIndentColumn - 1 } - ctx.addBuf(c) - s.progressColumn(ctx, 1) - } -} - -func (s *Scanner) scanLiteralHeader(ctx *Context) (pos int, err error) { - header := ctx.currentChar() - ctx.addOriginBuf(header) - ctx.progress(1) // skip '|' or '>' character - for idx, c := range ctx.src[ctx.idx:] { - pos = idx - ctx.addOriginBuf(c) - switch c { - case '\n', '\r': - value := ctx.source(ctx.idx, ctx.idx+idx) - opt := strings.TrimRight(value, " ") - orgOptLen := len(opt) - opt, err = trimCommentFromLiteralOpt(opt) - if err != nil { - return - } - switch opt { - case "", "+", "-", - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9": - hasComment := len(opt) < orgOptLen - if header == '|' { - if hasComment { - commentLen := orgOptLen - len(opt) - headerPos := strings.Index(string(ctx.obuf), "|") - litBuf := ctx.obuf[:len(ctx.obuf)-commentLen-headerPos] - commentBuf := ctx.obuf[len(litBuf):] - ctx.addToken(token.Literal("|"+opt, string(litBuf), s.pos())) - s.column += len(litBuf) - s.offset += len(litBuf) - commentHeader := strings.Index(value, "#") - ctx.addToken(token.Comment(string(value[commentHeader+1:]), string(commentBuf), s.pos())) - } else { - ctx.addToken(token.Literal("|"+opt, string(ctx.obuf), s.pos())) - } - ctx.isLiteral = true - } else if header == '>' { - if hasComment { - commentLen := orgOptLen - len(opt) - headerPos := strings.Index(string(ctx.obuf), ">") - foldedBuf := ctx.obuf[:len(ctx.obuf)-commentLen-headerPos] - commentBuf := ctx.obuf[len(foldedBuf):] - ctx.addToken(token.Folded(">"+opt, string(foldedBuf), s.pos())) - s.column += len(foldedBuf) - s.offset += len(foldedBuf) - commentHeader := strings.Index(value, "#") - ctx.addToken(token.Comment(string(value[commentHeader+1:]), string(commentBuf), s.pos())) - } else { - ctx.addToken(token.Folded(">"+opt, string(ctx.obuf), s.pos())) - } - ctx.isFolded = true - } - s.indentState = IndentStateKeep - ctx.resetBuffer() - ctx.literalOpt = opt - return - } - break + if err := ctx.validateDocumentLineIndentColumn(); err != nil { + invalidTk := token.Invalid(err.Error(), string(ctx.obuf), s.pos()) + s.progressColumn(ctx, 1) + return ErrInvalidToken(invalidTk) } + ctx.updateDocumentNewLineInFolded(s.column) + ctx.addBufWithTab(c) + s.progressColumn(ctx, 1) } - err = xerrors.New("invalid literal header") - return + return nil } func (s *Scanner) scanNewLine(ctx *Context, c rune) { if len(ctx.buf) > 0 && s.savedPos == nil { + bufLen := len(ctx.bufferedSrc()) s.savedPos = s.pos() - s.savedPos.Column -= len(ctx.bufferedSrc()) + s.savedPos.Column -= bufLen + s.savedPos.Offset -= bufLen } // if the following case, origin buffer has unnecessary two spaces. @@ -606,14 +807,7 @@ func (s *Scanner) scanNewLine(ctx *Context, c rune) { // --- // a:[space][space] // b: c - removedNum := ctx.removeRightSpaceFromBuf() - if removedNum > 0 { - s.column -= removedNum - s.offset -= removedNum - if s.savedPos != nil { - s.savedPos.Column -= removedNum - } - } + ctx.removeRightSpaceFromBuf() // There is no problem that we ignore CR which followed by LF and normalize it to LF, because of following YAML1.2 spec. // > Line breaks inside scalar content must be normalized by the YAML processor. Each such line break must be parsed into a single line feed character. @@ -621,254 +815,591 @@ func (s *Scanner) scanNewLine(ctx *Context, c rune) { // > -- https://yaml.org/spec/1.2/spec.html if c == '\r' && ctx.nextChar() == '\n' { ctx.addOriginBuf('\r') - ctx.progress(1) + s.progress(ctx, 1) + s.offset++ c = '\n' } if ctx.isEOS() { s.addBufferedTokenIfExists(ctx) - } else if s.isAnchor { + } else if s.isAnchor || s.isAlias || s.isDirective { s.addBufferedTokenIfExists(ctx) } - ctx.addBuf(' ') + if ctx.existsBuffer() && s.isFirstCharAtLine { + if ctx.buf[len(ctx.buf)-1] == ' ' { + ctx.buf[len(ctx.buf)-1] = '\n' + } else { + ctx.buf = append(ctx.buf, '\n') + } + } else { + ctx.addBuf(' ') + } + ctx.addOriginBuf(c) + s.progressLine(ctx) +} + +func (s *Scanner) isFlowMode() bool { + if s.startedFlowSequenceNum > 0 { + return true + } + if s.startedFlowMapNum > 0 { + return true + } + return false +} + +func (s *Scanner) scanFlowMapStart(ctx *Context) bool { + if ctx.existsBuffer() && !s.isFlowMode() { + return false + } + + s.addBufferedTokenIfExists(ctx) + ctx.addOriginBuf('{') + ctx.addToken(token.MappingStart(string(ctx.obuf), s.pos())) + s.startedFlowMapNum++ + s.progressColumn(ctx, 1) + ctx.clear() + return true +} + +func (s *Scanner) scanFlowMapEnd(ctx *Context) bool { + if s.startedFlowMapNum <= 0 { + return false + } + + s.addBufferedTokenIfExists(ctx) + ctx.addOriginBuf('}') + ctx.addToken(token.MappingEnd(string(ctx.obuf), s.pos())) + s.startedFlowMapNum-- + s.progressColumn(ctx, 1) + ctx.clear() + return true +} + +func (s *Scanner) scanFlowArrayStart(ctx *Context) bool { + if ctx.existsBuffer() && !s.isFlowMode() { + return false + } + + s.addBufferedTokenIfExists(ctx) + ctx.addOriginBuf('[') + ctx.addToken(token.SequenceStart(string(ctx.obuf), s.pos())) + s.startedFlowSequenceNum++ + s.progressColumn(ctx, 1) + ctx.clear() + return true +} + +func (s *Scanner) scanFlowArrayEnd(ctx *Context) bool { + if ctx.existsBuffer() && s.startedFlowSequenceNum <= 0 { + return false + } + + s.addBufferedTokenIfExists(ctx) + ctx.addOriginBuf(']') + ctx.addToken(token.SequenceEnd(string(ctx.obuf), s.pos())) + s.startedFlowSequenceNum-- + s.progressColumn(ctx, 1) + ctx.clear() + return true +} + +func (s *Scanner) scanFlowEntry(ctx *Context, c rune) bool { + if s.startedFlowSequenceNum <= 0 && s.startedFlowMapNum <= 0 { + return false + } + + s.addBufferedTokenIfExists(ctx) ctx.addOriginBuf(c) - ctx.isSingleLine = false + ctx.addToken(token.CollectEntry(string(ctx.obuf), s.pos())) + s.progressColumn(ctx, 1) + ctx.clear() + return true +} + +func (s *Scanner) scanMapDelim(ctx *Context) (bool, error) { + nc := ctx.nextChar() + if s.isDirective || s.isAnchor || s.isAlias { + return false, nil + } + if s.startedFlowMapNum <= 0 && nc != ' ' && nc != '\t' && !s.isNewLineChar(nc) && !ctx.isNextEOS() { + return false, nil + } + + if strings.HasPrefix(strings.TrimPrefix(string(ctx.obuf), " "), "\t") && !strings.HasPrefix(string(ctx.buf), "\t") { + invalidTk := token.Invalid("tab character cannot use as a map key directly", string(ctx.obuf), s.pos()) + s.progressColumn(ctx, 1) + return false, ErrInvalidToken(invalidTk) + } + + // mapping value + tk := s.bufferedToken(ctx) + if tk != nil { + s.lastDelimColumn = tk.Position.Column + ctx.addToken(tk) + } else if tk := ctx.lastToken(); tk != nil { + // If the map key is quote, the buffer does not exist because it has already been cut into tokens. + // Therefore, we need to check the last token. + if tk.Indicator == token.QuotedScalarIndicator { + s.lastDelimColumn = tk.Position.Column + } + } + ctx.addToken(token.MappingValue(s.pos())) + s.progressColumn(ctx, 1) + ctx.clear() + return true, nil +} + +func (s *Scanner) scanDocumentStart(ctx *Context) bool { + if s.indentNum != 0 { + return false + } + if s.column != 1 { + return false + } + if ctx.repeatNum('-') != 3 { + return false + } + if ctx.size > ctx.idx+3 { + c := ctx.src[ctx.idx+3] + if c != ' ' && c != '\t' && c != '\n' && c != '\r' { + return false + } + } + + s.addBufferedTokenIfExists(ctx) + ctx.addToken(token.DocumentHeader(string(ctx.obuf)+"---", s.pos())) + s.progressColumn(ctx, 3) + ctx.clear() + s.clearState() + return true +} + +func (s *Scanner) scanDocumentEnd(ctx *Context) bool { + if s.indentNum != 0 { + return false + } + if s.column != 1 { + return false + } + if ctx.repeatNum('.') != 3 { + return false + } + + s.addBufferedTokenIfExists(ctx) + ctx.addToken(token.DocumentEnd(string(ctx.obuf)+"...", s.pos())) + s.progressColumn(ctx, 3) + ctx.clear() + return true +} + +func (s *Scanner) scanMergeKey(ctx *Context) bool { + if !s.isMergeKey(ctx) { + return false + } + + s.lastDelimColumn = s.column + ctx.addToken(token.MergeKey(string(ctx.obuf)+"<<", s.pos())) + s.progressColumn(ctx, 2) + ctx.clear() + return true +} + +func (s *Scanner) scanRawFoldedChar(ctx *Context) bool { + if !ctx.existsBuffer() { + return false + } + if !s.isChangedToIndentStateUp() { + return false + } + + ctx.updateDocumentLineIndentColumn(s.column) + ctx.isRawFolded = true + ctx.addBuf('-') + ctx.addOriginBuf('-') + s.progressColumn(ctx, 1) + return true +} + +func (s *Scanner) scanSequence(ctx *Context) (bool, error) { + if ctx.existsBuffer() { + return false, nil + } + + nc := ctx.nextChar() + if nc != 0 && nc != ' ' && nc != '\t' && !s.isNewLineChar(nc) { + return false, nil + } + + if strings.HasPrefix(strings.TrimPrefix(string(ctx.obuf), " "), "\t") { + invalidTk := token.Invalid("tab character cannot use as a sequence delimiter", string(ctx.obuf), s.pos()) + s.progressColumn(ctx, 1) + return false, ErrInvalidToken(invalidTk) + } + + s.addBufferedTokenIfExists(ctx) + ctx.addOriginBuf('-') + tk := token.SequenceEntry(string(ctx.obuf), s.pos()) + s.lastDelimColumn = tk.Position.Column + ctx.addToken(tk) + s.progressColumn(ctx, 1) + ctx.clear() + return true, nil +} + +func (s *Scanner) scanDocumentHeader(ctx *Context) (bool, error) { + if ctx.existsBuffer() { + return false, nil + } + + if err := s.scanDocumentHeaderOption(ctx); err != nil { + return false, err + } + ctx.updateDocumentIndentColumn() s.progressLine(ctx) + return true, nil +} + +func (s *Scanner) validateDocumentHeaderOption(opt string) error { + if len(opt) == 0 { + return nil + } + opt = strings.TrimPrefix(opt, "-") + opt = strings.TrimPrefix(opt, "+") + opt = strings.TrimSuffix(opt, "-") + opt = strings.TrimSuffix(opt, "+") + if len(opt) == 0 { + return nil + } + if _, err := strconv.ParseInt(opt, 10, 64); err != nil { + return fmt.Errorf("invalid header option: %q", opt) + } + return nil +} + +func (s *Scanner) scanDocumentHeaderOption(ctx *Context) error { + header := ctx.currentChar() + ctx.addOriginBuf(header) + s.progress(ctx, 1) // skip '|' or '>' character + for idx, c := range ctx.src[ctx.idx:] { + progress := idx + ctx.addOriginBuf(c) + switch c { + case '\n', '\r': + value := strings.TrimRight(ctx.source(ctx.idx, ctx.idx+idx), " ") + commentValueIndex := strings.Index(value, "#") + opt := value + if commentValueIndex > 0 { + opt = value[:commentValueIndex] + } + opt = strings.TrimRightFunc(opt, func(r rune) bool { + return r == ' ' || r == '\t' + }) + if len(opt) != 0 { + if err := s.validateDocumentHeaderOption(opt); err != nil { + invalidTk := token.Invalid(err.Error(), string(ctx.obuf), s.pos()) + s.progressColumn(ctx, progress) + return ErrInvalidToken(invalidTk) + } + } + if s.column == 1 { + s.lastDelimColumn = 1 + } + + commentIndex := strings.Index(string(ctx.obuf), "#") + headerBuf := string(ctx.obuf) + if commentIndex > 0 { + headerBuf = headerBuf[:commentIndex] + } + switch header { + case '|': + ctx.addToken(token.Literal("|"+opt, headerBuf, s.pos())) + ctx.isLiteral = true + case '>': + ctx.addToken(token.Folded(">"+opt, headerBuf, s.pos())) + ctx.isFolded = true + } + if commentIndex > 0 { + comment := string(value[commentValueIndex+1:]) + s.offset += len(headerBuf) + s.column += len(headerBuf) + ctx.addToken(token.Comment(comment, string(ctx.obuf[len(headerBuf):]), s.pos())) + } + s.indentState = IndentStateKeep + ctx.resetBuffer() + ctx.docOpt = opt + s.progressColumn(ctx, progress) + return nil + } + } + text := string(ctx.src[ctx.idx:]) + invalidTk := token.Invalid( + fmt.Sprintf("invalid document header: %q", text), + string(ctx.obuf), s.pos(), + ) + s.progressColumn(ctx, len(text)) + return ErrInvalidToken(invalidTk) +} + +func (s *Scanner) scanMapKey(ctx *Context) bool { + if ctx.existsBuffer() { + return false + } + + nc := ctx.nextChar() + if nc != ' ' && nc != '\t' { + return false + } + + tk := token.MappingKey(s.pos()) + s.lastDelimColumn = tk.Position.Column + ctx.addToken(tk) + s.progressColumn(ctx, 1) + ctx.clear() + return true } -func (s *Scanner) scan(ctx *Context) (pos int) { +func (s *Scanner) scanDirective(ctx *Context) bool { + if ctx.existsBuffer() { + return false + } + if s.indentNum != 0 { + return false + } + + ctx.addToken(token.Directive(string(ctx.obuf)+"%", s.pos())) + s.progressColumn(ctx, 1) + ctx.clear() + s.isDirective = true + return true +} + +func (s *Scanner) scanAnchor(ctx *Context) bool { + if ctx.existsBuffer() { + return false + } + + s.addBufferedTokenIfExists(ctx) + ctx.addOriginBuf('&') + ctx.addToken(token.Anchor(string(ctx.obuf), s.pos())) + s.progressColumn(ctx, 1) + s.isAnchor = true + ctx.clear() + return true +} + +func (s *Scanner) scanAlias(ctx *Context) bool { + if ctx.existsBuffer() { + return false + } + + s.addBufferedTokenIfExists(ctx) + ctx.addOriginBuf('*') + ctx.addToken(token.Alias(string(ctx.obuf), s.pos())) + s.progressColumn(ctx, 1) + s.isAlias = true + ctx.clear() + return true +} + +func (s *Scanner) scanReservedChar(ctx *Context, c rune) error { + if ctx.existsBuffer() { + return nil + } + + ctx.addBuf(c) + ctx.addOriginBuf(c) + err := ErrInvalidToken( + token.Invalid( + fmt.Sprintf("%q is a reserved character", c), + string(ctx.obuf), s.pos(), + ), + ) + s.progressColumn(ctx, 1) + ctx.clear() + return err +} + +func (s *Scanner) scanTab(ctx *Context, c rune) error { + if s.startedFlowSequenceNum > 0 || s.startedFlowMapNum > 0 { + // tabs character is allowed in flow mode. + return nil + } + + if !s.isFirstCharAtLine { + return nil + } + + ctx.addBuf(c) + ctx.addOriginBuf(c) + err := ErrInvalidToken( + token.Invalid("found character '\t' that cannot start any token", + string(ctx.obuf), s.pos(), + ), + ) + s.progressColumn(ctx, 1) + ctx.clear() + return err +} + +func (s *Scanner) scan(ctx *Context) error { for ctx.next() { - pos = ctx.nextPos() c := ctx.currentChar() + // First, change the IndentState. + // If the target character is the first character in a line, IndentState is Up/Down/Equal state. + // The second and subsequent letters are Keep. s.updateIndent(ctx, c) + + // If IndentState is down, tokens are split, so the buffer accumulated until that point needs to be cutted as a token. + if s.isChangedToIndentStateDown() { + s.addBufferedTokenIfExists(ctx) + } if ctx.isDocument() { - if s.isChangedToIndentStateEqual() || - s.isChangedToIndentStateDown() { - s.addBufferedTokenIfExists(ctx) - s.breakLiteral(ctx) + if s.isChangedToIndentStateDown() { + if tk := ctx.lastToken(); tk != nil { + // If literal/folded content is empty, no string token is added. + // Therefore, add an empty string token. + // But if literal/folded token column is 1, it is invalid at down state. + if tk.Position.Column == 1 { + return ErrInvalidToken( + token.Invalid( + "could not find document", + string(ctx.obuf), s.pos(), + ), + ) + } + if tk.Type != token.StringType { + ctx.addToken(token.String("", "", s.pos())) + } + } + s.breakDocument(ctx) } else { - s.scanLiteral(ctx, c) + if err := s.scanDocument(ctx, c); err != nil { + return err + } continue } - } else if s.isChangedToIndentStateDown() { - s.addBufferedTokenIfExists(ctx) - } else if s.isChangedToIndentStateEqual() { - // if first character is new line character, buffer expect to raw folded literal - if len(ctx.obuf) > 0 && s.newLineCount(ctx.obuf) <= 1 { - // doesn't raw folded literal - s.addBufferedTokenIfExists(ctx) - } } switch c { case '{': - if !ctx.existsBuffer() { - ctx.addOriginBuf(c) - ctx.addToken(token.MappingStart(string(ctx.obuf), s.pos())) - s.startedFlowMapNum++ - s.progressColumn(ctx, 1) - return + if s.scanFlowMapStart(ctx) { + continue } case '}': - if !ctx.existsBuffer() || s.startedFlowMapNum > 0 { - ctx.addToken(s.bufferedToken(ctx)) - ctx.addOriginBuf(c) - ctx.addToken(token.MappingEnd(string(ctx.obuf), s.pos())) - s.startedFlowMapNum-- - s.progressColumn(ctx, 1) - return + if s.scanFlowMapEnd(ctx) { + continue } case '.': - if s.indentNum == 0 && s.column == 1 && ctx.repeatNum('.') == 3 { - ctx.addToken(token.DocumentEnd(string(ctx.obuf)+"...", s.pos())) - s.progressColumn(ctx, 3) - pos += 2 - return + if s.scanDocumentEnd(ctx) { + continue } case '<': - if s.isMergeKey(ctx) { - s.prevIndentColumn = s.column - ctx.addToken(token.MergeKey(string(ctx.obuf)+"<<", s.pos())) - s.progressColumn(ctx, 1) - pos++ - return + if s.scanMergeKey(ctx) { + continue } case '-': - if s.indentNum == 0 && s.column == 1 && ctx.repeatNum('-') == 3 { - s.addBufferedTokenIfExists(ctx) - ctx.addToken(token.DocumentHeader(string(ctx.obuf)+"---", s.pos())) - s.progressColumn(ctx, 3) - pos += 2 - return - } - if ctx.existsBuffer() && s.isChangedToIndentStateUp() { - // raw folded - ctx.isRawFolded = true - ctx.addBuf(c) - ctx.addOriginBuf(c) - s.progressColumn(ctx, 1) + if s.scanDocumentStart(ctx) { continue } - if ctx.existsBuffer() { - // '-' is literal - ctx.addBuf(c) - ctx.addOriginBuf(c) - s.progressColumn(ctx, 1) + if s.scanRawFoldedChar(ctx) { continue } - nc := ctx.nextChar() - if nc == ' ' || s.isNewLineChar(nc) { - s.addBufferedTokenIfExists(ctx) - ctx.addOriginBuf(c) - tk := token.SequenceEntry(string(ctx.obuf), s.pos()) - s.prevIndentColumn = tk.Position.Column - ctx.addToken(tk) - s.progressColumn(ctx, 1) - return + scanned, err := s.scanSequence(ctx) + if err != nil { + return err + } + if scanned { + continue } case '[': - if !ctx.existsBuffer() { - ctx.addOriginBuf(c) - ctx.addToken(token.SequenceStart(string(ctx.obuf), s.pos())) - s.startedFlowSequenceNum++ - s.progressColumn(ctx, 1) - return + if s.scanFlowArrayStart(ctx) { + continue } case ']': - if !ctx.existsBuffer() || s.startedFlowSequenceNum > 0 { - s.addBufferedTokenIfExists(ctx) - ctx.addOriginBuf(c) - ctx.addToken(token.SequenceEnd(string(ctx.obuf), s.pos())) - s.startedFlowSequenceNum-- - s.progressColumn(ctx, 1) - return + if s.scanFlowArrayEnd(ctx) { + continue } case ',': - if s.startedFlowSequenceNum > 0 || s.startedFlowMapNum > 0 { - s.addBufferedTokenIfExists(ctx) - ctx.addOriginBuf(c) - ctx.addToken(token.CollectEntry(string(ctx.obuf), s.pos())) - s.progressColumn(ctx, 1) - return + if s.scanFlowEntry(ctx, c) { + continue } case ':': - nc := ctx.nextChar() - if s.startedFlowMapNum > 0 || nc == ' ' || s.isNewLineChar(nc) || ctx.isNextEOS() { - // mapping value - tk := s.bufferedToken(ctx) - if tk != nil { - s.prevIndentColumn = tk.Position.Column - ctx.addToken(tk) - } else if tk := ctx.lastToken(); tk != nil { - // If the map key is quote, the buffer does not exist because it has already been cut into tokens. - // Therefore, we need to check the last token. - if tk.Indicator == token.QuotedScalarIndicator { - s.prevIndentColumn = tk.Position.Column - } - } - ctx.addToken(token.MappingValue(s.pos())) - s.progressColumn(ctx, 1) - return + scanned, err := s.scanMapDelim(ctx) + if err != nil { + return err + } + if scanned { + continue } case '|', '>': - if !ctx.existsBuffer() { - progress, err := s.scanLiteralHeader(ctx) - if err != nil { - // TODO: returns syntax error object - return - } - s.progressColumn(ctx, progress) - s.progressLine(ctx) + scanned, err := s.scanDocumentHeader(ctx) + if err != nil { + return err + } + if scanned { continue } case '!': - if !ctx.existsBuffer() { - token, progress := s.scanTag(ctx) - ctx.addToken(token) - s.progressColumn(ctx, progress) - if c := ctx.previousChar(); s.isNewLineChar(c) { - s.progressLine(ctx) - } - pos += progress - return + if s.scanTag(ctx) { + continue } case '%': - if !ctx.existsBuffer() && s.indentNum == 0 { - ctx.addToken(token.Directive(string(ctx.obuf)+"%", s.pos())) - s.progressColumn(ctx, 1) - return + if s.scanDirective(ctx) { + continue } case '?': - nc := ctx.nextChar() - if !ctx.existsBuffer() && nc == ' ' { - ctx.addToken(token.MappingKey(s.pos())) - s.progressColumn(ctx, 1) - return + if s.scanMapKey(ctx) { + continue } case '&': - if !ctx.existsBuffer() { - s.addBufferedTokenIfExists(ctx) - ctx.addOriginBuf(c) - ctx.addToken(token.Anchor(string(ctx.obuf), s.pos())) - s.progressColumn(ctx, 1) - s.isAnchor = true - return + if s.scanAnchor(ctx) { + continue } case '*': - if !ctx.existsBuffer() { - s.addBufferedTokenIfExists(ctx) - ctx.addOriginBuf(c) - ctx.addToken(token.Alias(string(ctx.obuf), s.pos())) - s.progressColumn(ctx, 1) - return + if s.scanAlias(ctx) { + continue } case '#': - if !ctx.existsBuffer() || ctx.previousChar() == ' ' { - s.addBufferedTokenIfExists(ctx) - token, progress := s.scanComment(ctx) - ctx.addToken(token) - s.progressColumn(ctx, progress) - s.progressLine(ctx) - pos += progress - return + if s.scanComment(ctx) { + continue } case '\'', '"': - if !ctx.existsBuffer() { - token, progress := s.scanQuote(ctx, c) - ctx.addToken(token) - pos += progress - // If the non-whitespace character immediately following the quote is ':', the quote should be treated as a map key. - // Therefore, do not return and continue processing as a normal map key. - if ctx.currentCharWithSkipWhitespace() == ':' { - continue - } - return + scanned, err := s.scanQuote(ctx, c) + if err != nil { + return err + } + if scanned { + continue } case '\r', '\n': s.scanNewLine(ctx, c) continue case ' ': - if ctx.isSaveIndentMode() || (!s.isAnchor && !s.isFirstCharAtLine) { - ctx.addBuf(c) - ctx.addOriginBuf(c) - s.progressColumn(ctx, 1) + if s.scanWhiteSpace(ctx) { continue } - if s.isFirstCharAtLine { - s.progressColumn(ctx, 1) + case '@', '`': + if err := s.scanReservedChar(ctx, c); err != nil { + return err + } + case '\t': + if ctx.existsBuffer() && s.lastDelimColumn == 0 { + // tab indent for plain text (yaml-test-suite's spec-example-7-12-plain-lines). + s.indentNum++ ctx.addOriginBuf(c) + s.progressColumn(ctx, 1) continue } - s.addBufferedTokenIfExists(ctx) - pos-- // to rescan white space at next scanning for adding white space to next buffer. - s.isAnchor = false - return + if err := s.scanTab(ctx, c); err != nil { + return err + } } ctx.addBuf(c) ctx.addOriginBuf(c) s.progressColumn(ctx, 1) } s.addBufferedTokenIfExists(ctx) - return + return nil } // Init prepares the scanner s to tokenize the text src by setting the scanner at the beginning of src. @@ -880,12 +1411,15 @@ func (s *Scanner) Init(text string) { s.line = 1 s.column = 1 s.offset = 1 - s.prevIndentLevel = 0 - s.prevIndentNum = 0 - s.prevIndentColumn = 0 + s.isFirstCharAtLine = true + s.clearState() +} + +func (s *Scanner) clearState() { + s.prevLineIndentNum = 0 + s.lastDelimColumn = 0 s.indentLevel = 0 s.indentNum = 0 - s.isFirstCharAtLine = true } // Scan scans the next token and returns the token collection. The source end is indicated by io.EOF. @@ -895,9 +1429,17 @@ func (s *Scanner) Scan() (token.Tokens, error) { } ctx := newContext(s.source[s.sourcePos:]) defer ctx.release() - progress := s.scan(ctx) - s.sourcePos += progress + var tokens token.Tokens + err := s.scan(ctx) tokens = append(tokens, ctx.tokens...) + + if err != nil { + var invalidTokenErr *InvalidTokenError + if errors.As(err, &invalidTokenErr) { + tokens = append(tokens, invalidTokenErr.Token) + } + return tokens, err + } return tokens, nil } diff --git a/vendor/github.com/goccy/go-yaml/struct.go b/vendor/github.com/goccy/go-yaml/struct.go index a3da8dd..dae4d65 100644 --- a/vendor/github.com/goccy/go-yaml/struct.go +++ b/vendor/github.com/goccy/go-yaml/struct.go @@ -1,10 +1,9 @@ package yaml import ( + "fmt" "reflect" "strings" - - "golang.org/x/xerrors" ) const ( @@ -84,11 +83,7 @@ func isIgnoredStructField(field reflect.StructField) bool { // private field return true } - tag := getTag(field) - if tag == "-" { - return true - } - return false + return getTag(field) == "-" } type StructFieldMap map[string]*StructField @@ -121,7 +116,7 @@ func structFieldMap(structType reflect.Type) (StructFieldMap, error) { } structField := structField(field) if _, exists := renderNameMap[structField.RenderName]; exists { - return nil, xerrors.Errorf("duplicated struct field name %s", structField.RenderName) + return nil, fmt.Errorf("duplicated struct field name %s", structField.RenderName) } structFieldMap[structField.FieldName] = structField renderNameMap[structField.RenderName] = struct{}{} diff --git a/vendor/github.com/goccy/go-yaml/token/token.go b/vendor/github.com/goccy/go-yaml/token/token.go index 14d7622..208ebff 100644 --- a/vendor/github.com/goccy/go-yaml/token/token.go +++ b/vendor/github.com/goccy/go-yaml/token/token.go @@ -2,6 +2,7 @@ package token import ( "fmt" + "strconv" "strings" ) @@ -117,6 +118,8 @@ const ( StringType // BoolType type for Bool token BoolType + // InvalidType type for invalid token + InvalidType ) // String type identifier to text @@ -186,6 +189,8 @@ func (t Type) String() string { return "Infinity" case NanType: return "Nan" + case InvalidType: + return "Invalid" } return "" } @@ -202,6 +207,8 @@ const ( CharacterTypeMiscellaneous // CharacterTypeEscaped type of escaped character CharacterTypeEscaped + // CharacterTypeInvalid type for a invalid token. + CharacterTypeInvalid ) // String character type identifier to text @@ -339,9 +346,12 @@ func reservedKeywordToken(typ Type, value, org string, pos *Position) *Token { func init() { for _, keyword := range reservedNullKeywords { - reservedKeywordMap[keyword] = func(value, org string, pos *Position) *Token { + f := func(value, org string, pos *Position) *Token { return reservedKeywordToken(NullType, value, org, pos) } + + reservedKeywordMap[keyword] = f + reservedEncKeywordMap[keyword] = f } for _, keyword := range reservedBoolKeywords { f := func(value, org string, pos *Position) *Token { @@ -391,6 +401,8 @@ const ( SetTag ReservedTagKeyword = "!!set" // TimestampTag `!!timestamp` tag TimestampTag ReservedTagKeyword = "!!timestamp" + // BooleanTag `!!bool` tag + BooleanTag ReservedTagKeyword = "!!bool" ) var ( @@ -496,102 +508,108 @@ var ( Position: pos, } }, + BooleanTag: func(value, org string, pos *Position) *Token { + return &Token{ + Type: TagType, + CharacterType: CharacterTypeIndicator, + Indicator: NodePropertyIndicator, + Value: value, + Origin: org, + Position: pos, + } + }, } ) -type numType int +type NumberType string const ( - numTypeNone numType = iota - numTypeBinary - numTypeOctet - numTypeHex - numTypeFloat + NumberTypeDecimal NumberType = "decimal" + NumberTypeBinary NumberType = "binary" + NumberTypeOctet NumberType = "octet" + NumberTypeHex NumberType = "hex" + NumberTypeFloat NumberType = "float" ) -type numStat struct { - isNum bool - typ numType +type NumberValue struct { + Type NumberType + Value any + Text string } -func getNumberStat(str string) *numStat { - stat := &numStat{} - if str == "" { - return stat +func ToNumber(value string) *NumberValue { + if len(value) == 0 { + return nil } - if str == "-" || str == "." || str == "+" || str == "_" { - return stat + if strings.HasPrefix(value, "_") { + return nil } - if str[0] == '_' { - return stat + dotCount := strings.Count(value, ".") + if dotCount > 1 { + return nil } - dotFound := false - isNegative := false - isExponent := false - if str[0] == '-' { - isNegative = true + + isNegative := strings.HasPrefix(value, "-") + normalized := strings.ReplaceAll(strings.TrimPrefix(strings.TrimPrefix(value, "+"), "-"), "_", "") + + var ( + typ NumberType + base int + ) + switch { + case strings.HasPrefix(normalized, "0x"): + normalized = strings.TrimPrefix(normalized, "0x") + base = 16 + typ = NumberTypeHex + case strings.HasPrefix(normalized, "0o"): + normalized = strings.TrimPrefix(normalized, "0o") + base = 8 + typ = NumberTypeOctet + case strings.HasPrefix(normalized, "0b"): + normalized = strings.TrimPrefix(normalized, "0b") + base = 2 + typ = NumberTypeBinary + case strings.HasPrefix(normalized, "0") && len(normalized) > 1 && dotCount == 0: + base = 8 + typ = NumberTypeOctet + case dotCount == 1: + typ = NumberTypeFloat + default: + typ = NumberTypeDecimal + base = 10 } - for idx, c := range str { - switch c { - case 'x': - if (isNegative && idx == 2) || (!isNegative && idx == 1) { - continue - } - case 'o': - if (isNegative && idx == 2) || (!isNegative && idx == 1) { - continue - } - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - continue - case 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F': - if (len(str) > 2 && str[0] == '0' && str[1] == 'x') || - (len(str) > 3 && isNegative && str[1] == '0' && str[2] == 'x') { - // hex number - continue - } - if c == 'b' && ((isNegative && idx == 2) || (!isNegative && idx == 1)) { - // binary number - continue - } - if (c == 'e' || c == 'E') && dotFound { - // exponent - isExponent = true - continue - } - case '.': - if dotFound { - // multiple dot - return stat - } - dotFound = true - continue - case '-': - if idx == 0 || isExponent { - continue - } - case '+': - if idx == 0 || isExponent { - continue - } - case '_': - continue + + text := normalized + if isNegative { + text = "-" + text + } + + var v any + if typ == NumberTypeFloat { + f, err := strconv.ParseFloat(text, 64) + if err != nil { + return nil + } + v = f + } else if isNegative { + i, err := strconv.ParseInt(text, base, 64) + if err != nil { + return nil + } + v = i + } else { + u, err := strconv.ParseUint(text, base, 64) + if err != nil { + return nil } - return stat + v = u + } + + return &NumberValue{ + Type: typ, + Value: v, + Text: text, } - stat.isNum = true - switch { - case dotFound: - stat.typ = numTypeFloat - case strings.HasPrefix(str, "0b") || strings.HasPrefix(str, "-0b"): - stat.typ = numTypeBinary - case strings.HasPrefix(str, "0x") || strings.HasPrefix(str, "-0x"): - stat.typ = numTypeHex - case strings.HasPrefix(str, "0o") || strings.HasPrefix(str, "-0o"): - stat.typ = numTypeOctet - case (len(str) > 1 && str[0] == '0') || (len(str) > 1 && str[0] == '-' && str[1] == '0'): - stat.typ = numTypeOctet - } - return stat } func looksLikeTimeValue(value string) bool { @@ -618,7 +636,7 @@ func IsNeedQuoted(value string) bool { if _, exists := reservedEncKeywordMap[value]; exists { return true } - if stat := getNumberStat(value); stat.isNum { + if num := ToNumber(value); num != nil { return true } first := value[0] @@ -663,13 +681,13 @@ func LiteralBlockHeader(value string) string { } } -// New create reserved keyword token or number token and other string token +// New create reserved keyword token or number token and other string token. func New(value string, org string, pos *Position) *Token { fn := reservedKeywordMap[value] if fn != nil { return fn(value, org, pos) } - if stat := getNumberStat(value); stat.isNum { + if num := ToNumber(value); num != nil { tk := &Token{ Type: IntegerType, CharacterType: CharacterTypeMiscellaneous, @@ -678,14 +696,14 @@ func New(value string, org string, pos *Position) *Token { Origin: org, Position: pos, } - switch stat.typ { - case numTypeFloat: + switch num.Type { + case NumberTypeFloat: tk.Type = FloatType - case numTypeBinary: + case NumberTypeBinary: tk.Type = BinaryIntegerType - case numTypeOctet: + case NumberTypeOctet: tk.Type = OctetIntegerType - case numTypeHex: + case NumberTypeHex: tk.Type = HexIntegerType } return tk @@ -709,14 +727,24 @@ func (p *Position) String() string { // Token type for token type Token struct { - Type Type + // Type is a token type. + Type Type + // CharacterType is a character type. CharacterType CharacterType - Indicator Indicator - Value string - Origin string - Position *Position - Next *Token - Prev *Token + // Indicator is a indicator type. + Indicator Indicator + // Value is a string extracted with only meaningful characters, with spaces and such removed. + Value string + // Origin is a string that stores the original text as-is. + Origin string + // Error keeps error message for InvalidToken. + Error string + // Position is a token position. + Position *Position + // Next is a next token reference. + Next *Token + // Prev is a previous token reference. + Prev *Token } // PreviousType previous token type @@ -756,9 +784,26 @@ func (t *Token) Clone() *Token { return &copied } +// Dump outputs token information to stdout for debugging. +func (t *Token) Dump() { + fmt.Printf( + "[TYPE]:%q [CHARTYPE]:%q [INDICATOR]:%q [VALUE]:%q [ORG]:%q [POS(line:column:level:offset)]: %d:%d:%d:%d\n", + t.Type, t.CharacterType, t.Indicator, t.Value, t.Origin, t.Position.Line, t.Position.Column, t.Position.IndentLevel, t.Position.Offset, + ) +} + // Tokens type of token collection type Tokens []*Token +func (t Tokens) InvalidToken() *Token { + for _, tt := range t { + if tt.Type == InvalidType { + return tt + } + } + return nil +} + func (t *Tokens) add(tk *Token) { tokens := *t if len(tokens) == 0 { @@ -782,7 +827,8 @@ func (t *Tokens) Add(tks ...*Token) { // Dump dump all token structures for debugging func (t Tokens) Dump() { for _, tk := range t { - fmt.Printf("- %+v\n", tk) + fmt.Print("- ") + tk.Dump() } } @@ -1054,6 +1100,18 @@ func DocumentEnd(org string, pos *Position) *Token { } } +func Invalid(err string, org string, pos *Position) *Token { + return &Token{ + Type: InvalidType, + CharacterType: CharacterTypeInvalid, + Indicator: NotIndicator, + Value: org, + Origin: org, + Error: err, + Position: pos, + } +} + // DetectLineBreakCharacter detect line break character in only one inside scalar content scope. func DetectLineBreakCharacter(src string) string { nc := strings.Count(src, "\n") diff --git a/vendor/github.com/goccy/go-yaml/yaml.go b/vendor/github.com/goccy/go-yaml/yaml.go index 25b1056..ec2103b 100644 --- a/vendor/github.com/goccy/go-yaml/yaml.go +++ b/vendor/github.com/goccy/go-yaml/yaml.go @@ -9,7 +9,6 @@ import ( "github.com/goccy/go-yaml/ast" "github.com/goccy/go-yaml/internal/errors" - "golang.org/x/xerrors" ) // BytesMarshaler interface may be implemented by types to customize their @@ -80,11 +79,11 @@ func (s MapSlice) ToMap() map[interface{}]interface{} { // of the generated document will reflect the structure of the value itself. // Maps and pointers (to struct, string, int, etc) are accepted as the in value. // -// Struct fields are only marshalled if they are exported (have an upper case -// first letter), and are marshalled using the field name lowercased as the +// Struct fields are only marshaled if they are exported (have an upper case +// first letter), and are marshaled using the field name lowercased as the // default key. Custom keys may be defined via the "yaml" name in the field // tag: the content preceding the first comma is used as the key, and the -// following comma-separated options are used to tweak the marshalling process. +// following comma-separated options are used to tweak the marshaling process. // Conflicting names result in a runtime error. // // The field tag format accepted is: @@ -138,7 +137,7 @@ func MarshalWithOptions(v interface{}, opts ...EncodeOption) ([]byte, error) { func MarshalContext(ctx context.Context, v interface{}, opts ...EncodeOption) ([]byte, error) { var buf bytes.Buffer if err := NewEncoder(&buf, opts...).EncodeContext(ctx, v); err != nil { - return nil, errors.Wrapf(err, "failed to marshal") + return nil, err } return buf.Bytes(), nil } @@ -148,7 +147,7 @@ func ValueToNode(v interface{}, opts ...EncodeOption) (ast.Node, error) { var buf bytes.Buffer node, err := NewEncoder(&buf, opts...).EncodeToNode(v) if err != nil { - return nil, errors.Wrapf(err, "failed to convert value to node") + return nil, err } return node, nil } @@ -161,7 +160,7 @@ func ValueToNode(v interface{}, opts ...EncodeOption) (ast.Node, error) { // lowercased as the default key. Custom keys may be defined via the // "yaml" name in the field tag: the content preceding the first comma // is used as the key, and the following comma-separated options are -// used to tweak the marshalling process (see Marshal). +// used to tweak the marshaling process (see Marshal). // Conflicting names result in a runtime error. // // For example: @@ -192,7 +191,7 @@ func UnmarshalContext(ctx context.Context, data []byte, v interface{}, opts ...D if err == io.EOF { return nil } - return errors.Wrapf(err, "failed to unmarshal") + return err } return nil } @@ -201,7 +200,7 @@ func UnmarshalContext(ctx context.Context, data []byte, v interface{}, opts ...D func NodeToValue(node ast.Node, v interface{}, opts ...DecodeOption) error { var buf bytes.Buffer if err := NewDecoder(&buf, opts...).DecodeFromNode(node, v); err != nil { - return errors.Wrapf(err, "failed to convert node to value") + return err } return nil } @@ -213,11 +212,9 @@ func NodeToValue(node ast.Node, v interface{}, opts ...DecodeOption) error { // If the third argument `inclSource` is true, the error message will // contain snippets of the YAML source that was used. func FormatError(e error, colored, inclSource bool) string { - var pp errors.PrettyPrinter - if xerrors.As(e, &pp) { - var buf bytes.Buffer - pp.PrettyPrint(&errors.Sink{&buf}, colored, inclSource) - return buf.String() + var pe errors.PrettyFormatError + if errors.As(e, &pe) { + return pe.FormatError(colored, inclSource) } return e.Error() @@ -227,11 +224,11 @@ func FormatError(e error, colored, inclSource bool) string { func YAMLToJSON(bytes []byte) ([]byte, error) { var v interface{} if err := UnmarshalWithOptions(bytes, &v, UseOrderedMap()); err != nil { - return nil, errors.Wrapf(err, "failed to unmarshal") + return nil, err } out, err := MarshalWithOptions(v, JSON()) if err != nil { - return nil, errors.Wrapf(err, "failed to marshal with json option") + return nil, err } return out, nil } @@ -240,11 +237,11 @@ func YAMLToJSON(bytes []byte) ([]byte, error) { func JSONToYAML(bytes []byte) ([]byte, error) { var v interface{} if err := UnmarshalWithOptions(bytes, &v, UseOrderedMap()); err != nil { - return nil, errors.Wrapf(err, "failed to unmarshal from json bytes") + return nil, err } out, err := Marshal(v) if err != nil { - return nil, errors.Wrapf(err, "failed to marshal") + return nil, err } return out, nil } diff --git a/vendor/github.com/mattn/go-colorable/LICENSE b/vendor/github.com/mattn/go-colorable/LICENSE deleted file mode 100644 index 91b5cef..0000000 --- a/vendor/github.com/mattn/go-colorable/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Yasuhiro Matsumoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md deleted file mode 100644 index ca04837..0000000 --- a/vendor/github.com/mattn/go-colorable/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# go-colorable - -[![Build Status](https://github.com/mattn/go-colorable/workflows/test/badge.svg)](https://github.com/mattn/go-colorable/actions?query=workflow%3Atest) -[![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable) -[![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) -[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) - -Colorable writer for windows. - -For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.) -This package is possible to handle escape sequence for ansi color on windows. - -## Too Bad! - -![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png) - - -## So Good! - -![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png) - -## Usage - -```go -logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) -logrus.SetOutput(colorable.NewColorableStdout()) - -logrus.Info("succeeded") -logrus.Warn("not correct") -logrus.Error("something error") -logrus.Fatal("panic") -``` - -You can compile above code on non-windows OSs. - -## Installation - -``` -$ go get github.com/mattn/go-colorable -``` - -# License - -MIT - -# Author - -Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go deleted file mode 100644 index 416d1bb..0000000 --- a/vendor/github.com/mattn/go-colorable/colorable_appengine.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build appengine -// +build appengine - -package colorable - -import ( - "io" - "os" - - _ "github.com/mattn/go-isatty" -) - -// NewColorable returns new instance of Writer which handles escape sequence. -func NewColorable(file *os.File) io.Writer { - if file == nil { - panic("nil passed instead of *os.File to NewColorable()") - } - - return file -} - -// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. -func NewColorableStdout() io.Writer { - return os.Stdout -} - -// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. -func NewColorableStderr() io.Writer { - return os.Stderr -} - -// EnableColorsStdout enable colors if possible. -func EnableColorsStdout(enabled *bool) func() { - if enabled != nil { - *enabled = true - } - return func() {} -} diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go deleted file mode 100644 index 766d946..0000000 --- a/vendor/github.com/mattn/go-colorable/colorable_others.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build !windows && !appengine -// +build !windows,!appengine - -package colorable - -import ( - "io" - "os" - - _ "github.com/mattn/go-isatty" -) - -// NewColorable returns new instance of Writer which handles escape sequence. -func NewColorable(file *os.File) io.Writer { - if file == nil { - panic("nil passed instead of *os.File to NewColorable()") - } - - return file -} - -// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. -func NewColorableStdout() io.Writer { - return os.Stdout -} - -// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. -func NewColorableStderr() io.Writer { - return os.Stderr -} - -// EnableColorsStdout enable colors if possible. -func EnableColorsStdout(enabled *bool) func() { - if enabled != nil { - *enabled = true - } - return func() {} -} diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go deleted file mode 100644 index 1846ad5..0000000 --- a/vendor/github.com/mattn/go-colorable/colorable_windows.go +++ /dev/null @@ -1,1047 +0,0 @@ -//go:build windows && !appengine -// +build windows,!appengine - -package colorable - -import ( - "bytes" - "io" - "math" - "os" - "strconv" - "strings" - "sync" - "syscall" - "unsafe" - - "github.com/mattn/go-isatty" -) - -const ( - foregroundBlue = 0x1 - foregroundGreen = 0x2 - foregroundRed = 0x4 - foregroundIntensity = 0x8 - foregroundMask = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity) - backgroundBlue = 0x10 - backgroundGreen = 0x20 - backgroundRed = 0x40 - backgroundIntensity = 0x80 - backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity) - commonLvbUnderscore = 0x8000 - - cENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4 -) - -const ( - genericRead = 0x80000000 - genericWrite = 0x40000000 -) - -const ( - consoleTextmodeBuffer = 0x1 -) - -type wchar uint16 -type short int16 -type dword uint32 -type word uint16 - -type coord struct { - x short - y short -} - -type smallRect struct { - left short - top short - right short - bottom short -} - -type consoleScreenBufferInfo struct { - size coord - cursorPosition coord - attributes word - window smallRect - maximumWindowSize coord -} - -type consoleCursorInfo struct { - size dword - visible int32 -} - -var ( - kernel32 = syscall.NewLazyDLL("kernel32.dll") - procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") - procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute") - procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") - procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW") - procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute") - procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo") - procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo") - procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW") - procGetConsoleMode = kernel32.NewProc("GetConsoleMode") - procSetConsoleMode = kernel32.NewProc("SetConsoleMode") - procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer") -) - -// Writer provides colorable Writer to the console -type Writer struct { - out io.Writer - handle syscall.Handle - althandle syscall.Handle - oldattr word - oldpos coord - rest bytes.Buffer - mutex sync.Mutex -} - -// NewColorable returns new instance of Writer which handles escape sequence from File. -func NewColorable(file *os.File) io.Writer { - if file == nil { - panic("nil passed instead of *os.File to NewColorable()") - } - - if isatty.IsTerminal(file.Fd()) { - var mode uint32 - if r, _, _ := procGetConsoleMode.Call(file.Fd(), uintptr(unsafe.Pointer(&mode))); r != 0 && mode&cENABLE_VIRTUAL_TERMINAL_PROCESSING != 0 { - return file - } - var csbi consoleScreenBufferInfo - handle := syscall.Handle(file.Fd()) - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - return &Writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}} - } - return file -} - -// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. -func NewColorableStdout() io.Writer { - return NewColorable(os.Stdout) -} - -// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. -func NewColorableStderr() io.Writer { - return NewColorable(os.Stderr) -} - -var color256 = map[int]int{ - 0: 0x000000, - 1: 0x800000, - 2: 0x008000, - 3: 0x808000, - 4: 0x000080, - 5: 0x800080, - 6: 0x008080, - 7: 0xc0c0c0, - 8: 0x808080, - 9: 0xff0000, - 10: 0x00ff00, - 11: 0xffff00, - 12: 0x0000ff, - 13: 0xff00ff, - 14: 0x00ffff, - 15: 0xffffff, - 16: 0x000000, - 17: 0x00005f, - 18: 0x000087, - 19: 0x0000af, - 20: 0x0000d7, - 21: 0x0000ff, - 22: 0x005f00, - 23: 0x005f5f, - 24: 0x005f87, - 25: 0x005faf, - 26: 0x005fd7, - 27: 0x005fff, - 28: 0x008700, - 29: 0x00875f, - 30: 0x008787, - 31: 0x0087af, - 32: 0x0087d7, - 33: 0x0087ff, - 34: 0x00af00, - 35: 0x00af5f, - 36: 0x00af87, - 37: 0x00afaf, - 38: 0x00afd7, - 39: 0x00afff, - 40: 0x00d700, - 41: 0x00d75f, - 42: 0x00d787, - 43: 0x00d7af, - 44: 0x00d7d7, - 45: 0x00d7ff, - 46: 0x00ff00, - 47: 0x00ff5f, - 48: 0x00ff87, - 49: 0x00ffaf, - 50: 0x00ffd7, - 51: 0x00ffff, - 52: 0x5f0000, - 53: 0x5f005f, - 54: 0x5f0087, - 55: 0x5f00af, - 56: 0x5f00d7, - 57: 0x5f00ff, - 58: 0x5f5f00, - 59: 0x5f5f5f, - 60: 0x5f5f87, - 61: 0x5f5faf, - 62: 0x5f5fd7, - 63: 0x5f5fff, - 64: 0x5f8700, - 65: 0x5f875f, - 66: 0x5f8787, - 67: 0x5f87af, - 68: 0x5f87d7, - 69: 0x5f87ff, - 70: 0x5faf00, - 71: 0x5faf5f, - 72: 0x5faf87, - 73: 0x5fafaf, - 74: 0x5fafd7, - 75: 0x5fafff, - 76: 0x5fd700, - 77: 0x5fd75f, - 78: 0x5fd787, - 79: 0x5fd7af, - 80: 0x5fd7d7, - 81: 0x5fd7ff, - 82: 0x5fff00, - 83: 0x5fff5f, - 84: 0x5fff87, - 85: 0x5fffaf, - 86: 0x5fffd7, - 87: 0x5fffff, - 88: 0x870000, - 89: 0x87005f, - 90: 0x870087, - 91: 0x8700af, - 92: 0x8700d7, - 93: 0x8700ff, - 94: 0x875f00, - 95: 0x875f5f, - 96: 0x875f87, - 97: 0x875faf, - 98: 0x875fd7, - 99: 0x875fff, - 100: 0x878700, - 101: 0x87875f, - 102: 0x878787, - 103: 0x8787af, - 104: 0x8787d7, - 105: 0x8787ff, - 106: 0x87af00, - 107: 0x87af5f, - 108: 0x87af87, - 109: 0x87afaf, - 110: 0x87afd7, - 111: 0x87afff, - 112: 0x87d700, - 113: 0x87d75f, - 114: 0x87d787, - 115: 0x87d7af, - 116: 0x87d7d7, - 117: 0x87d7ff, - 118: 0x87ff00, - 119: 0x87ff5f, - 120: 0x87ff87, - 121: 0x87ffaf, - 122: 0x87ffd7, - 123: 0x87ffff, - 124: 0xaf0000, - 125: 0xaf005f, - 126: 0xaf0087, - 127: 0xaf00af, - 128: 0xaf00d7, - 129: 0xaf00ff, - 130: 0xaf5f00, - 131: 0xaf5f5f, - 132: 0xaf5f87, - 133: 0xaf5faf, - 134: 0xaf5fd7, - 135: 0xaf5fff, - 136: 0xaf8700, - 137: 0xaf875f, - 138: 0xaf8787, - 139: 0xaf87af, - 140: 0xaf87d7, - 141: 0xaf87ff, - 142: 0xafaf00, - 143: 0xafaf5f, - 144: 0xafaf87, - 145: 0xafafaf, - 146: 0xafafd7, - 147: 0xafafff, - 148: 0xafd700, - 149: 0xafd75f, - 150: 0xafd787, - 151: 0xafd7af, - 152: 0xafd7d7, - 153: 0xafd7ff, - 154: 0xafff00, - 155: 0xafff5f, - 156: 0xafff87, - 157: 0xafffaf, - 158: 0xafffd7, - 159: 0xafffff, - 160: 0xd70000, - 161: 0xd7005f, - 162: 0xd70087, - 163: 0xd700af, - 164: 0xd700d7, - 165: 0xd700ff, - 166: 0xd75f00, - 167: 0xd75f5f, - 168: 0xd75f87, - 169: 0xd75faf, - 170: 0xd75fd7, - 171: 0xd75fff, - 172: 0xd78700, - 173: 0xd7875f, - 174: 0xd78787, - 175: 0xd787af, - 176: 0xd787d7, - 177: 0xd787ff, - 178: 0xd7af00, - 179: 0xd7af5f, - 180: 0xd7af87, - 181: 0xd7afaf, - 182: 0xd7afd7, - 183: 0xd7afff, - 184: 0xd7d700, - 185: 0xd7d75f, - 186: 0xd7d787, - 187: 0xd7d7af, - 188: 0xd7d7d7, - 189: 0xd7d7ff, - 190: 0xd7ff00, - 191: 0xd7ff5f, - 192: 0xd7ff87, - 193: 0xd7ffaf, - 194: 0xd7ffd7, - 195: 0xd7ffff, - 196: 0xff0000, - 197: 0xff005f, - 198: 0xff0087, - 199: 0xff00af, - 200: 0xff00d7, - 201: 0xff00ff, - 202: 0xff5f00, - 203: 0xff5f5f, - 204: 0xff5f87, - 205: 0xff5faf, - 206: 0xff5fd7, - 207: 0xff5fff, - 208: 0xff8700, - 209: 0xff875f, - 210: 0xff8787, - 211: 0xff87af, - 212: 0xff87d7, - 213: 0xff87ff, - 214: 0xffaf00, - 215: 0xffaf5f, - 216: 0xffaf87, - 217: 0xffafaf, - 218: 0xffafd7, - 219: 0xffafff, - 220: 0xffd700, - 221: 0xffd75f, - 222: 0xffd787, - 223: 0xffd7af, - 224: 0xffd7d7, - 225: 0xffd7ff, - 226: 0xffff00, - 227: 0xffff5f, - 228: 0xffff87, - 229: 0xffffaf, - 230: 0xffffd7, - 231: 0xffffff, - 232: 0x080808, - 233: 0x121212, - 234: 0x1c1c1c, - 235: 0x262626, - 236: 0x303030, - 237: 0x3a3a3a, - 238: 0x444444, - 239: 0x4e4e4e, - 240: 0x585858, - 241: 0x626262, - 242: 0x6c6c6c, - 243: 0x767676, - 244: 0x808080, - 245: 0x8a8a8a, - 246: 0x949494, - 247: 0x9e9e9e, - 248: 0xa8a8a8, - 249: 0xb2b2b2, - 250: 0xbcbcbc, - 251: 0xc6c6c6, - 252: 0xd0d0d0, - 253: 0xdadada, - 254: 0xe4e4e4, - 255: 0xeeeeee, -} - -// `\033]0;TITLESTR\007` -func doTitleSequence(er *bytes.Reader) error { - var c byte - var err error - - c, err = er.ReadByte() - if err != nil { - return err - } - if c != '0' && c != '2' { - return nil - } - c, err = er.ReadByte() - if err != nil { - return err - } - if c != ';' { - return nil - } - title := make([]byte, 0, 80) - for { - c, err = er.ReadByte() - if err != nil { - return err - } - if c == 0x07 || c == '\n' { - break - } - title = append(title, c) - } - if len(title) > 0 { - title8, err := syscall.UTF16PtrFromString(string(title)) - if err == nil { - procSetConsoleTitle.Call(uintptr(unsafe.Pointer(title8))) - } - } - return nil -} - -// returns Atoi(s) unless s == "" in which case it returns def -func atoiWithDefault(s string, def int) (int, error) { - if s == "" { - return def, nil - } - return strconv.Atoi(s) -} - -// Write writes data on console -func (w *Writer) Write(data []byte) (n int, err error) { - w.mutex.Lock() - defer w.mutex.Unlock() - var csbi consoleScreenBufferInfo - procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) - - handle := w.handle - - var er *bytes.Reader - if w.rest.Len() > 0 { - var rest bytes.Buffer - w.rest.WriteTo(&rest) - w.rest.Reset() - rest.Write(data) - er = bytes.NewReader(rest.Bytes()) - } else { - er = bytes.NewReader(data) - } - var plaintext bytes.Buffer -loop: - for { - c1, err := er.ReadByte() - if err != nil { - plaintext.WriteTo(w.out) - break loop - } - if c1 != 0x1b { - plaintext.WriteByte(c1) - continue - } - _, err = plaintext.WriteTo(w.out) - if err != nil { - break loop - } - c2, err := er.ReadByte() - if err != nil { - break loop - } - - switch c2 { - case '>': - continue - case ']': - w.rest.WriteByte(c1) - w.rest.WriteByte(c2) - er.WriteTo(&w.rest) - if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 { - break loop - } - er = bytes.NewReader(w.rest.Bytes()[2:]) - err := doTitleSequence(er) - if err != nil { - break loop - } - w.rest.Reset() - continue - // https://github.com/mattn/go-colorable/issues/27 - case '7': - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - w.oldpos = csbi.cursorPosition - continue - case '8': - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) - continue - case 0x5b: - // execute part after switch - default: - continue - } - - w.rest.WriteByte(c1) - w.rest.WriteByte(c2) - er.WriteTo(&w.rest) - - var buf bytes.Buffer - var m byte - for i, c := range w.rest.Bytes()[2:] { - if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { - m = c - er = bytes.NewReader(w.rest.Bytes()[2+i+1:]) - w.rest.Reset() - break - } - buf.Write([]byte(string(c))) - } - if m == 0 { - break loop - } - - switch m { - case 'A': - n, err = atoiWithDefault(buf.String(), 1) - if err != nil { - continue - } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - csbi.cursorPosition.y -= short(n) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) - case 'B': - n, err = atoiWithDefault(buf.String(), 1) - if err != nil { - continue - } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - csbi.cursorPosition.y += short(n) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) - case 'C': - n, err = atoiWithDefault(buf.String(), 1) - if err != nil { - continue - } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - csbi.cursorPosition.x += short(n) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) - case 'D': - n, err = atoiWithDefault(buf.String(), 1) - if err != nil { - continue - } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - csbi.cursorPosition.x -= short(n) - if csbi.cursorPosition.x < 0 { - csbi.cursorPosition.x = 0 - } - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) - case 'E': - n, err = strconv.Atoi(buf.String()) - if err != nil { - continue - } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - csbi.cursorPosition.x = 0 - csbi.cursorPosition.y += short(n) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) - case 'F': - n, err = strconv.Atoi(buf.String()) - if err != nil { - continue - } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - csbi.cursorPosition.x = 0 - csbi.cursorPosition.y -= short(n) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) - case 'G': - n, err = strconv.Atoi(buf.String()) - if err != nil { - continue - } - if n < 1 { - n = 1 - } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - csbi.cursorPosition.x = short(n - 1) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) - case 'H', 'f': - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - if buf.Len() > 0 { - token := strings.Split(buf.String(), ";") - switch len(token) { - case 1: - n1, err := strconv.Atoi(token[0]) - if err != nil { - continue - } - csbi.cursorPosition.y = short(n1 - 1) - case 2: - n1, err := strconv.Atoi(token[0]) - if err != nil { - continue - } - n2, err := strconv.Atoi(token[1]) - if err != nil { - continue - } - csbi.cursorPosition.x = short(n2 - 1) - csbi.cursorPosition.y = short(n1 - 1) - } - } else { - csbi.cursorPosition.y = 0 - } - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) - case 'J': - n := 0 - if buf.Len() > 0 { - n, err = strconv.Atoi(buf.String()) - if err != nil { - continue - } - } - var count, written dword - var cursor coord - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - switch n { - case 0: - cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} - count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x) - case 1: - cursor = coord{x: csbi.window.left, y: csbi.window.top} - count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x) - case 2: - cursor = coord{x: csbi.window.left, y: csbi.window.top} - count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x) - } - procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) - procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) - case 'K': - n := 0 - if buf.Len() > 0 { - n, err = strconv.Atoi(buf.String()) - if err != nil { - continue - } - } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - var cursor coord - var count, written dword - switch n { - case 0: - cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} - count = dword(csbi.size.x - csbi.cursorPosition.x) - case 1: - cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y} - count = dword(csbi.size.x - csbi.cursorPosition.x) - case 2: - cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y} - count = dword(csbi.size.x) - } - procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) - procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) - case 'X': - n := 0 - if buf.Len() > 0 { - n, err = strconv.Atoi(buf.String()) - if err != nil { - continue - } - } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - var cursor coord - var written dword - cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} - procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) - procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) - case 'm': - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - attr := csbi.attributes - cs := buf.String() - if cs == "" { - procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr)) - continue - } - token := strings.Split(cs, ";") - for i := 0; i < len(token); i++ { - ns := token[i] - if n, err = strconv.Atoi(ns); err == nil { - switch { - case n == 0 || n == 100: - attr = w.oldattr - case n == 4: - attr |= commonLvbUnderscore - case (1 <= n && n <= 3) || n == 5: - attr |= foregroundIntensity - case n == 7 || n == 27: - attr = - (attr &^ (foregroundMask | backgroundMask)) | - ((attr & foregroundMask) << 4) | - ((attr & backgroundMask) >> 4) - case n == 22: - attr &^= foregroundIntensity - case n == 24: - attr &^= commonLvbUnderscore - case 30 <= n && n <= 37: - attr &= backgroundMask - if (n-30)&1 != 0 { - attr |= foregroundRed - } - if (n-30)&2 != 0 { - attr |= foregroundGreen - } - if (n-30)&4 != 0 { - attr |= foregroundBlue - } - case n == 38: // set foreground color. - if i < len(token)-2 && (token[i+1] == "5" || token[i+1] == "05") { - if n256, err := strconv.Atoi(token[i+2]); err == nil { - if n256foreAttr == nil { - n256setup() - } - attr &= backgroundMask - attr |= n256foreAttr[n256%len(n256foreAttr)] - i += 2 - } - } else if len(token) == 5 && token[i+1] == "2" { - var r, g, b int - r, _ = strconv.Atoi(token[i+2]) - g, _ = strconv.Atoi(token[i+3]) - b, _ = strconv.Atoi(token[i+4]) - i += 4 - if r > 127 { - attr |= foregroundRed - } - if g > 127 { - attr |= foregroundGreen - } - if b > 127 { - attr |= foregroundBlue - } - } else { - attr = attr & (w.oldattr & backgroundMask) - } - case n == 39: // reset foreground color. - attr &= backgroundMask - attr |= w.oldattr & foregroundMask - case 40 <= n && n <= 47: - attr &= foregroundMask - if (n-40)&1 != 0 { - attr |= backgroundRed - } - if (n-40)&2 != 0 { - attr |= backgroundGreen - } - if (n-40)&4 != 0 { - attr |= backgroundBlue - } - case n == 48: // set background color. - if i < len(token)-2 && token[i+1] == "5" { - if n256, err := strconv.Atoi(token[i+2]); err == nil { - if n256backAttr == nil { - n256setup() - } - attr &= foregroundMask - attr |= n256backAttr[n256%len(n256backAttr)] - i += 2 - } - } else if len(token) == 5 && token[i+1] == "2" { - var r, g, b int - r, _ = strconv.Atoi(token[i+2]) - g, _ = strconv.Atoi(token[i+3]) - b, _ = strconv.Atoi(token[i+4]) - i += 4 - if r > 127 { - attr |= backgroundRed - } - if g > 127 { - attr |= backgroundGreen - } - if b > 127 { - attr |= backgroundBlue - } - } else { - attr = attr & (w.oldattr & foregroundMask) - } - case n == 49: // reset foreground color. - attr &= foregroundMask - attr |= w.oldattr & backgroundMask - case 90 <= n && n <= 97: - attr = (attr & backgroundMask) - attr |= foregroundIntensity - if (n-90)&1 != 0 { - attr |= foregroundRed - } - if (n-90)&2 != 0 { - attr |= foregroundGreen - } - if (n-90)&4 != 0 { - attr |= foregroundBlue - } - case 100 <= n && n <= 107: - attr = (attr & foregroundMask) - attr |= backgroundIntensity - if (n-100)&1 != 0 { - attr |= backgroundRed - } - if (n-100)&2 != 0 { - attr |= backgroundGreen - } - if (n-100)&4 != 0 { - attr |= backgroundBlue - } - } - procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr)) - } - } - case 'h': - var ci consoleCursorInfo - cs := buf.String() - if cs == "5>" { - procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) - ci.visible = 0 - procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) - } else if cs == "?25" { - procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) - ci.visible = 1 - procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) - } else if cs == "?1049" { - if w.althandle == 0 { - h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0) - w.althandle = syscall.Handle(h) - if w.althandle != 0 { - handle = w.althandle - } - } - } - case 'l': - var ci consoleCursorInfo - cs := buf.String() - if cs == "5>" { - procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) - ci.visible = 1 - procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) - } else if cs == "?25" { - procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) - ci.visible = 0 - procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) - } else if cs == "?1049" { - if w.althandle != 0 { - syscall.CloseHandle(w.althandle) - w.althandle = 0 - handle = w.handle - } - } - case 's': - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - w.oldpos = csbi.cursorPosition - case 'u': - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) - } - } - - return len(data), nil -} - -type consoleColor struct { - rgb int - red bool - green bool - blue bool - intensity bool -} - -func (c consoleColor) foregroundAttr() (attr word) { - if c.red { - attr |= foregroundRed - } - if c.green { - attr |= foregroundGreen - } - if c.blue { - attr |= foregroundBlue - } - if c.intensity { - attr |= foregroundIntensity - } - return -} - -func (c consoleColor) backgroundAttr() (attr word) { - if c.red { - attr |= backgroundRed - } - if c.green { - attr |= backgroundGreen - } - if c.blue { - attr |= backgroundBlue - } - if c.intensity { - attr |= backgroundIntensity - } - return -} - -var color16 = []consoleColor{ - {0x000000, false, false, false, false}, - {0x000080, false, false, true, false}, - {0x008000, false, true, false, false}, - {0x008080, false, true, true, false}, - {0x800000, true, false, false, false}, - {0x800080, true, false, true, false}, - {0x808000, true, true, false, false}, - {0xc0c0c0, true, true, true, false}, - {0x808080, false, false, false, true}, - {0x0000ff, false, false, true, true}, - {0x00ff00, false, true, false, true}, - {0x00ffff, false, true, true, true}, - {0xff0000, true, false, false, true}, - {0xff00ff, true, false, true, true}, - {0xffff00, true, true, false, true}, - {0xffffff, true, true, true, true}, -} - -type hsv struct { - h, s, v float32 -} - -func (a hsv) dist(b hsv) float32 { - dh := a.h - b.h - switch { - case dh > 0.5: - dh = 1 - dh - case dh < -0.5: - dh = -1 - dh - } - ds := a.s - b.s - dv := a.v - b.v - return float32(math.Sqrt(float64(dh*dh + ds*ds + dv*dv))) -} - -func toHSV(rgb int) hsv { - r, g, b := float32((rgb&0xFF0000)>>16)/256.0, - float32((rgb&0x00FF00)>>8)/256.0, - float32(rgb&0x0000FF)/256.0 - min, max := minmax3f(r, g, b) - h := max - min - if h > 0 { - if max == r { - h = (g - b) / h - if h < 0 { - h += 6 - } - } else if max == g { - h = 2 + (b-r)/h - } else { - h = 4 + (r-g)/h - } - } - h /= 6.0 - s := max - min - if max != 0 { - s /= max - } - v := max - return hsv{h: h, s: s, v: v} -} - -type hsvTable []hsv - -func toHSVTable(rgbTable []consoleColor) hsvTable { - t := make(hsvTable, len(rgbTable)) - for i, c := range rgbTable { - t[i] = toHSV(c.rgb) - } - return t -} - -func (t hsvTable) find(rgb int) consoleColor { - hsv := toHSV(rgb) - n := 7 - l := float32(5.0) - for i, p := range t { - d := hsv.dist(p) - if d < l { - l, n = d, i - } - } - return color16[n] -} - -func minmax3f(a, b, c float32) (min, max float32) { - if a < b { - if b < c { - return a, c - } else if a < c { - return a, b - } else { - return c, b - } - } else { - if a < c { - return b, c - } else if b < c { - return b, a - } else { - return c, a - } - } -} - -var n256foreAttr []word -var n256backAttr []word - -func n256setup() { - n256foreAttr = make([]word, 256) - n256backAttr = make([]word, 256) - t := toHSVTable(color16) - for i, rgb := range color256 { - c := t.find(rgb) - n256foreAttr[i] = c.foregroundAttr() - n256backAttr[i] = c.backgroundAttr() - } -} - -// EnableColorsStdout enable colors if possible. -func EnableColorsStdout(enabled *bool) func() { - var mode uint32 - h := os.Stdout.Fd() - if r, _, _ := procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&mode))); r != 0 { - if r, _, _ = procSetConsoleMode.Call(h, uintptr(mode|cENABLE_VIRTUAL_TERMINAL_PROCESSING)); r != 0 { - if enabled != nil { - *enabled = true - } - return func() { - procSetConsoleMode.Call(h, uintptr(mode)) - } - } - } - if enabled != nil { - *enabled = true - } - return func() {} -} diff --git a/vendor/github.com/mattn/go-colorable/go.test.sh b/vendor/github.com/mattn/go-colorable/go.test.sh deleted file mode 100644 index 012162b..0000000 --- a/vendor/github.com/mattn/go-colorable/go.test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e -echo "" > coverage.txt - -for d in $(go list ./... | grep -v vendor); do - go test -race -coverprofile=profile.out -covermode=atomic "$d" - if [ -f profile.out ]; then - cat profile.out >> coverage.txt - rm profile.out - fi -done diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go deleted file mode 100644 index 05d6f74..0000000 --- a/vendor/github.com/mattn/go-colorable/noncolorable.go +++ /dev/null @@ -1,57 +0,0 @@ -package colorable - -import ( - "bytes" - "io" -) - -// NonColorable holds writer but removes escape sequence. -type NonColorable struct { - out io.Writer -} - -// NewNonColorable returns new instance of Writer which removes escape sequence from Writer. -func NewNonColorable(w io.Writer) io.Writer { - return &NonColorable{out: w} -} - -// Write writes data on console -func (w *NonColorable) Write(data []byte) (n int, err error) { - er := bytes.NewReader(data) - var plaintext bytes.Buffer -loop: - for { - c1, err := er.ReadByte() - if err != nil { - plaintext.WriteTo(w.out) - break loop - } - if c1 != 0x1b { - plaintext.WriteByte(c1) - continue - } - _, err = plaintext.WriteTo(w.out) - if err != nil { - break loop - } - c2, err := er.ReadByte() - if err != nil { - break loop - } - if c2 != 0x5b { - continue - } - - for { - c, err := er.ReadByte() - if err != nil { - break loop - } - if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { - break - } - } - } - - return len(data), nil -} diff --git a/vendor/github.com/mattn/go-isatty/LICENSE b/vendor/github.com/mattn/go-isatty/LICENSE deleted file mode 100644 index 65dc692..0000000 --- a/vendor/github.com/mattn/go-isatty/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -Copyright (c) Yasuhiro MATSUMOTO - -MIT License (Expat) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/mattn/go-isatty/README.md b/vendor/github.com/mattn/go-isatty/README.md deleted file mode 100644 index 3841835..0000000 --- a/vendor/github.com/mattn/go-isatty/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# go-isatty - -[![Godoc Reference](https://godoc.org/github.com/mattn/go-isatty?status.svg)](http://godoc.org/github.com/mattn/go-isatty) -[![Codecov](https://codecov.io/gh/mattn/go-isatty/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-isatty) -[![Coverage Status](https://coveralls.io/repos/github/mattn/go-isatty/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-isatty?branch=master) -[![Go Report Card](https://goreportcard.com/badge/mattn/go-isatty)](https://goreportcard.com/report/mattn/go-isatty) - -isatty for golang - -## Usage - -```go -package main - -import ( - "fmt" - "github.com/mattn/go-isatty" - "os" -) - -func main() { - if isatty.IsTerminal(os.Stdout.Fd()) { - fmt.Println("Is Terminal") - } else if isatty.IsCygwinTerminal(os.Stdout.Fd()) { - fmt.Println("Is Cygwin/MSYS2 Terminal") - } else { - fmt.Println("Is Not Terminal") - } -} -``` - -## Installation - -``` -$ go get github.com/mattn/go-isatty -``` - -## License - -MIT - -## Author - -Yasuhiro Matsumoto (a.k.a mattn) - -## Thanks - -* k-takata: base idea for IsCygwinTerminal - - https://github.com/k-takata/go-iscygpty diff --git a/vendor/github.com/mattn/go-isatty/doc.go b/vendor/github.com/mattn/go-isatty/doc.go deleted file mode 100644 index 17d4f90..0000000 --- a/vendor/github.com/mattn/go-isatty/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package isatty implements interface to isatty -package isatty diff --git a/vendor/github.com/mattn/go-isatty/go.test.sh b/vendor/github.com/mattn/go-isatty/go.test.sh deleted file mode 100644 index 012162b..0000000 --- a/vendor/github.com/mattn/go-isatty/go.test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e -echo "" > coverage.txt - -for d in $(go list ./... | grep -v vendor); do - go test -race -coverprofile=profile.out -covermode=atomic "$d" - if [ -f profile.out ]; then - cat profile.out >> coverage.txt - rm profile.out - fi -done diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go deleted file mode 100644 index d0ea68f..0000000 --- a/vendor/github.com/mattn/go-isatty/isatty_bsd.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build (darwin || freebsd || openbsd || netbsd || dragonfly || hurd) && !appengine && !tinygo -// +build darwin freebsd openbsd netbsd dragonfly hurd -// +build !appengine -// +build !tinygo - -package isatty - -import "golang.org/x/sys/unix" - -// IsTerminal return true if the file descriptor is terminal. -func IsTerminal(fd uintptr) bool { - _, err := unix.IoctlGetTermios(int(fd), unix.TIOCGETA) - return err == nil -} - -// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 -// terminal. This is also always false on this environment. -func IsCygwinTerminal(fd uintptr) bool { - return false -} diff --git a/vendor/github.com/mattn/go-isatty/isatty_others.go b/vendor/github.com/mattn/go-isatty/isatty_others.go deleted file mode 100644 index 7402e06..0000000 --- a/vendor/github.com/mattn/go-isatty/isatty_others.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build (appengine || js || nacl || tinygo || wasm) && !windows -// +build appengine js nacl tinygo wasm -// +build !windows - -package isatty - -// IsTerminal returns true if the file descriptor is terminal which -// is always false on js and appengine classic which is a sandboxed PaaS. -func IsTerminal(fd uintptr) bool { - return false -} - -// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2 -// terminal. This is also always false on this environment. -func IsCygwinTerminal(fd uintptr) bool { - return false -} diff --git a/vendor/github.com/mattn/go-isatty/isatty_plan9.go b/vendor/github.com/mattn/go-isatty/isatty_plan9.go deleted file mode 100644 index bae7f9b..0000000 --- a/vendor/github.com/mattn/go-isatty/isatty_plan9.go +++ /dev/null @@ -1,23 +0,0 @@ -//go:build plan9 -// +build plan9 - -package isatty - -import ( - "syscall" -) - -// IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd uintptr) bool { - path, err := syscall.Fd2path(int(fd)) - if err != nil { - return false - } - return path == "/dev/cons" || path == "/mnt/term/dev/cons" -} - -// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 -// terminal. This is also always false on this environment. -func IsCygwinTerminal(fd uintptr) bool { - return false -} diff --git a/vendor/github.com/mattn/go-isatty/isatty_solaris.go b/vendor/github.com/mattn/go-isatty/isatty_solaris.go deleted file mode 100644 index 0c3acf2..0000000 --- a/vendor/github.com/mattn/go-isatty/isatty_solaris.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build solaris && !appengine -// +build solaris,!appengine - -package isatty - -import ( - "golang.org/x/sys/unix" -) - -// IsTerminal returns true if the given file descriptor is a terminal. -// see: https://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/isatty.c -func IsTerminal(fd uintptr) bool { - _, err := unix.IoctlGetTermio(int(fd), unix.TCGETA) - return err == nil -} - -// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 -// terminal. This is also always false on this environment. -func IsCygwinTerminal(fd uintptr) bool { - return false -} diff --git a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go deleted file mode 100644 index 0337d8c..0000000 --- a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build (linux || aix || zos) && !appengine && !tinygo -// +build linux aix zos -// +build !appengine -// +build !tinygo - -package isatty - -import "golang.org/x/sys/unix" - -// IsTerminal return true if the file descriptor is terminal. -func IsTerminal(fd uintptr) bool { - _, err := unix.IoctlGetTermios(int(fd), unix.TCGETS) - return err == nil -} - -// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 -// terminal. This is also always false on this environment. -func IsCygwinTerminal(fd uintptr) bool { - return false -} diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go deleted file mode 100644 index 8e3c991..0000000 --- a/vendor/github.com/mattn/go-isatty/isatty_windows.go +++ /dev/null @@ -1,125 +0,0 @@ -//go:build windows && !appengine -// +build windows,!appengine - -package isatty - -import ( - "errors" - "strings" - "syscall" - "unicode/utf16" - "unsafe" -) - -const ( - objectNameInfo uintptr = 1 - fileNameInfo = 2 - fileTypePipe = 3 -) - -var ( - kernel32 = syscall.NewLazyDLL("kernel32.dll") - ntdll = syscall.NewLazyDLL("ntdll.dll") - procGetConsoleMode = kernel32.NewProc("GetConsoleMode") - procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx") - procGetFileType = kernel32.NewProc("GetFileType") - procNtQueryObject = ntdll.NewProc("NtQueryObject") -) - -func init() { - // Check if GetFileInformationByHandleEx is available. - if procGetFileInformationByHandleEx.Find() != nil { - procGetFileInformationByHandleEx = nil - } -} - -// IsTerminal return true if the file descriptor is terminal. -func IsTerminal(fd uintptr) bool { - var st uint32 - r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0) - return r != 0 && e == 0 -} - -// Check pipe name is used for cygwin/msys2 pty. -// Cygwin/MSYS2 PTY has a name like: -// \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master -func isCygwinPipeName(name string) bool { - token := strings.Split(name, "-") - if len(token) < 5 { - return false - } - - if token[0] != `\msys` && - token[0] != `\cygwin` && - token[0] != `\Device\NamedPipe\msys` && - token[0] != `\Device\NamedPipe\cygwin` { - return false - } - - if token[1] == "" { - return false - } - - if !strings.HasPrefix(token[2], "pty") { - return false - } - - if token[3] != `from` && token[3] != `to` { - return false - } - - if token[4] != "master" { - return false - } - - return true -} - -// getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler -// since GetFileInformationByHandleEx is not available under windows Vista and still some old fashion -// guys are using Windows XP, this is a workaround for those guys, it will also work on system from -// Windows vista to 10 -// see https://stackoverflow.com/a/18792477 for details -func getFileNameByHandle(fd uintptr) (string, error) { - if procNtQueryObject == nil { - return "", errors.New("ntdll.dll: NtQueryObject not supported") - } - - var buf [4 + syscall.MAX_PATH]uint16 - var result int - r, _, e := syscall.Syscall6(procNtQueryObject.Addr(), 5, - fd, objectNameInfo, uintptr(unsafe.Pointer(&buf)), uintptr(2*len(buf)), uintptr(unsafe.Pointer(&result)), 0) - if r != 0 { - return "", e - } - return string(utf16.Decode(buf[4 : 4+buf[0]/2])), nil -} - -// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2 -// terminal. -func IsCygwinTerminal(fd uintptr) bool { - if procGetFileInformationByHandleEx == nil { - name, err := getFileNameByHandle(fd) - if err != nil { - return false - } - return isCygwinPipeName(name) - } - - // Cygwin/msys's pty is a pipe. - ft, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0) - if ft != fileTypePipe || e != 0 { - return false - } - - var buf [2 + syscall.MAX_PATH]uint16 - r, _, e := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), - 4, fd, fileNameInfo, uintptr(unsafe.Pointer(&buf)), - uintptr(len(buf)*2), 0, 0) - if r == 0 || e != 0 { - return false - } - - l := *(*uint32)(unsafe.Pointer(&buf)) - return isCygwinPipeName(string(utf16.Decode(buf[2 : 2+l/2]))) -} diff --git a/vendor/golang.org/x/xerrors/LICENSE b/vendor/golang.org/x/xerrors/LICENSE deleted file mode 100644 index e4a47e1..0000000 --- a/vendor/golang.org/x/xerrors/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2019 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/xerrors/PATENTS b/vendor/golang.org/x/xerrors/PATENTS deleted file mode 100644 index 7330990..0000000 --- a/vendor/golang.org/x/xerrors/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/xerrors/README b/vendor/golang.org/x/xerrors/README deleted file mode 100644 index aac7867..0000000 --- a/vendor/golang.org/x/xerrors/README +++ /dev/null @@ -1,2 +0,0 @@ -This repository holds the transition packages for the new Go 1.13 error values. -See golang.org/design/29934-error-values. diff --git a/vendor/golang.org/x/xerrors/adaptor.go b/vendor/golang.org/x/xerrors/adaptor.go deleted file mode 100644 index 4317f24..0000000 --- a/vendor/golang.org/x/xerrors/adaptor.go +++ /dev/null @@ -1,193 +0,0 @@ -// 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. - -package xerrors - -import ( - "bytes" - "fmt" - "io" - "reflect" - "strconv" -) - -// FormatError calls the FormatError method of f with an errors.Printer -// configured according to s and verb, and writes the result to s. -func FormatError(f Formatter, s fmt.State, verb rune) { - // Assuming this function is only called from the Format method, and given - // that FormatError takes precedence over Format, it cannot be called from - // any package that supports errors.Formatter. It is therefore safe to - // disregard that State may be a specific printer implementation and use one - // of our choice instead. - - // limitations: does not support printing error as Go struct. - - var ( - sep = " " // separator before next error - p = &state{State: s} - direct = true - ) - - var err error = f - - switch verb { - // Note that this switch must match the preference order - // for ordinary string printing (%#v before %+v, and so on). - - case 'v': - if s.Flag('#') { - if stringer, ok := err.(fmt.GoStringer); ok { - io.WriteString(&p.buf, stringer.GoString()) - goto exit - } - // proceed as if it were %v - } else if s.Flag('+') { - p.printDetail = true - sep = "\n - " - } - case 's': - case 'q', 'x', 'X': - // Use an intermediate buffer in the rare cases that precision, - // truncation, or one of the alternative verbs (q, x, and X) are - // specified. - direct = false - - default: - p.buf.WriteString("%!") - p.buf.WriteRune(verb) - p.buf.WriteByte('(') - switch { - case err != nil: - p.buf.WriteString(reflect.TypeOf(f).String()) - default: - p.buf.WriteString("") - } - p.buf.WriteByte(')') - io.Copy(s, &p.buf) - return - } - -loop: - for { - switch v := err.(type) { - case Formatter: - err = v.FormatError((*printer)(p)) - case fmt.Formatter: - v.Format(p, 'v') - break loop - default: - io.WriteString(&p.buf, v.Error()) - break loop - } - if err == nil { - break - } - if p.needColon || !p.printDetail { - p.buf.WriteByte(':') - p.needColon = false - } - p.buf.WriteString(sep) - p.inDetail = false - p.needNewline = false - } - -exit: - width, okW := s.Width() - prec, okP := s.Precision() - - if !direct || (okW && width > 0) || okP { - // Construct format string from State s. - format := []byte{'%'} - if s.Flag('-') { - format = append(format, '-') - } - if s.Flag('+') { - format = append(format, '+') - } - if s.Flag(' ') { - format = append(format, ' ') - } - if okW { - format = strconv.AppendInt(format, int64(width), 10) - } - if okP { - format = append(format, '.') - format = strconv.AppendInt(format, int64(prec), 10) - } - format = append(format, string(verb)...) - fmt.Fprintf(s, string(format), p.buf.String()) - } else { - io.Copy(s, &p.buf) - } -} - -var detailSep = []byte("\n ") - -// state tracks error printing state. It implements fmt.State. -type state struct { - fmt.State - buf bytes.Buffer - - printDetail bool - inDetail bool - needColon bool - needNewline bool -} - -func (s *state) Write(b []byte) (n int, err error) { - if s.printDetail { - if len(b) == 0 { - return 0, nil - } - if s.inDetail && s.needColon { - s.needNewline = true - if b[0] == '\n' { - b = b[1:] - } - } - k := 0 - for i, c := range b { - if s.needNewline { - if s.inDetail && s.needColon { - s.buf.WriteByte(':') - s.needColon = false - } - s.buf.Write(detailSep) - s.needNewline = false - } - if c == '\n' { - s.buf.Write(b[k:i]) - k = i + 1 - s.needNewline = true - } - } - s.buf.Write(b[k:]) - if !s.inDetail { - s.needColon = true - } - } else if !s.inDetail { - s.buf.Write(b) - } - return len(b), nil -} - -// printer wraps a state to implement an xerrors.Printer. -type printer state - -func (s *printer) Print(args ...interface{}) { - if !s.inDetail || s.printDetail { - fmt.Fprint((*state)(s), args...) - } -} - -func (s *printer) Printf(format string, args ...interface{}) { - if !s.inDetail || s.printDetail { - fmt.Fprintf((*state)(s), format, args...) - } -} - -func (s *printer) Detail() bool { - s.inDetail = true - return s.printDetail -} diff --git a/vendor/golang.org/x/xerrors/codereview.cfg b/vendor/golang.org/x/xerrors/codereview.cfg deleted file mode 100644 index 3f8b14b..0000000 --- a/vendor/golang.org/x/xerrors/codereview.cfg +++ /dev/null @@ -1 +0,0 @@ -issuerepo: golang/go diff --git a/vendor/golang.org/x/xerrors/doc.go b/vendor/golang.org/x/xerrors/doc.go deleted file mode 100644 index eef99d9..0000000 --- a/vendor/golang.org/x/xerrors/doc.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 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. - -// Package xerrors implements functions to manipulate errors. -// -// This package is based on the Go 2 proposal for error values: -// https://golang.org/design/29934-error-values -// -// These functions were incorporated into the standard library's errors package -// in Go 1.13: -// - Is -// - As -// - Unwrap -// -// Also, Errorf's %w verb was incorporated into fmt.Errorf. -// -// Use this package to get equivalent behavior in all supported Go versions. -// -// No other features of this package were included in Go 1.13, and at present -// there are no plans to include any of them. -package xerrors // import "golang.org/x/xerrors" diff --git a/vendor/golang.org/x/xerrors/errors.go b/vendor/golang.org/x/xerrors/errors.go deleted file mode 100644 index e88d377..0000000 --- a/vendor/golang.org/x/xerrors/errors.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2011 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. - -package xerrors - -import "fmt" - -// errorString is a trivial implementation of error. -type errorString struct { - s string - frame Frame -} - -// New returns an error that formats as the given text. -// -// The returned error contains a Frame set to the caller's location and -// implements Formatter to show this information when printed with details. -func New(text string) error { - return &errorString{text, Caller(1)} -} - -func (e *errorString) Error() string { - return e.s -} - -func (e *errorString) Format(s fmt.State, v rune) { FormatError(e, s, v) } - -func (e *errorString) FormatError(p Printer) (next error) { - p.Print(e.s) - e.frame.Format(p) - return nil -} diff --git a/vendor/golang.org/x/xerrors/fmt.go b/vendor/golang.org/x/xerrors/fmt.go deleted file mode 100644 index 829862d..0000000 --- a/vendor/golang.org/x/xerrors/fmt.go +++ /dev/null @@ -1,187 +0,0 @@ -// 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. - -package xerrors - -import ( - "fmt" - "strings" - "unicode" - "unicode/utf8" - - "golang.org/x/xerrors/internal" -) - -const percentBangString = "%!" - -// Errorf formats according to a format specifier and returns the string as a -// value that satisfies error. -// -// The returned error includes the file and line number of the caller when -// formatted with additional detail enabled. If the last argument is an error -// the returned error's Format method will return it if the format string ends -// with ": %s", ": %v", or ": %w". If the last argument is an error and the -// format string ends with ": %w", the returned error implements an Unwrap -// method returning it. -// -// If the format specifier includes a %w verb with an error operand in a -// position other than at the end, the returned error will still implement an -// Unwrap method returning the operand, but the error's Format method will not -// return the wrapped error. -// -// It is invalid to include more than one %w verb or to supply it with an -// operand that does not implement the error interface. The %w verb is otherwise -// a synonym for %v. -func Errorf(format string, a ...interface{}) error { - format = formatPlusW(format) - // Support a ": %[wsv]" suffix, which works well with xerrors.Formatter. - wrap := strings.HasSuffix(format, ": %w") - idx, format2, ok := parsePercentW(format) - percentWElsewhere := !wrap && idx >= 0 - if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) { - err := errorAt(a, len(a)-1) - if err == nil { - return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)} - } - // TODO: this is not entirely correct. The error value could be - // printed elsewhere in format if it mixes numbered with unnumbered - // substitutions. With relatively small changes to doPrintf we can - // have it optionally ignore extra arguments and pass the argument - // list in its entirety. - msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...) - frame := Frame{} - if internal.EnableTrace { - frame = Caller(1) - } - if wrap { - return &wrapError{msg, err, frame} - } - return &noWrapError{msg, err, frame} - } - // Support %w anywhere. - // TODO: don't repeat the wrapped error's message when %w occurs in the middle. - msg := fmt.Sprintf(format2, a...) - if idx < 0 { - return &noWrapError{msg, nil, Caller(1)} - } - err := errorAt(a, idx) - if !ok || err == nil { - // Too many %ws or argument of %w is not an error. Approximate the Go - // 1.13 fmt.Errorf message. - return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)} - } - frame := Frame{} - if internal.EnableTrace { - frame = Caller(1) - } - return &wrapError{msg, err, frame} -} - -func errorAt(args []interface{}, i int) error { - if i < 0 || i >= len(args) { - return nil - } - err, ok := args[i].(error) - if !ok { - return nil - } - return err -} - -// formatPlusW is used to avoid the vet check that will barf at %w. -func formatPlusW(s string) string { - return s -} - -// Return the index of the only %w in format, or -1 if none. -// Also return a rewritten format string with %w replaced by %v, and -// false if there is more than one %w. -// TODO: handle "%[N]w". -func parsePercentW(format string) (idx int, newFormat string, ok bool) { - // Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go. - idx = -1 - ok = true - n := 0 - sz := 0 - var isW bool - for i := 0; i < len(format); i += sz { - if format[i] != '%' { - sz = 1 - continue - } - // "%%" is not a format directive. - if i+1 < len(format) && format[i+1] == '%' { - sz = 2 - continue - } - sz, isW = parsePrintfVerb(format[i:]) - if isW { - if idx >= 0 { - ok = false - } else { - idx = n - } - // "Replace" the last character, the 'w', with a 'v'. - p := i + sz - 1 - format = format[:p] + "v" + format[p+1:] - } - n++ - } - return idx, format, ok -} - -// Parse the printf verb starting with a % at s[0]. -// Return how many bytes it occupies and whether the verb is 'w'. -func parsePrintfVerb(s string) (int, bool) { - // Assume only that the directive is a sequence of non-letters followed by a single letter. - sz := 0 - var r rune - for i := 1; i < len(s); i += sz { - r, sz = utf8.DecodeRuneInString(s[i:]) - if unicode.IsLetter(r) { - return i + sz, r == 'w' - } - } - return len(s), false -} - -type noWrapError struct { - msg string - err error - frame Frame -} - -func (e *noWrapError) Error() string { - return fmt.Sprint(e) -} - -func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) } - -func (e *noWrapError) FormatError(p Printer) (next error) { - p.Print(e.msg) - e.frame.Format(p) - return e.err -} - -type wrapError struct { - msg string - err error - frame Frame -} - -func (e *wrapError) Error() string { - return fmt.Sprint(e) -} - -func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) } - -func (e *wrapError) FormatError(p Printer) (next error) { - p.Print(e.msg) - e.frame.Format(p) - return e.err -} - -func (e *wrapError) Unwrap() error { - return e.err -} diff --git a/vendor/golang.org/x/xerrors/format.go b/vendor/golang.org/x/xerrors/format.go deleted file mode 100644 index 1bc9c26..0000000 --- a/vendor/golang.org/x/xerrors/format.go +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -package xerrors - -// A Formatter formats error messages. -type Formatter interface { - error - - // FormatError prints the receiver's first error and returns the next error in - // the error chain, if any. - FormatError(p Printer) (next error) -} - -// A Printer formats error messages. -// -// The most common implementation of Printer is the one provided by package fmt -// during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message -// typically provide their own implementations. -type Printer interface { - // Print appends args to the message output. - Print(args ...interface{}) - - // Printf writes a formatted string. - Printf(format string, args ...interface{}) - - // Detail reports whether error detail is requested. - // After the first call to Detail, all text written to the Printer - // is formatted as additional detail, or ignored when - // detail has not been requested. - // If Detail returns false, the caller can avoid printing the detail at all. - Detail() bool -} diff --git a/vendor/golang.org/x/xerrors/frame.go b/vendor/golang.org/x/xerrors/frame.go deleted file mode 100644 index 0de628e..0000000 --- a/vendor/golang.org/x/xerrors/frame.go +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -package xerrors - -import ( - "runtime" -) - -// A Frame contains part of a call stack. -type Frame struct { - // Make room for three PCs: the one we were asked for, what it called, - // and possibly a PC for skipPleaseUseCallersFrames. See: - // https://go.googlesource.com/go/+/032678e0fb/src/runtime/extern.go#169 - frames [3]uintptr -} - -// Caller returns a Frame that describes a frame on the caller's stack. -// The argument skip is the number of frames to skip over. -// Caller(0) returns the frame for the caller of Caller. -func Caller(skip int) Frame { - var s Frame - runtime.Callers(skip+1, s.frames[:]) - return s -} - -// location reports the file, line, and function of a frame. -// -// The returned function may be "" even if file and line are not. -func (f Frame) location() (function, file string, line int) { - frames := runtime.CallersFrames(f.frames[:]) - if _, ok := frames.Next(); !ok { - return "", "", 0 - } - fr, ok := frames.Next() - if !ok { - return "", "", 0 - } - return fr.Function, fr.File, fr.Line -} - -// Format prints the stack as error detail. -// It should be called from an error's Format implementation -// after printing any other error detail. -func (f Frame) Format(p Printer) { - if p.Detail() { - function, file, line := f.location() - if function != "" { - p.Printf("%s\n ", function) - } - if file != "" { - p.Printf("%s:%d\n", file, line) - } - } -} diff --git a/vendor/golang.org/x/xerrors/internal/internal.go b/vendor/golang.org/x/xerrors/internal/internal.go deleted file mode 100644 index 89f4eca..0000000 --- a/vendor/golang.org/x/xerrors/internal/internal.go +++ /dev/null @@ -1,8 +0,0 @@ -// 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. - -package internal - -// EnableTrace indicates whether stack information should be recorded in errors. -var EnableTrace = true diff --git a/vendor/golang.org/x/xerrors/wrap.go b/vendor/golang.org/x/xerrors/wrap.go deleted file mode 100644 index 9a3b510..0000000 --- a/vendor/golang.org/x/xerrors/wrap.go +++ /dev/null @@ -1,106 +0,0 @@ -// 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. - -package xerrors - -import ( - "reflect" -) - -// A Wrapper provides context around another error. -type Wrapper interface { - // Unwrap returns the next error in the error chain. - // If there is no next error, Unwrap returns nil. - Unwrap() error -} - -// Opaque returns an error with the same error formatting as err -// but that does not match err and cannot be unwrapped. -func Opaque(err error) error { - return noWrapper{err} -} - -type noWrapper struct { - error -} - -func (e noWrapper) FormatError(p Printer) (next error) { - if f, ok := e.error.(Formatter); ok { - return f.FormatError(p) - } - p.Print(e.error) - return nil -} - -// Unwrap returns the result of calling the Unwrap method on err, if err implements -// Unwrap. Otherwise, Unwrap returns nil. -func Unwrap(err error) error { - u, ok := err.(Wrapper) - if !ok { - return nil - } - return u.Unwrap() -} - -// Is reports whether any error in err's chain matches target. -// -// An error is considered to match a target if it is equal to that target or if -// it implements a method Is(error) bool such that Is(target) returns true. -func Is(err, target error) bool { - if target == nil { - return err == target - } - - isComparable := reflect.TypeOf(target).Comparable() - for { - if isComparable && err == target { - return true - } - if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) { - return true - } - // TODO: consider supporing target.Is(err). This would allow - // user-definable predicates, but also may allow for coping with sloppy - // APIs, thereby making it easier to get away with them. - if err = Unwrap(err); err == nil { - return false - } - } -} - -// As finds the first error in err's chain that matches the type to which target -// points, and if so, sets the target to its value and returns true. An error -// matches a type if it is assignable to the target type, or if it has a method -// As(interface{}) bool such that As(target) returns true. As will panic if target -// is not a non-nil pointer to a type which implements error or is of interface type. -// -// The As method should set the target to its value and return true if err -// matches the type to which target points. -func As(err error, target interface{}) bool { - if target == nil { - panic("errors: target cannot be nil") - } - val := reflect.ValueOf(target) - typ := val.Type() - if typ.Kind() != reflect.Ptr || val.IsNil() { - panic("errors: target must be a non-nil pointer") - } - if e := typ.Elem(); e.Kind() != reflect.Interface && !e.Implements(errorType) { - panic("errors: *target must be interface or implement error") - } - targetType := typ.Elem() - for err != nil { - if reflect.TypeOf(err).AssignableTo(targetType) { - val.Elem().Set(reflect.ValueOf(err)) - return true - } - if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) { - return true - } - err = Unwrap(err) - } - return false -} - -var errorType = reflect.TypeOf((*error)(nil)).Elem() diff --git a/vendor/modules.txt b/vendor/modules.txt index 65efc59..e58760b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -9,9 +9,6 @@ github.com/SovereignCloudStack/csctl/pkg/hash # github.com/dustin/go-humanize v1.0.1 ## explicit; go 1.16 github.com/dustin/go-humanize -# github.com/fatih/color v1.13.0 -## explicit; go 1.13 -github.com/fatih/color # github.com/go-ini/ini v1.67.0 ## explicit github.com/go-ini/ini @@ -26,8 +23,8 @@ github.com/goccy/go-json/internal/encoder/vm_color_indent github.com/goccy/go-json/internal/encoder/vm_indent github.com/goccy/go-json/internal/errors github.com/goccy/go-json/internal/runtime -# github.com/goccy/go-yaml v1.12.0 -## explicit; go 1.19 +# github.com/goccy/go-yaml v1.15.5 +## explicit; go 1.21.0 github.com/goccy/go-yaml github.com/goccy/go-yaml/ast github.com/goccy/go-yaml/internal/errors @@ -57,12 +54,6 @@ github.com/klauspost/compress/s2 github.com/klauspost/cpuid/v2 # github.com/kr/pretty v0.3.1 ## explicit; go 1.12 -# github.com/mattn/go-colorable v0.1.13 -## explicit; go 1.15 -github.com/mattn/go-colorable -# github.com/mattn/go-isatty v0.0.20 -## explicit; go 1.15 -github.com/mattn/go-isatty # github.com/minio/md5-simd v1.1.2 ## explicit; go 1.14 github.com/minio/md5-simd @@ -111,10 +102,6 @@ golang.org/x/text/secure/bidirule golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm -# golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 -## explicit; go 1.11 -golang.org/x/xerrors -golang.org/x/xerrors/internal # gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c ## explicit; go 1.11 # gopkg.in/yaml.v3 v3.0.1