VOL-2265 test go.mod and vendor consistency;
Update dependencies to resolve `410 Gone` errors when fetching modules

Change-Id: If0bdbc1b6d629ce819b9fa4701c016df812f92d5
diff --git a/Makefile b/Makefile
index fc0ea52..305a165 100644
--- a/Makefile
+++ b/Makefile
@@ -140,9 +140,19 @@
 	@echo "OK"
 
 lint-mod:
-	@echo -n "Running dependency check ... "
-	@echo -n $(shell go mod verify)
-	@echo " ... OK"
+	go version
+	@echo "Running dependency check..."
+	@go mod verify
+	@echo "Dependency check OK. Running vendor check..."
+	@git status > /dev/null
+	@git diff-index --quiet HEAD -- go.mod go.sum vendor || (echo "ERROR: Staged or modified files must be committed before running this test" && echo "`git status`" && exit 1)
+	@[[ `git ls-files --exclude-standard --others go.mod go.sum vendor` == "" ]] || (echo "ERROR: Untracked files must be cleaned up before running this test" && echo "`git status`" && exit 1)
+	go mod tidy
+	go mod vendor
+	@git status > /dev/null
+	@git diff-index --quiet HEAD -- go.mod go.sum vendor || (echo "ERROR: Modified files detected after running go mod tidy / go mod vendor" && echo "`git status`" && exit 1)
+	@[[ `git ls-files --exclude-standard --others go.mod go.sum vendor` == "" ]] || (echo "ERROR: Untracked files detected after running go mod tidy / go mod vendor" && echo "`git status`" && exit 1)
+	@echo "Vendor check OK."
 
 lint: lint-style lint-sanity lint-mod
 
diff --git a/go.mod b/go.mod
index 806a854..7b70d1b 100644
--- a/go.mod
+++ b/go.mod
@@ -3,14 +3,14 @@
 go 1.12
 
 require (
-	github.com/fullstorydev/grpcurl v1.3.0
+	github.com/fullstorydev/grpcurl v1.4.0
 	github.com/gogo/protobuf v1.2.1 // indirect
 	github.com/golang/protobuf v1.3.1
 	github.com/google/gofuzz v1.0.0 // indirect
 	github.com/googleapis/gnostic v0.3.0 // indirect
 	github.com/imdario/mergo v0.3.7 // indirect
 	github.com/jessevdk/go-flags v1.4.0
-	github.com/jhump/protoreflect v1.4.1
+	github.com/jhump/protoreflect v1.5.0
 	github.com/json-iterator/go v1.1.6 // indirect
 	github.com/spf13/pflag v1.0.3 // indirect
 	github.com/stretchr/testify v1.4.0
@@ -18,11 +18,10 @@
 	golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect
 	golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
 	google.golang.org/appengine v1.6.1 // indirect
-	google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69 // indirect
 	google.golang.org/grpc v1.21.0
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v2 v2.2.2
-	k8s.io/api v0.0.0-20190620084959-7cf5895f2711
-	k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719
-	k8s.io/client-go v12.0.0+incompatible
+	k8s.io/api v0.0.0-20190819141258-3544db3b9e44
+	k8s.io/apimachinery v0.0.0-20190817020851-f2f3a405f61d
+	k8s.io/client-go v0.0.0-20190819141724-e14f31a72a77 // go get k8s.io/client-go@kubernetes-1.15.3
 )
diff --git a/go.sum b/go.sum
index 0580b82..4105b2c 100644
--- a/go.sum
+++ b/go.sum
@@ -11,8 +11,8 @@
 github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
 github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/fullstorydev/grpcurl v1.3.0 h1:XwiEVudma689HpecmJX6sTmOQCd1G5Cyqyj+zSqdk30=
-github.com/fullstorydev/grpcurl v1.3.0/go.mod h1:MtIe/E5RoUPHdbcijFZe/WoJKQtal5JNj0KGIbVqCy8=
+github.com/fullstorydev/grpcurl v1.4.0 h1:rKQyAaegPtCj4mpItnCHd+PIEHspIZl14VWhHYIHhls=
+github.com/fullstorydev/grpcurl v1.4.0/go.mod h1:kvk8xPCXOrwVd9zYdjy+xSOT4YWm6kyth4Y9NMfBns4=
 github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@@ -43,8 +43,8 @@
 github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
-github.com/jhump/protoreflect v1.4.1 h1:tgahjuElRiJthp9JfaMUFxabBVIytT/lnMSadY5kMjM=
-github.com/jhump/protoreflect v1.4.1/go.mod h1:gZ3i/BeD62fjlaIL0VW4UDMT70CTX+3m4pOnAlJ0BX8=
+github.com/jhump/protoreflect v1.5.0 h1:NgpVT+dX71c8hZnxHof2M7QDK7QtohIJ7DYycjnkyfc=
+github.com/jhump/protoreflect v1.5.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
 github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -72,30 +72,24 @@
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
 golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68=
+golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -111,8 +105,6 @@
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@@ -120,12 +112,10 @@
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
-google.golang.org/genproto v0.0.0-20170818100345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69 h1:4rNOqY4ULrKzS6twXa619uQgI7h9PaVd4ZhjFQ7C5zs=
-google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
 google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
-google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0=
 google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
@@ -139,12 +129,12 @@
 gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-k8s.io/api v0.0.0-20190620084959-7cf5895f2711 h1:BblVYz/wE5WtBsD/Gvu54KyBUTJMflolzc5I2DTvh50=
-k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A=
-k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719 h1:uV4S5IB5g4Nvi+TBVNf3e9L4wrirlwYJ6w88jUQxTUw=
-k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA=
-k8s.io/client-go v12.0.0+incompatible h1:YlJxncpeVUC98/WMZKC3JZGk/OXQWCZjAB4Xr3B17RY=
-k8s.io/client-go v12.0.0+incompatible/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k=
+k8s.io/api v0.0.0-20190819141258-3544db3b9e44 h1:7Gz7/nQ7X2qmPXMyN0bNq7Zm9Uip+UnFuMZTd2l3vms=
+k8s.io/api v0.0.0-20190819141258-3544db3b9e44/go.mod h1:AOxZTnaXR/xiarlQL0JUfwQPxjmKDvVYoRp58cA7lUo=
+k8s.io/apimachinery v0.0.0-20190817020851-f2f3a405f61d h1:7Kns6qqhMAQWvGkxYOLSLRZ5hJO0/5pcE5lPGP2fxUw=
+k8s.io/apimachinery v0.0.0-20190817020851-f2f3a405f61d/go.mod h1:3jediapYqJ2w1BFw7lAZPCx7scubsTfosqHkhXCWJKw=
+k8s.io/client-go v0.0.0-20190819141724-e14f31a72a77 h1:w1BoabVnPpPqQCY3sHK4qVwa12Lk8ip1pKMR1C+qbdo=
+k8s.io/client-go v0.0.0-20190819141724-e14f31a72a77/go.mod h1:DmkJD5UDP87MVqUQ5VJ6Tj9Oen8WzXPhk3la4qpyG4g=
 k8s.io/klog v0.3.1 h1:RVgyDHY/kFKtLqh67NvEWIgkMneNoIrdkN0CxDSQc68=
 k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
 k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
diff --git a/vendor/github.com/fullstorydev/grpcurl/.gitignore b/vendor/github.com/fullstorydev/grpcurl/.gitignore
index 849ddff..53fe3b5 100644
--- a/vendor/github.com/fullstorydev/grpcurl/.gitignore
+++ b/vendor/github.com/fullstorydev/grpcurl/.gitignore
@@ -1 +1,2 @@
 dist/
+VERSION
diff --git a/vendor/github.com/fullstorydev/grpcurl/Dockerfile b/vendor/github.com/fullstorydev/grpcurl/Dockerfile
new file mode 100644
index 0000000..0f71406
--- /dev/null
+++ b/vendor/github.com/fullstorydev/grpcurl/Dockerfile
@@ -0,0 +1,33 @@
+FROM golang:1.11.10-alpine as builder
+MAINTAINER FullStory Engineering
+
+# currently, a module build requires gcc (so Go tool can build
+# module-aware versions of std library; it ships only w/ the
+# non-module versions)
+RUN apk update && apk add --no-cache ca-certificates git gcc g++ libc-dev
+# create non-privileged group and user
+RUN addgroup -S grpcurl && adduser -S grpcurl -G grpcurl
+
+WORKDIR /tmp/fullstorydev/grpcurl
+# copy just the files/sources we need to build grpcurl
+COPY VERSION *.go go.* /tmp/fullstorydev/grpcurl/
+COPY cmd /tmp/fullstorydev/grpcurl/cmd
+# and build a completely static binary (so we can use
+# scratch as basis for the final image)
+ENV CGO_ENABLED=0
+ENV GOOS=linux
+ENV GOARCH=amd64
+ENV GO111MODULE=on
+RUN go build -o /grpcurl \
+    -ldflags "-w -extldflags \"-static\" -X \"main.version=$(cat VERSION)\"" \
+    ./cmd/grpcurl
+
+# New FROM so we have a nice'n'tiny image
+FROM scratch
+WORKDIR /
+COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
+COPY --from=builder /etc/passwd /etc/passwd
+COPY --from=builder /grpcurl /bin/grpcurl
+USER grpcurl
+
+ENTRYPOINT ["/bin/grpcurl"]
diff --git a/vendor/github.com/fullstorydev/grpcurl/Makefile b/vendor/github.com/fullstorydev/grpcurl/Makefile
index 982d043..8c34d31 100644
--- a/vendor/github.com/fullstorydev/grpcurl/Makefile
+++ b/vendor/github.com/fullstorydev/grpcurl/Makefile
@@ -25,6 +25,12 @@
 	@GO111MODULE=off go get github.com/goreleaser/goreleaser
 	goreleaser --rm-dist
 
+.PHONY: docker
+docker:
+	@echo $(dev_build_version) > VERSION
+	docker build -t fullstorydev/grpcurl:$(dev_build_version) .
+	@rm VERSION
+
 .PHONY: checkgofmt
 checkgofmt:
 	gofmt -s -l .
diff --git a/vendor/github.com/fullstorydev/grpcurl/desc_source.go b/vendor/github.com/fullstorydev/grpcurl/desc_source.go
index c23ae3d..635ddef 100644
--- a/vendor/github.com/fullstorydev/grpcurl/desc_source.go
+++ b/vendor/github.com/fullstorydev/grpcurl/desc_source.go
@@ -3,6 +3,7 @@
 import (
 	"errors"
 	"fmt"
+	"io"
 	"io/ioutil"
 	"sync"
 
@@ -251,3 +252,53 @@
 	}
 	return err
 }
+
+// WriteProtoset will use the given descriptor source to resolve all of the given
+// symbols and write a proto file descriptor set with their definitions to the
+// given output. The output will include descriptors for all files in which the
+// symbols are defined as well as their transitive dependencies.
+func WriteProtoset(out io.Writer, descSource DescriptorSource, symbols ...string) error {
+	// compute set of file descriptors
+	filenames := make([]string, 0, len(symbols))
+	fds := make(map[string]*desc.FileDescriptor, len(symbols))
+	for _, sym := range symbols {
+		d, err := descSource.FindSymbol(sym)
+		if err != nil {
+			return fmt.Errorf("failed to find descriptor for %q: %v", sym, err)
+		}
+		fd := d.GetFile()
+		if _, ok := fds[fd.GetName()]; !ok {
+			fds[fd.GetName()] = fd
+			filenames = append(filenames, fd.GetName())
+		}
+	}
+	// now expand that to include transitive dependencies in topologically sorted
+	// order (such that file always appears after its dependencies)
+	expandedFiles := make(map[string]struct{}, len(fds))
+	allFilesSlice := make([]*descpb.FileDescriptorProto, 0, len(fds))
+	for _, filename := range filenames {
+		allFilesSlice = addFilesToSet(allFilesSlice, expandedFiles, fds[filename])
+	}
+	// now we can serialize to file
+	b, err := proto.Marshal(&descpb.FileDescriptorSet{File: allFilesSlice})
+	if err != nil {
+		return fmt.Errorf("failed to serialize file descriptor set: %v", err)
+	}
+	if _, err := out.Write(b); err != nil {
+		return fmt.Errorf("failed to write file descriptor set: %v", err)
+	}
+	return nil
+}
+
+func addFilesToSet(allFiles []*descpb.FileDescriptorProto, expanded map[string]struct{}, fd *desc.FileDescriptor) []*descpb.FileDescriptorProto {
+	if _, ok := expanded[fd.GetName()]; ok {
+		// already seen this one
+		return allFiles
+	}
+	expanded[fd.GetName()] = struct{}{}
+	// add all dependencies first
+	for _, dep := range fd.GetDependencies() {
+		allFiles = addFilesToSet(allFiles, expanded, dep)
+	}
+	return append(allFiles, fd.AsFileDescriptorProto())
+}
diff --git a/vendor/github.com/fullstorydev/grpcurl/go.mod b/vendor/github.com/fullstorydev/grpcurl/go.mod
index f6af37d..52a9832 100644
--- a/vendor/github.com/fullstorydev/grpcurl/go.mod
+++ b/vendor/github.com/fullstorydev/grpcurl/go.mod
@@ -2,7 +2,7 @@
 
 require (
 	github.com/golang/protobuf v1.3.1
-	github.com/jhump/protoreflect v1.4.1
+	github.com/jhump/protoreflect v1.5.0
 	golang.org/x/net v0.0.0-20190311183353-d8887717615a
 	google.golang.org/grpc v1.21.0
 )
diff --git a/vendor/github.com/fullstorydev/grpcurl/go.sum b/vendor/github.com/fullstorydev/grpcurl/go.sum
index 466dbb1..5a79975 100644
--- a/vendor/github.com/fullstorydev/grpcurl/go.sum
+++ b/vendor/github.com/fullstorydev/grpcurl/go.sum
@@ -7,8 +7,8 @@
 github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/jhump/protoreflect v1.4.1 h1:tgahjuElRiJthp9JfaMUFxabBVIytT/lnMSadY5kMjM=
-github.com/jhump/protoreflect v1.4.1/go.mod h1:gZ3i/BeD62fjlaIL0VW4UDMT70CTX+3m4pOnAlJ0BX8=
+github.com/jhump/protoreflect v1.5.0 h1:NgpVT+dX71c8hZnxHof2M7QDK7QtohIJ7DYycjnkyfc=
+github.com/jhump/protoreflect v1.5.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -21,7 +21,7 @@
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/genproto v0.0.0-20170818100345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
diff --git a/vendor/github.com/fullstorydev/grpcurl/grpcurl.go b/vendor/github.com/fullstorydev/grpcurl/grpcurl.go
index 64947de..3c5c607 100644
--- a/vendor/github.com/fullstorydev/grpcurl/grpcurl.go
+++ b/vendor/github.com/fullstorydev/grpcurl/grpcurl.go
@@ -15,6 +15,8 @@
 	"fmt"
 	"io/ioutil"
 	"net"
+	"os"
+	"regexp"
 	"sort"
 	"strings"
 
@@ -161,6 +163,36 @@
 	return md
 }
 
+var envVarRegex = regexp.MustCompile(`\${\w+}`)
+
+// ExpandHeaders expands environment variables contained in the header string.
+// If no corresponding environment variable is found an error is returned.
+// TODO: Add escaping for `${`
+func ExpandHeaders(headers []string) ([]string, error) {
+	expandedHeaders := make([]string, len(headers))
+	for idx, header := range headers {
+		if header == "" {
+			continue
+		}
+		results := envVarRegex.FindAllString(header, -1)
+		if len(results) == 0 {
+			expandedHeaders[idx] = headers[idx]
+			continue
+		}
+		expandedHeader := header
+		for _, result := range results {
+			envVarName := result[2 : len(result)-1] // strip leading `${` and trailing `}`
+			envVarValue, ok := os.LookupEnv(envVarName)
+			if !ok {
+				return nil, fmt.Errorf("header %q refers to missing environment variable %q", header, envVarName)
+			}
+			expandedHeader = strings.Replace(expandedHeader, result, envVarValue, -1)
+		}
+		expandedHeaders[idx] = expandedHeader
+	}
+	return expandedHeaders, nil
+}
+
 var base64Codecs = []*base64.Encoding{base64.StdEncoding, base64.URLEncoding, base64.RawStdEncoding, base64.RawURLEncoding}
 
 func decode(val string) (string, error) {
diff --git a/vendor/github.com/jhump/protoreflect/codec/buffer.go b/vendor/github.com/jhump/protoreflect/codec/buffer.go
new file mode 100644
index 0000000..b9de99c
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/buffer.go
@@ -0,0 +1,112 @@
+package codec
+
+import (
+	"fmt"
+	"io"
+)
+
+// Buffer is a reader and a writer that wraps a slice of bytes and also
+// provides API for decoding and encoding the protobuf binary format.
+//
+// Its operation is similar to that of a bytes.Buffer: writing pushes
+// data to the end of the buffer while reading pops data from the head
+// of the buffer. So the same buffer can be used to both read and write.
+type Buffer struct {
+	buf   []byte
+	index int
+
+	// tmp is used when another byte slice is needed, such as when
+	// serializing messages, since we need to know the length before
+	// we can write the length prefix; by caching this, including
+	// after it is grown by serialization operations, we reduce the
+	// number of allocations needed
+	tmp []byte
+
+	deterministic bool
+}
+
+// NewBuffer creates a new buffer with the given slice of bytes as the
+// buffer's initial contents.
+func NewBuffer(buf []byte) *Buffer {
+	return &Buffer{buf: buf}
+}
+
+// SetDeterministic sets this buffer to encode messages deterministically. This
+// is useful for tests. But the overhead is non-zero, so it should not likely be
+// used outside of tests. When true, map fields in a message must have their
+// keys sorted before serialization to ensure deterministic output. Otherwise,
+// values in a map field will be serialized in map iteration order.
+func (cb *Buffer) SetDeterministic(deterministic bool) {
+	cb.deterministic = deterministic
+}
+
+// Reset resets this buffer back to empty. Any subsequent writes/encodes
+// to the buffer will allocate a new backing slice of bytes.
+func (cb *Buffer) Reset() {
+	cb.buf = []byte(nil)
+	cb.index = 0
+}
+
+// Bytes returns the slice of bytes remaining in the buffer. Note that
+// this does not perform a copy: if the contents of the returned slice
+// are modified, the modifications will be visible to subsequent reads
+// via the buffer.
+func (cb *Buffer) Bytes() []byte {
+	return cb.buf[cb.index:]
+}
+
+// String returns the remaining bytes in the buffer as a string.
+func (cb *Buffer) String() string {
+	return string(cb.Bytes())
+}
+
+// EOF returns true if there are no more bytes remaining to read.
+func (cb *Buffer) EOF() bool {
+	return cb.index >= len(cb.buf)
+}
+
+// Skip attempts to skip the given number of bytes in the input. If
+// the input has fewer bytes than the given count, false is returned
+// and the buffer is unchanged. Otherwise, the given number of bytes
+// are skipped and true is returned.
+func (cb *Buffer) Skip(count int) error {
+	if count < 0 {
+		return fmt.Errorf("proto: bad byte length %d", count)
+	}
+	newIndex := cb.index + count
+	if newIndex < cb.index || newIndex > len(cb.buf) {
+		return io.ErrUnexpectedEOF
+	}
+	cb.index = newIndex
+	return nil
+}
+
+// Len returns the remaining number of bytes in the buffer.
+func (cb *Buffer) Len() int {
+	return len(cb.buf) - cb.index
+}
+
+// Read implements the io.Reader interface. If there are no bytes
+// remaining in the buffer, it will return 0, io.EOF. Otherwise,
+// it reads max(len(dest), cb.Len()) bytes from input and copies
+// them into dest. It returns the number of bytes copied and a nil
+// error in this case.
+func (cb *Buffer) Read(dest []byte) (int, error) {
+	if cb.index == len(cb.buf) {
+		return 0, io.EOF
+	}
+	copied := copy(dest, cb.buf[cb.index:])
+	cb.index += copied
+	return copied, nil
+}
+
+var _ io.Reader = (*Buffer)(nil)
+
+// Write implements the io.Writer interface. It always returns
+// len(data), nil.
+func (cb *Buffer) Write(data []byte) (int, error) {
+	cb.buf = append(cb.buf, data...)
+	return len(data), nil
+}
+
+var _ io.Writer = (*Buffer)(nil)
diff --git a/vendor/github.com/jhump/protoreflect/codec/decode.go b/vendor/github.com/jhump/protoreflect/codec/decode.go
new file mode 100644
index 0000000..2a7e59f
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/decode.go
@@ -0,0 +1,372 @@
+package codec
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"math"
+
+	"github.com/golang/protobuf/proto"
+	"github.com/golang/protobuf/protoc-gen-go/descriptor"
+)
+
+// ErrOverflow is returned when an integer is too large to be represented.
+var ErrOverflow = errors.New("proto: integer overflow")
+
+// ErrBadWireType is returned when decoding a wire-type from a buffer that
+// is not valid.
+var ErrBadWireType = errors.New("proto: bad wiretype")
+
+var varintTypes = map[descriptor.FieldDescriptorProto_Type]bool{}
+var fixed32Types = map[descriptor.FieldDescriptorProto_Type]bool{}
+var fixed64Types = map[descriptor.FieldDescriptorProto_Type]bool{}
+
+func init() {
+	varintTypes[descriptor.FieldDescriptorProto_TYPE_BOOL] = true
+	varintTypes[descriptor.FieldDescriptorProto_TYPE_INT32] = true
+	varintTypes[descriptor.FieldDescriptorProto_TYPE_INT64] = true
+	varintTypes[descriptor.FieldDescriptorProto_TYPE_UINT32] = true
+	varintTypes[descriptor.FieldDescriptorProto_TYPE_UINT64] = true
+	varintTypes[descriptor.FieldDescriptorProto_TYPE_SINT32] = true
+	varintTypes[descriptor.FieldDescriptorProto_TYPE_SINT64] = true
+	varintTypes[descriptor.FieldDescriptorProto_TYPE_ENUM] = true
+
+	fixed32Types[descriptor.FieldDescriptorProto_TYPE_FIXED32] = true
+	fixed32Types[descriptor.FieldDescriptorProto_TYPE_SFIXED32] = true
+	fixed32Types[descriptor.FieldDescriptorProto_TYPE_FLOAT] = true
+
+	fixed64Types[descriptor.FieldDescriptorProto_TYPE_FIXED64] = true
+	fixed64Types[descriptor.FieldDescriptorProto_TYPE_SFIXED64] = true
+	fixed64Types[descriptor.FieldDescriptorProto_TYPE_DOUBLE] = true
+}
+
+func (cb *Buffer) decodeVarintSlow() (x uint64, err error) {
+	i := cb.index
+	l := len(cb.buf)
+
+	for shift := uint(0); shift < 64; shift += 7 {
+		if i >= l {
+			err = io.ErrUnexpectedEOF
+			return
+		}
+		b := cb.buf[i]
+		i++
+		x |= (uint64(b) & 0x7F) << shift
+		if b < 0x80 {
+			cb.index = i
+			return
+		}
+	}
+
+	// The number is too large to represent in a 64-bit value.
+	err = ErrOverflow
+	return
+}
+
+// DecodeVarint reads a varint-encoded integer from the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (cb *Buffer) DecodeVarint() (uint64, error) {
+	i := cb.index
+	buf := cb.buf
+
+	if i >= len(buf) {
+		return 0, io.ErrUnexpectedEOF
+	} else if buf[i] < 0x80 {
+		cb.index++
+		return uint64(buf[i]), nil
+	} else if len(buf)-i < 10 {
+		return cb.decodeVarintSlow()
+	}
+
+	var b uint64
+	// we already checked the first byte
+	x := uint64(buf[i]) - 0x80
+	i++
+
+	b = uint64(buf[i])
+	i++
+	x += b << 7
+	if b&0x80 == 0 {
+		goto done
+	}
+	x -= 0x80 << 7
+
+	b = uint64(buf[i])
+	i++
+	x += b << 14
+	if b&0x80 == 0 {
+		goto done
+	}
+	x -= 0x80 << 14
+
+	b = uint64(buf[i])
+	i++
+	x += b << 21
+	if b&0x80 == 0 {
+		goto done
+	}
+	x -= 0x80 << 21
+
+	b = uint64(buf[i])
+	i++
+	x += b << 28
+	if b&0x80 == 0 {
+		goto done
+	}
+	x -= 0x80 << 28
+
+	b = uint64(buf[i])
+	i++
+	x += b << 35
+	if b&0x80 == 0 {
+		goto done
+	}
+	x -= 0x80 << 35
+
+	b = uint64(buf[i])
+	i++
+	x += b << 42
+	if b&0x80 == 0 {
+		goto done
+	}
+	x -= 0x80 << 42
+
+	b = uint64(buf[i])
+	i++
+	x += b << 49
+	if b&0x80 == 0 {
+		goto done
+	}
+	x -= 0x80 << 49
+
+	b = uint64(buf[i])
+	i++
+	x += b << 56
+	if b&0x80 == 0 {
+		goto done
+	}
+	x -= 0x80 << 56
+
+	b = uint64(buf[i])
+	i++
+	x += b << 63
+	if b&0x80 == 0 {
+		goto done
+	}
+	// x -= 0x80 << 63 // Always zero.
+
+	return 0, ErrOverflow
+
+done:
+	cb.index = i
+	return x, nil
+}
+
+// DecodeTagAndWireType decodes a field tag and wire type from input.
+// This reads a varint and then extracts the two fields from the varint
+// value read.
+func (cb *Buffer) DecodeTagAndWireType() (tag int32, wireType int8, err error) {
+	var v uint64
+	v, err = cb.DecodeVarint()
+	if err != nil {
+		return
+	}
+	// low 7 bits is wire type
+	wireType = int8(v & 7)
+	// rest is int32 tag number
+	v = v >> 3
+	if v > math.MaxInt32 {
+		err = fmt.Errorf("tag number out of range: %d", v)
+		return
+	}
+	tag = int32(v)
+	return
+}
+
+// DecodeFixed64 reads a 64-bit integer from the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (cb *Buffer) DecodeFixed64() (x uint64, err error) {
+	// x, err already 0
+	i := cb.index + 8
+	if i < 0 || i > len(cb.buf) {
+		err = io.ErrUnexpectedEOF
+		return
+	}
+	cb.index = i
+
+	x = uint64(cb.buf[i-8])
+	x |= uint64(cb.buf[i-7]) << 8
+	x |= uint64(cb.buf[i-6]) << 16
+	x |= uint64(cb.buf[i-5]) << 24
+	x |= uint64(cb.buf[i-4]) << 32
+	x |= uint64(cb.buf[i-3]) << 40
+	x |= uint64(cb.buf[i-2]) << 48
+	x |= uint64(cb.buf[i-1]) << 56
+	return
+}
+
+// DecodeFixed32 reads a 32-bit integer from the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (cb *Buffer) DecodeFixed32() (x uint64, err error) {
+	// x, err already 0
+	i := cb.index + 4
+	if i < 0 || i > len(cb.buf) {
+		err = io.ErrUnexpectedEOF
+		return
+	}
+	cb.index = i
+
+	x = uint64(cb.buf[i-4])
+	x |= uint64(cb.buf[i-3]) << 8
+	x |= uint64(cb.buf[i-2]) << 16
+	x |= uint64(cb.buf[i-1]) << 24
+	return
+}
+
+// DecodeZigZag32 decodes a signed 32-bit integer from the given
+// zig-zag encoded value.
+func DecodeZigZag32(v uint64) int32 {
+	return int32((uint32(v) >> 1) ^ uint32((int32(v&1)<<31)>>31))
+}
+
+// DecodeZigZag64 decodes a signed 64-bit integer from the given
+// zig-zag encoded value.
+func DecodeZigZag64(v uint64) int64 {
+	return int64((v >> 1) ^ uint64((int64(v&1)<<63)>>63))
+}
+
+// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (cb *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
+	n, err := cb.DecodeVarint()
+	if err != nil {
+		return nil, err
+	}
+
+	nb := int(n)
+	if nb < 0 {
+		return nil, fmt.Errorf("proto: bad byte length %d", nb)
+	}
+	end := cb.index + nb
+	if end < cb.index || end > len(cb.buf) {
+		return nil, io.ErrUnexpectedEOF
+	}
+
+	if !alloc {
+		buf = cb.buf[cb.index:end]
+		cb.index = end
+		return
+	}
+
+	buf = make([]byte, nb)
+	copy(buf, cb.buf[cb.index:])
+	cb.index = end
+	return
+}
+
+// ReadGroup reads the input until a "group end" tag is found
+// and returns the data up to that point. Subsequent reads from
+// the buffer will read data after the group end tag. If alloc
+// is true, the data is copied to a new slice before being returned.
+// Otherwise, the returned slice is a view into the buffer's
+// underlying byte slice.
+//
+// This function correctly handles nested groups: if a "group start"
+// tag is found, then that group's end tag will be included in the
+// returned data.
+func (cb *Buffer) ReadGroup(alloc bool) ([]byte, error) {
+	var groupEnd, dataEnd int
+	groupEnd, dataEnd, err := cb.findGroupEnd()
+	if err != nil {
+		return nil, err
+	}
+	var results []byte
+	if !alloc {
+		results = cb.buf[cb.index:dataEnd]
+	} else {
+		results = make([]byte, dataEnd-cb.index)
+		copy(results, cb.buf[cb.index:])
+	}
+	cb.index = groupEnd
+	return results, nil
+}
+
+// SkipGroup is like ReadGroup, except that it discards the
+// data and just advances the buffer to point to the input
+// right *after* the "group end" tag.
+func (cb *Buffer) SkipGroup() error {
+	groupEnd, _, err := cb.findGroupEnd()
+	if err != nil {
+		return err
+	}
+	cb.index = groupEnd
+	return nil
+}
+
+func (cb *Buffer) findGroupEnd() (groupEnd int, dataEnd int, err error) {
+	bs := cb.buf
+	start := cb.index
+	defer func() {
+		cb.index = start
+	}()
+	for {
+		fieldStart := cb.index
+		// read a field tag
+		_, wireType, err := cb.DecodeTagAndWireType()
+		if err != nil {
+			return 0, 0, err
+		}
+		// skip past the field's data
+		switch wireType {
+		case proto.WireFixed32:
+			if err := cb.Skip(4); err != nil {
+				return 0, 0, err
+			}
+		case proto.WireFixed64:
+			if err := cb.Skip(8); err != nil {
+				return 0, 0, err
+			}
+		case proto.WireVarint:
+			// skip varint by finding last byte (has high bit unset)
+			i := cb.index
+			limit := i + 10 // varint cannot be >10 bytes
+			for {
+				if i >= limit {
+					return 0, 0, ErrOverflow
+				}
+				if i >= len(bs) {
+					return 0, 0, io.ErrUnexpectedEOF
+				}
+				if bs[i]&0x80 == 0 {
+					break
+				}
+				i++
+			}
+			// TODO: This would only overflow if buffer length was MaxInt and we
+			// read the last byte. This is not a real/feasible concern on 64-bit
+			// systems. Something to worry about for 32-bit systems? Do we care?
+			cb.index = i + 1
+		case proto.WireBytes:
+			l, err := cb.DecodeVarint()
+			if err != nil {
+				return 0, 0, err
+			}
+			if err := cb.Skip(int(l)); err != nil {
+				return 0, 0, err
+			}
+		case proto.WireStartGroup:
+			if err := cb.SkipGroup(); err != nil {
+				return 0, 0, err
+			}
+		case proto.WireEndGroup:
+			return cb.index, fieldStart, nil
+		default:
+			return 0, 0, ErrBadWireType
+		}
+	}
+}
diff --git a/vendor/github.com/jhump/protoreflect/codec/decode_fields.go b/vendor/github.com/jhump/protoreflect/codec/decode_fields.go
new file mode 100644
index 0000000..938b4d9
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/decode_fields.go
@@ -0,0 +1,283 @@
+package codec
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"math"
+
+	"github.com/golang/protobuf/proto"
+	"github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+	"github.com/jhump/protoreflect/desc"
+)
+
+// ErrWireTypeEndGroup is returned from DecodeFieldValue if the tag and wire-type
+// it reads indicates an end-group marker.
+var ErrWireTypeEndGroup = errors.New("unexpected wire type: end group")
+
+// MessageFactory is used to instantiate messages when DecodeFieldValue needs to
+// decode a message value.
+//
+// Also see MessageFactory in "github.com/jhump/protoreflect/dynamic", which
+// implements this interface.
+type MessageFactory interface {
+	NewMessage(md *desc.MessageDescriptor) proto.Message
+}
+
+// UnknownField represents a field that was parsed from the binary wire
+// format for a message, but was not a recognized field number. Enough
+// information is preserved so that re-serializing the message won't lose
+// any of the unrecognized data.
+type UnknownField struct {
+	// The tag number for the unrecognized field.
+	Tag int32
+
+	// Encoding indicates how the unknown field was encoded on the wire. If it
+	// is proto.WireBytes or proto.WireGroupStart then Contents will be set to
+	// the raw bytes. If it is proto.WireTypeFixed32 then the data is in the least
+	// significant 32 bits of Value. Otherwise, the data is in all 64 bits of
+	// Value.
+	Encoding int8
+	Contents []byte
+	Value    uint64
+}
+
+// DecodeFieldValue will read a field value from the buffer and return its
+// value and the corresponding field descriptor. The given function is used
+// to lookup a field descriptor by tag number. The given factory is used to
+// instantiate a message if the field value is (or contains) a message value.
+//
+// On error, the field descriptor and value are typically nil. However, if the
+// error returned is ErrWireTypeEndGroup, the returned value will indicate any
+// tag number encoded in the end-group marker.
+//
+// If the field descriptor returned is nil, that means that the given function
+// returned nil. This is expected to happen for unrecognized tag numbers. In
+// that case, no error is returned, and the value will be an UnknownField.
+func (cb *Buffer) DecodeFieldValue(fieldFinder func(int32) *desc.FieldDescriptor, fact MessageFactory) (*desc.FieldDescriptor, interface{}, error) {
+	if cb.EOF() {
+		return nil, nil, io.EOF
+	}
+	tagNumber, wireType, err := cb.DecodeTagAndWireType()
+	if err != nil {
+		return nil, nil, err
+	}
+	if wireType == proto.WireEndGroup {
+		return nil, tagNumber, ErrWireTypeEndGroup
+	}
+	fd := fieldFinder(tagNumber)
+	if fd == nil {
+		val, err := cb.decodeUnknownField(tagNumber, wireType)
+		return nil, val, err
+	}
+	val, err := cb.decodeKnownField(fd, wireType, fact)
+	return fd, val, err
+}
+
+// DecodeScalarField extracts a properly-typed value from v. The returned value's
+// type depends on the given field descriptor type. It will be the same type as
+// generated structs use for the field descriptor's type. Enum types will return
+// an int32. If the given field type uses length-delimited encoding (nested
+// messages, bytes, and strings), an error is returned.
+func DecodeScalarField(fd *desc.FieldDescriptor, v uint64) (interface{}, error) {
+	switch fd.GetType() {
+	case descriptor.FieldDescriptorProto_TYPE_BOOL:
+		return v != 0, nil
+	case descriptor.FieldDescriptorProto_TYPE_UINT32,
+		descriptor.FieldDescriptorProto_TYPE_FIXED32:
+		if v > math.MaxUint32 {
+			return nil, ErrOverflow
+		}
+		return uint32(v), nil
+
+	case descriptor.FieldDescriptorProto_TYPE_INT32,
+		descriptor.FieldDescriptorProto_TYPE_ENUM:
+		s := int64(v)
+		if s > math.MaxInt32 || s < math.MinInt32 {
+			return nil, ErrOverflow
+		}
+		return int32(s), nil
+
+	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+		if v > math.MaxUint32 {
+			return nil, ErrOverflow
+		}
+		return int32(v), nil
+
+	case descriptor.FieldDescriptorProto_TYPE_SINT32:
+		if v > math.MaxUint32 {
+			return nil, ErrOverflow
+		}
+		return DecodeZigZag32(v), nil
+
+	case descriptor.FieldDescriptorProto_TYPE_UINT64,
+		descriptor.FieldDescriptorProto_TYPE_FIXED64:
+		return v, nil
+
+	case descriptor.FieldDescriptorProto_TYPE_INT64,
+		descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+		return int64(v), nil
+
+	case descriptor.FieldDescriptorProto_TYPE_SINT64:
+		return DecodeZigZag64(v), nil
+
+	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+		if v > math.MaxUint32 {
+			return nil, ErrOverflow
+		}
+		return math.Float32frombits(uint32(v)), nil
+
+	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+		return math.Float64frombits(v), nil
+
+	default:
+		// bytes, string, message, and group cannot be represented as a simple numeric value
+		return nil, fmt.Errorf("bad input; field %s requires length-delimited wire type", fd.GetFullyQualifiedName())
+	}
+}
+
+// DecodeLengthDelimitedField extracts a properly-typed value from bytes. The
+// returned value's type will usually be []byte, string, or, for nested messages,
+// the type returned from the given message factory. However, since repeated
+// scalar fields can be length-delimited, when they used packed encoding, it can
+// also return an []interface{}, where each element is a scalar value. Furthermore,
+// it could return a scalar type, not in a slice, if the given field descriptor is
+// not repeated. This is to support cases where a field is changed from optional
+// to repeated. New code may emit a packed repeated representation, but old code
+// still expects a single scalar value. In this case, if the actual data in bytes
+// contains multiple values, only the last value is returned.
+func DecodeLengthDelimitedField(fd *desc.FieldDescriptor, bytes []byte, mf MessageFactory) (interface{}, error) {
+	switch {
+	case fd.GetType() == descriptor.FieldDescriptorProto_TYPE_BYTES:
+		return bytes, nil
+
+	case fd.GetType() == descriptor.FieldDescriptorProto_TYPE_STRING:
+		return string(bytes), nil
+
+	case fd.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE ||
+		fd.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP:
+		msg := mf.NewMessage(fd.GetMessageType())
+		err := proto.Unmarshal(bytes, msg)
+		if err != nil {
+			return nil, err
+		} else {
+			return msg, nil
+		}
+
+	default:
+		// even if the field is not repeated or not packed, we still parse it as such for
+		// backwards compatibility (e.g. message we are de-serializing could have been both
+		// repeated and packed at the time of serialization)
+		packedBuf := NewBuffer(bytes)
+		var slice []interface{}
+		var val interface{}
+		for !packedBuf.EOF() {
+			var v uint64
+			var err error
+			if varintTypes[fd.GetType()] {
+				v, err = packedBuf.DecodeVarint()
+			} else if fixed32Types[fd.GetType()] {
+				v, err = packedBuf.DecodeFixed32()
+			} else if fixed64Types[fd.GetType()] {
+				v, err = packedBuf.DecodeFixed64()
+			} else {
+				return nil, fmt.Errorf("bad input; cannot parse length-delimited wire type for field %s", fd.GetFullyQualifiedName())
+			}
+			if err != nil {
+				return nil, err
+			}
+			val, err = DecodeScalarField(fd, v)
+			if err != nil {
+				return nil, err
+			}
+			if fd.IsRepeated() {
+				slice = append(slice, val)
+			}
+		}
+		if fd.IsRepeated() {
+			return slice, nil
+		} else {
+			// if not a repeated field, last value wins
+			return val, nil
+		}
+	}
+}
+
+func (b *Buffer) decodeKnownField(fd *desc.FieldDescriptor, encoding int8, fact MessageFactory) (interface{}, error) {
+	var val interface{}
+	var err error
+	switch encoding {
+	case proto.WireFixed32:
+		var num uint64
+		num, err = b.DecodeFixed32()
+		if err == nil {
+			val, err = DecodeScalarField(fd, num)
+		}
+	case proto.WireFixed64:
+		var num uint64
+		num, err = b.DecodeFixed64()
+		if err == nil {
+			val, err = DecodeScalarField(fd, num)
+		}
+	case proto.WireVarint:
+		var num uint64
+		num, err = b.DecodeVarint()
+		if err == nil {
+			val, err = DecodeScalarField(fd, num)
+		}
+
+	case proto.WireBytes:
+		alloc := fd.GetType() == descriptor.FieldDescriptorProto_TYPE_BYTES
+		var raw []byte
+		raw, err = b.DecodeRawBytes(alloc)
+		if err == nil {
+			val, err = DecodeLengthDelimitedField(fd, raw, fact)
+		}
+
+	case proto.WireStartGroup:
+		if fd.GetMessageType() == nil {
+			return nil, fmt.Errorf("cannot parse field %s from group-encoded wire type", fd.GetFullyQualifiedName())
+		}
+		msg := fact.NewMessage(fd.GetMessageType())
+		var data []byte
+		data, err = b.ReadGroup(false)
+		if err == nil {
+			err = proto.Unmarshal(data, msg)
+			if err == nil {
+				val = msg
+			}
+		}
+
+	default:
+		return nil, ErrBadWireType
+	}
+	if err != nil {
+		return nil, err
+	}
+
+	return val, nil
+}
+
+func (b *Buffer) decodeUnknownField(tagNumber int32, encoding int8) (interface{}, error) {
+	u := UnknownField{Tag: tagNumber, Encoding: encoding}
+	var err error
+	switch encoding {
+	case proto.WireFixed32:
+		u.Value, err = b.DecodeFixed32()
+	case proto.WireFixed64:
+		u.Value, err = b.DecodeFixed64()
+	case proto.WireVarint:
+		u.Value, err = b.DecodeVarint()
+	case proto.WireBytes:
+		u.Contents, err = b.DecodeRawBytes(true)
+	case proto.WireStartGroup:
+		u.Contents, err = b.ReadGroup(true)
+	default:
+		err = ErrBadWireType
+	}
+	if err != nil {
+		return nil, err
+	}
+	return u, nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/codec/doc.go b/vendor/github.com/jhump/protoreflect/codec/doc.go
new file mode 100644
index 0000000..f76499f
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/doc.go
@@ -0,0 +1,7 @@
+// Package codec contains a reader/write type that assists with encoding
+// and decoding protobuf's binary representation.
+//
+// The code in this package began as a fork of proto.Buffer but provides
+// additional API to make it more useful to code that needs to dynamically
+// process or produce the protobuf binary format.
+package codec
diff --git a/vendor/github.com/jhump/protoreflect/codec/encode.go b/vendor/github.com/jhump/protoreflect/codec/encode.go
new file mode 100644
index 0000000..c84523f
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/encode.go
@@ -0,0 +1,163 @@
+package codec
+
+import "github.com/golang/protobuf/proto"
+
+// EncodeVarint writes a varint-encoded integer to the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (cb *Buffer) EncodeVarint(x uint64) error {
+	for x >= 1<<7 {
+		cb.buf = append(cb.buf, uint8(x&0x7f|0x80))
+		x >>= 7
+	}
+	cb.buf = append(cb.buf, uint8(x))
+	return nil
+}
+
+// EncodeTagAndWireType encodes the given field tag and wire type to the
+// buffer. This combines the two values and then writes them as a varint.
+func (cb *Buffer) EncodeTagAndWireType(tag int32, wireType int8) error {
+	v := uint64((int64(tag) << 3) | int64(wireType))
+	return cb.EncodeVarint(v)
+}
+
+// EncodeFixed64 writes a 64-bit integer to the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (cb *Buffer) EncodeFixed64(x uint64) error {
+	cb.buf = append(cb.buf,
+		uint8(x),
+		uint8(x>>8),
+		uint8(x>>16),
+		uint8(x>>24),
+		uint8(x>>32),
+		uint8(x>>40),
+		uint8(x>>48),
+		uint8(x>>56))
+	return nil
+}
+
+// EncodeFixed32 writes a 32-bit integer to the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (cb *Buffer) EncodeFixed32(x uint64) error {
+	cb.buf = append(cb.buf,
+		uint8(x),
+		uint8(x>>8),
+		uint8(x>>16),
+		uint8(x>>24))
+	return nil
+}
+
+// EncodeZigZag64 does zig-zag encoding to convert the given
+// signed 64-bit integer into a form that can be expressed
+// efficiently as a varint, even for negative values.
+func EncodeZigZag64(v int64) uint64 {
+	return (uint64(v) << 1) ^ uint64(v>>63)
+}
+
+// EncodeZigZag32 does zig-zag encoding to convert the given
+// signed 32-bit integer into a form that can be expressed
+// efficiently as a varint, even for negative values.
+func EncodeZigZag32(v int32) uint64 {
+	return uint64((uint32(v) << 1) ^ uint32((v >> 31)))
+}
+
+// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (cb *Buffer) EncodeRawBytes(b []byte) error {
+	if err := cb.EncodeVarint(uint64(len(b))); err != nil {
+		return err
+	}
+	cb.buf = append(cb.buf, b...)
+	return nil
+}
+
+// EncodeMessage writes the given message to the buffer.
+func (cb *Buffer) EncodeMessage(pm proto.Message) error {
+	bytes, err := marshalMessage(cb.buf, pm, cb.deterministic)
+	if err != nil {
+		return err
+	}
+	cb.buf = bytes
+	return nil
+}
+
+// EncodeDelimitedMessage writes the given message to the buffer with a
+// varint-encoded length prefix (the delimiter).
+func (cb *Buffer) EncodeDelimitedMessage(pm proto.Message) error {
+	bytes, err := marshalMessage(cb.tmp, pm, cb.deterministic)
+	if err != nil {
+		return err
+	}
+	// save truncated buffer if it was grown (so we can re-use it and
+	// curtail future allocations)
+	if cap(bytes) > cap(cb.tmp) {
+		cb.tmp = bytes[:0]
+	}
+	return cb.EncodeRawBytes(bytes)
+}
+
+func marshalMessage(b []byte, pm proto.Message, deterministic bool) ([]byte, error) {
+	// we try to use the most efficient way to marshal to existing slice
+	nm, ok := pm.(interface {
+		// this interface is implemented by generated messages
+		XXX_Size() int
+		XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
+	})
+	if ok {
+		sz := nm.XXX_Size()
+		if cap(b) < len(b)+sz {
+			// re-allocate to fit
+			bytes := make([]byte, len(b), len(b)+sz)
+			copy(bytes, b)
+			b = bytes
+		}
+		return nm.XXX_Marshal(b, deterministic)
+	}
+
+	if deterministic {
+		// see if the message has custom deterministic methods, preferring an
+		// "append" method over one that must always re-allocate
+		madm, ok := pm.(interface {
+			MarshalAppendDeterministic(b []byte) ([]byte, error)
+		})
+		if ok {
+			return madm.MarshalAppendDeterministic(b)
+		}
+
+		mdm, ok := pm.(interface {
+			MarshalDeterministic() ([]byte, error)
+		})
+		if ok {
+			bytes, err := mdm.MarshalDeterministic()
+			if err != nil {
+				return nil, err
+			}
+			if len(b) == 0 {
+				return bytes, nil
+			}
+			return append(b, bytes...), nil
+		}
+	}
+
+	mam, ok := pm.(interface {
+		// see if we can append the message, vs. having to re-allocate
+		MarshalAppend(b []byte) ([]byte, error)
+	})
+	if ok {
+		return mam.MarshalAppend(b)
+	}
+
+	// lowest common denominator
+	bytes, err := proto.Marshal(pm)
+	if err != nil {
+		return nil, err
+	}
+	if len(b) == 0 {
+		return bytes, nil
+	}
+	return append(b, bytes...), nil
+}
diff --git a/vendor/github.com/jhump/protoreflect/codec/encode_fields.go b/vendor/github.com/jhump/protoreflect/codec/encode_fields.go
new file mode 100644
index 0000000..cda7299
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/codec/encode_fields.go
@@ -0,0 +1,267 @@
+package codec
+
+import (
+	"fmt"
+	"math"
+	"reflect"
+	"sort"
+
+	"github.com/golang/protobuf/proto"
+	"github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+	"github.com/jhump/protoreflect/desc"
+)
+
+func (cb *Buffer) EncodeFieldValue(fd *desc.FieldDescriptor, val interface{}) error {
+	if fd.IsMap() {
+		mp := val.(map[interface{}]interface{})
+		entryType := fd.GetMessageType()
+		keyType := entryType.FindFieldByNumber(1)
+		valType := entryType.FindFieldByNumber(2)
+		var entryBuffer Buffer
+		if cb.deterministic {
+			keys := make([]interface{}, 0, len(mp))
+			for k := range mp {
+				keys = append(keys, k)
+			}
+			sort.Sort(sortable(keys))
+			for _, k := range keys {
+				v := mp[k]
+				entryBuffer.Reset()
+				if err := entryBuffer.encodeFieldElement(keyType, k); err != nil {
+					return err
+				}
+				if err := entryBuffer.encodeFieldElement(valType, v); err != nil {
+					return err
+				}
+				if err := cb.EncodeTagAndWireType(fd.GetNumber(), proto.WireBytes); err != nil {
+					return err
+				}
+				if err := cb.EncodeRawBytes(entryBuffer.Bytes()); err != nil {
+					return err
+				}
+			}
+		} else {
+			for k, v := range mp {
+				entryBuffer.Reset()
+				if err := entryBuffer.encodeFieldElement(keyType, k); err != nil {
+					return err
+				}
+				if err := entryBuffer.encodeFieldElement(valType, v); err != nil {
+					return err
+				}
+				if err := cb.EncodeTagAndWireType(fd.GetNumber(), proto.WireBytes); err != nil {
+					return err
+				}
+				if err := cb.EncodeRawBytes(entryBuffer.Bytes()); err != nil {
+					return err
+				}
+			}
+		}
+		return nil
+	} else if fd.IsRepeated() {
+		sl := val.([]interface{})
+		wt, err := getWireType(fd.GetType())
+		if err != nil {
+			return err
+		}
+		if isPacked(fd) && len(sl) > 1 &&
+			(wt == proto.WireVarint || wt == proto.WireFixed32 || wt == proto.WireFixed64) {
+			// packed repeated field
+			var packedBuffer Buffer
+			for _, v := range sl {
+				if err := packedBuffer.encodeFieldValue(fd, v); err != nil {
+					return err
+				}
+			}
+			if err := cb.EncodeTagAndWireType(fd.GetNumber(), proto.WireBytes); err != nil {
+				return err
+			}
+			return cb.EncodeRawBytes(packedBuffer.Bytes())
+		} else {
+			// non-packed repeated field
+			for _, v := range sl {
+				if err := cb.encodeFieldElement(fd, v); err != nil {
+					return err
+				}
+			}
+			return nil
+		}
+	} else {
+		return cb.encodeFieldElement(fd, val)
+	}
+}
+
+func isPacked(fd *desc.FieldDescriptor) bool {
+	opts := fd.AsFieldDescriptorProto().GetOptions()
+	// if set, use that value
+	if opts != nil && opts.Packed != nil {
+		return opts.GetPacked()
+	}
+	// if unset: proto2 defaults to false, proto3 to true
+	return fd.GetFile().IsProto3()
+}
+
+// sortable is used to sort map keys. Values will be integers (int32, int64, uint32, and uint64),
+// bools, or strings.
+type sortable []interface{}
+
+func (s sortable) Len() int {
+	return len(s)
+}
+
+func (s sortable) Less(i, j int) bool {
+	vi := s[i]
+	vj := s[j]
+	switch reflect.TypeOf(vi).Kind() {
+	case reflect.Int32:
+		return vi.(int32) < vj.(int32)
+	case reflect.Int64:
+		return vi.(int64) < vj.(int64)
+	case reflect.Uint32:
+		return vi.(uint32) < vj.(uint32)
+	case reflect.Uint64:
+		return vi.(uint64) < vj.(uint64)
+	case reflect.String:
+		return vi.(string) < vj.(string)
+	case reflect.Bool:
+		return !vi.(bool) && vj.(bool)
+	default:
+		panic(fmt.Sprintf("cannot compare keys of type %v", reflect.TypeOf(vi)))
+	}
+}
+
+func (s sortable) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+
+func (b *Buffer) encodeFieldElement(fd *desc.FieldDescriptor, val interface{}) error {
+	wt, err := getWireType(fd.GetType())
+	if err != nil {
+		return err
+	}
+	if err := b.EncodeTagAndWireType(fd.GetNumber(), wt); err != nil {
+		return err
+	}
+	if err := b.encodeFieldValue(fd, val); err != nil {
+		return err
+	}
+	if wt == proto.WireStartGroup {
+		return b.EncodeTagAndWireType(fd.GetNumber(), proto.WireEndGroup)
+	}
+	return nil
+}
+
+func (b *Buffer) encodeFieldValue(fd *desc.FieldDescriptor, val interface{}) error {
+	switch fd.GetType() {
+	case descriptor.FieldDescriptorProto_TYPE_BOOL:
+		v := val.(bool)
+		if v {
+			return b.EncodeVarint(1)
+		}
+		return b.EncodeVarint(0)
+
+	case descriptor.FieldDescriptorProto_TYPE_ENUM,
+		descriptor.FieldDescriptorProto_TYPE_INT32:
+		v := val.(int32)
+		return b.EncodeVarint(uint64(v))
+
+	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+		v := val.(int32)
+		return b.EncodeFixed32(uint64(v))
+
+	case descriptor.FieldDescriptorProto_TYPE_SINT32:
+		v := val.(int32)
+		return b.EncodeVarint(EncodeZigZag32(v))
+
+	case descriptor.FieldDescriptorProto_TYPE_UINT32:
+		v := val.(uint32)
+		return b.EncodeVarint(uint64(v))
+
+	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
+		v := val.(uint32)
+		return b.EncodeFixed32(uint64(v))
+
+	case descriptor.FieldDescriptorProto_TYPE_INT64:
+		v := val.(int64)
+		return b.EncodeVarint(uint64(v))
+
+	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+		v := val.(int64)
+		return b.EncodeFixed64(uint64(v))
+
+	case descriptor.FieldDescriptorProto_TYPE_SINT64:
+		v := val.(int64)
+		return b.EncodeVarint(EncodeZigZag64(v))
+
+	case descriptor.FieldDescriptorProto_TYPE_UINT64:
+		v := val.(uint64)
+		return b.EncodeVarint(v)
+
+	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
+		v := val.(uint64)
+		return b.EncodeFixed64(v)
+
+	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+		v := val.(float64)
+		return b.EncodeFixed64(math.Float64bits(v))
+
+	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+		v := val.(float32)
+		return b.EncodeFixed32(uint64(math.Float32bits(v)))
+
+	case descriptor.FieldDescriptorProto_TYPE_BYTES:
+		v := val.([]byte)
+		return b.EncodeRawBytes(v)
+
+	case descriptor.FieldDescriptorProto_TYPE_STRING:
+		v := val.(string)
+		return b.EncodeRawBytes(([]byte)(v))
+
+	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+		return b.EncodeDelimitedMessage(val.(proto.Message))
+
+	case descriptor.FieldDescriptorProto_TYPE_GROUP:
+		// just append the nested message to this buffer
+		return b.EncodeMessage(val.(proto.Message))
+		// whosoever writeth start-group tag (e.g. caller) is responsible for writing end-group tag
+
+	default:
+		return fmt.Errorf("unrecognized field type: %v", fd.GetType())
+	}
+}
+
+func getWireType(t descriptor.FieldDescriptorProto_Type) (int8, error) {
+	switch t {
+	case descriptor.FieldDescriptorProto_TYPE_ENUM,
+		descriptor.FieldDescriptorProto_TYPE_BOOL,
+		descriptor.FieldDescriptorProto_TYPE_INT32,
+		descriptor.FieldDescriptorProto_TYPE_SINT32,
+		descriptor.FieldDescriptorProto_TYPE_UINT32,
+		descriptor.FieldDescriptorProto_TYPE_INT64,
+		descriptor.FieldDescriptorProto_TYPE_SINT64,
+		descriptor.FieldDescriptorProto_TYPE_UINT64:
+		return proto.WireVarint, nil
+
+	case descriptor.FieldDescriptorProto_TYPE_FIXED32,
+		descriptor.FieldDescriptorProto_TYPE_SFIXED32,
+		descriptor.FieldDescriptorProto_TYPE_FLOAT:
+		return proto.WireFixed32, nil
+
+	case descriptor.FieldDescriptorProto_TYPE_FIXED64,
+		descriptor.FieldDescriptorProto_TYPE_SFIXED64,
+		descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+		return proto.WireFixed64, nil
+
+	case descriptor.FieldDescriptorProto_TYPE_BYTES,
+		descriptor.FieldDescriptorProto_TYPE_STRING,
+		descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+		return proto.WireBytes, nil
+
+	case descriptor.FieldDescriptorProto_TYPE_GROUP:
+		return proto.WireStartGroup, nil
+
+	default:
+		return 0, ErrBadWireType
+	}
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/convert.go b/vendor/github.com/jhump/protoreflect/desc/convert.go
index 6573c90..538820c 100644
--- a/vendor/github.com/jhump/protoreflect/desc/convert.go
+++ b/vendor/github.com/jhump/protoreflect/desc/convert.go
@@ -166,16 +166,31 @@
 }
 
 func createFileDescriptorFromSet(fds *dpb.FileDescriptorSet, r *ImportResolver) (*FileDescriptor, error) {
+	result, err := createFileDescriptorsFromSet(fds, r)
+	if err != nil {
+		return nil, err
+	}
+	files := fds.GetFile()
+	lastFilename := files[len(files)-1].GetName()
+	return result[lastFilename], nil
+}
+
+// CreateFileDescriptorsFromSet creates file descriptors from the given file descriptor set.
+// The returned map includes all files in the set, keyed b name. The set must include the
+// full set of transitive dependencies for all files therein or else a link error will occur
+// and be returned instead of the slice of descriptors. This is the same format used by
+// protoc when a FileDescriptorSet file with an invocation like so:
+//    protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
+func CreateFileDescriptorsFromSet(fds *dpb.FileDescriptorSet) (map[string]*FileDescriptor, error) {
+	return createFileDescriptorsFromSet(fds, nil)
+}
+
+func createFileDescriptorsFromSet(fds *dpb.FileDescriptorSet, r *ImportResolver) (map[string]*FileDescriptor, error) {
 	files := fds.GetFile()
 	if len(files) == 0 {
 		return nil, errors.New("file descriptor set is empty")
 	}
-	resolved, err := createFileDescriptors(files, r)
-	if err != nil {
-		return nil, err
-	}
-	lastFilename := files[len(files)-1].GetName()
-	return resolved[lastFilename], nil
+	return createFileDescriptors(files, r)
 }
 
 // createFromSet creates a descriptor for the given filename. It recursively
diff --git a/vendor/github.com/jhump/protoreflect/desc/descriptor_no_unsafe.go b/vendor/github.com/jhump/protoreflect/desc/descriptor_no_unsafe.go
index d8e2df0..cd7348e 100644
--- a/vendor/github.com/jhump/protoreflect/desc/descriptor_no_unsafe.go
+++ b/vendor/github.com/jhump/protoreflect/desc/descriptor_no_unsafe.go
@@ -1,5 +1,6 @@
-//+build appengine
-// TODO: other build tags for environments where unsafe package is inappropriate
+//+build appengine gopherjs purego
+// NB: other environments where unsafe is unappropriate should use "purego" build tag
+// https://github.com/golang/go/issues/23172
 
 package desc
 
diff --git a/vendor/github.com/jhump/protoreflect/desc/descriptor_unsafe.go b/vendor/github.com/jhump/protoreflect/desc/descriptor_unsafe.go
index 6ff872f..19b808d 100644
--- a/vendor/github.com/jhump/protoreflect/desc/descriptor_unsafe.go
+++ b/vendor/github.com/jhump/protoreflect/desc/descriptor_unsafe.go
@@ -1,5 +1,6 @@
-//+build !appengine
-// TODO: exclude other build tags for environments where unsafe package is inappropriate
+//+build !appengine,!gopherjs,!purego
+// NB: other environments where unsafe is unappropriate should use "purego" build tag
+// https://github.com/golang/go/issues/23172
 
 package desc
 
diff --git a/vendor/github.com/jhump/protoreflect/desc/imports.go b/vendor/github.com/jhump/protoreflect/desc/imports.go
index caf3277..ab93032 100644
--- a/vendor/github.com/jhump/protoreflect/desc/imports.go
+++ b/vendor/github.com/jhump/protoreflect/desc/imports.go
@@ -292,6 +292,13 @@
 	return createFileDescriptorFromSet(fds, r)
 }
 
+// CreateFileDescriptorsFromSet is the same as the package function of the same
+// name, but any alternate paths configured in this resolver are used when
+// linking the descriptor protos in the given set.
+func (r *ImportResolver) CreateFileDescriptorsFromSet(fds *dpb.FileDescriptorSet) (map[string]*FileDescriptor, error) {
+	return createFileDescriptorsFromSet(fds, r)
+}
+
 const dotPrefix = "." + string(filepath.Separator)
 
 func clean(path string) string {
diff --git a/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go b/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go
index 4d7dbae..b4150b8 100644
--- a/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go
+++ b/vendor/github.com/jhump/protoreflect/desc/internal/source_info.go
@@ -6,16 +6,26 @@
 
 // SourceInfoMap is a map of paths in a descriptor to the corresponding source
 // code info.
-type SourceInfoMap map[string]*dpb.SourceCodeInfo_Location
+type SourceInfoMap map[string][]*dpb.SourceCodeInfo_Location
 
-// Get returns the source code info for the given path.
+// Get returns the source code info for the given path. If there are
+// multiple locations for the same path, the first one is returned.
 func (m SourceInfoMap) Get(path []int32) *dpb.SourceCodeInfo_Location {
+	v := m[asMapKey(path)]
+	if len(v) > 0 {
+		return v[0]
+	}
+	return nil
+}
+
+// GetAll returns all source code info for the given path.
+func (m SourceInfoMap) GetAll(path []int32) []*dpb.SourceCodeInfo_Location {
 	return m[asMapKey(path)]
 }
 
-// Put stores the given source code info for the given path.
-func (m SourceInfoMap) Put(path []int32, loc *dpb.SourceCodeInfo_Location) {
-	m[asMapKey(path)] = loc
+// Add stores the given source code info for the given path.
+func (m SourceInfoMap) Add(path []int32, loc *dpb.SourceCodeInfo_Location) {
+	m[asMapKey(path)] = append(m[asMapKey(path)], loc)
 }
 
 // PutIfAbsent stores the given source code info for the given path only if the
@@ -26,7 +36,7 @@
 	if _, ok := m[k]; ok {
 		return false
 	}
-	m[k] = loc
+	m[k] = []*dpb.SourceCodeInfo_Location{loc}
 	return true
 }
 
@@ -40,12 +50,13 @@
 	//return array.Interface()
 
 	b := make([]byte, len(slice)*4)
-	for i, s := range slice {
-		j := i * 4
+	j := 0
+	for _, s := range slice {
 		b[j] = byte(s)
 		b[j+1] = byte(s >> 8)
 		b[j+2] = byte(s >> 16)
 		b[j+3] = byte(s >> 24)
+		j += 4
 	}
 	return string(b)
 }
@@ -62,7 +73,7 @@
 // the given file descriptor.
 func PopulateSourceInfoMap(fd *dpb.FileDescriptorProto, m SourceInfoMap) {
 	for _, l := range fd.GetSourceCodeInfo().GetLocation() {
-		m.Put(l.Path, l)
+		m.Add(l.Path, l)
 	}
 }
 
diff --git a/vendor/github.com/jhump/protoreflect/desc/internal/util.go b/vendor/github.com/jhump/protoreflect/desc/internal/util.go
index d5197f1..139c9cd 100644
--- a/vendor/github.com/jhump/protoreflect/desc/internal/util.go
+++ b/vendor/github.com/jhump/protoreflect/desc/internal/util.go
@@ -105,6 +105,9 @@
 	// Field_typeTag is the tag number of the type element in a field descriptor
 	// proto.
 	Field_typeTag = 5
+	// Field_typeNameTag is the tag number of the type name element in a field
+	// descriptor proto.
+	Field_typeNameTag = 6
 	// Field_defaultTag is the tag number of the default value element in a
 	// field descriptor proto.
 	Field_defaultTag = 7
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/ast.go b/vendor/github.com/jhump/protoreflect/desc/protoparse/ast.go
index 2499917..e1eb4df 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoparse/ast.go
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/ast.go
@@ -1,24 +1,7 @@
 package protoparse
 
-import "fmt"
-
 // This file defines all of the nodes in the proto AST.
 
-// ErrorWithSourcePos is an error about a proto source file includes information
-// about the location in the file that caused the error.
-type ErrorWithSourcePos struct {
-	Underlying error
-	Pos        *SourcePos
-}
-
-// Error implements the error interface
-func (e ErrorWithSourcePos) Error() string {
-	if e.Pos.Line <= 0 || e.Pos.Col <= 0 {
-		return fmt.Sprintf("%s: %v", e.Pos.Filename, e.Underlying)
-	}
-	return fmt.Sprintf("%s:%d:%d: %v", e.Pos.Filename, e.Pos.Line, e.Pos.Col, e.Underlying)
-}
-
 // SourcePos identifies a location in a proto source file.
 type SourcePos struct {
 	Filename  string
@@ -30,17 +13,18 @@
 	return &SourcePos{Filename: filename}
 }
 
+// node is the interface implemented by all nodes in the AST
 type node interface {
 	start() *SourcePos
 	end() *SourcePos
-	leadingComments() []*comment
-	trailingComments() []*comment
+	leadingComments() []comment
+	trailingComments() []comment
 }
 
 type terminalNode interface {
 	node
-	popLeadingComment() *comment
-	pushTrailingComment(*comment)
+	popLeadingComment() comment
+	pushTrailingComment(comment)
 }
 
 var _ terminalNode = (*basicNode)(nil)
@@ -103,7 +87,6 @@
 type msgDecl interface {
 	node
 	messageName() node
-	reservedNames() []*stringLiteralNode
 }
 
 var _ msgDecl = (*messageNode)(nil)
@@ -121,38 +104,38 @@
 var _ methodDecl = (*noSourceNode)(nil)
 
 type posRange struct {
-	start, end *SourcePos
+	start, end SourcePos
 }
 
 type basicNode struct {
 	posRange
-	leading  []*comment
-	trailing []*comment
+	leading  []comment
+	trailing []comment
 }
 
 func (n *basicNode) start() *SourcePos {
-	return n.posRange.start
+	return &n.posRange.start
 }
 
 func (n *basicNode) end() *SourcePos {
-	return n.posRange.end
+	return &n.posRange.end
 }
 
-func (n *basicNode) leadingComments() []*comment {
+func (n *basicNode) leadingComments() []comment {
 	return n.leading
 }
 
-func (n *basicNode) trailingComments() []*comment {
+func (n *basicNode) trailingComments() []comment {
 	return n.trailing
 }
 
-func (n *basicNode) popLeadingComment() *comment {
+func (n *basicNode) popLeadingComment() comment {
 	c := n.leading[0]
 	n.leading = n.leading[1:]
 	return c
 }
 
-func (n *basicNode) pushTrailingComment(c *comment) {
+func (n *basicNode) pushTrailingComment(c comment) {
 	n.trailing = append(n.trailing, c)
 }
 
@@ -174,11 +157,11 @@
 	return n.last.end()
 }
 
-func (n *basicCompositeNode) leadingComments() []*comment {
+func (n *basicCompositeNode) leadingComments() []comment {
 	return n.first.leadingComments()
 }
 
-func (n *basicCompositeNode) trailingComments() []*comment {
+func (n *basicCompositeNode) trailingComments() []comment {
 	return n.last.trailingComments()
 }
 
@@ -192,13 +175,9 @@
 	syntax *syntaxNode
 	decls  []*fileElement
 
-	// These fields are populated after parsing, to make it easier to find them
-	// without searching decls. The parse result has a map of descriptors to
-	// nodes which makes the other declarations easily discoverable. But these
-	// elements do not map to descriptors -- they are just stored as strings in
-	// the file descriptor.
+	// This field is populated after parsing, to make it easier to find
+	// source locations by import name for constructing link errors.
 	imports []*importNode
-	pkg     *packageNode
 }
 
 func (n *fileNode) getSyntax() node {
@@ -225,11 +204,11 @@
 	return n.get().end()
 }
 
-func (n *fileElement) leadingComments() []*comment {
+func (n *fileElement) leadingComments() []comment {
 	return n.get().leadingComments()
 }
 
-func (n *fileElement) trailingComments() []*comment {
+func (n *fileElement) trailingComments() []comment {
 	return n.get().trailingComments()
 }
 
@@ -256,41 +235,53 @@
 
 type syntaxNode struct {
 	basicCompositeNode
-	syntax *stringLiteralNode
+	syntax *compoundStringNode
 }
 
 type importNode struct {
 	basicCompositeNode
-	name   *stringLiteralNode
+	name   *compoundStringNode
 	public bool
 	weak   bool
 }
 
 type packageNode struct {
 	basicCompositeNode
-	name *identNode
+	name *compoundIdentNode
 }
 
 type identifier string
 
-type identKind int
-
-const (
-	identSimpleName identKind = iota
-	identQualified
-	identTypeName
-)
-
 type identNode struct {
 	basicNode
-	val  string
-	kind identKind
+	val string
 }
 
 func (n *identNode) value() interface{} {
 	return identifier(n.val)
 }
 
+type compoundIdentNode struct {
+	basicCompositeNode
+	val string
+}
+
+func (n *compoundIdentNode) value() interface{} {
+	return identifier(n.val)
+}
+
+type compactOptionsNode struct {
+	basicCompositeNode
+	decls []*optionNode
+}
+
+func (n *compactOptionsNode) Elements() []*optionNode {
+	if n == nil {
+		return nil
+	}
+	return n.decls
+}
+
 type optionNode struct {
 	basicCompositeNode
 	name *optionNameNode
@@ -312,7 +303,7 @@
 
 type optionNamePartNode struct {
 	basicCompositeNode
-	text        *identNode
+	text        *compoundIdentNode
 	offset      int
 	length      int
 	isExtension bool
@@ -350,17 +341,22 @@
 	value() interface{}
 }
 
+var _ valueNode = (*identNode)(nil)
+var _ valueNode = (*compoundIdentNode)(nil)
 var _ valueNode = (*stringLiteralNode)(nil)
+var _ valueNode = (*compoundStringNode)(nil)
 var _ valueNode = (*intLiteralNode)(nil)
-var _ valueNode = (*negativeIntLiteralNode)(nil)
+var _ valueNode = (*compoundIntNode)(nil)
+var _ valueNode = (*compoundUintNode)(nil)
 var _ valueNode = (*floatLiteralNode)(nil)
+var _ valueNode = (*compoundFloatNode)(nil)
 var _ valueNode = (*boolLiteralNode)(nil)
 var _ valueNode = (*sliceLiteralNode)(nil)
 var _ valueNode = (*aggregateLiteralNode)(nil)
 var _ valueNode = (*noSourceNode)(nil)
 
 type stringLiteralNode struct {
-	basicCompositeNode
+	basicNode
 	val string
 }
 
@@ -368,12 +364,13 @@
 	return n.val
 }
 
-func (n *stringLiteralNode) popLeadingComment() *comment {
-	return n.first.(terminalNode).popLeadingComment()
+type compoundStringNode struct {
+	basicCompositeNode
+	val string
 }
 
-func (n *stringLiteralNode) pushTrailingComment(c *comment) {
-	n.last.(terminalNode).pushTrailingComment(c)
+func (n *compoundStringNode) value() interface{} {
+	return n.val
 }
 
 type intLiteralNode struct {
@@ -385,17 +382,26 @@
 	return n.val
 }
 
-type negativeIntLiteralNode struct {
+type compoundUintNode struct {
+	basicCompositeNode
+	val uint64
+}
+
+func (n *compoundUintNode) value() interface{} {
+	return n.val
+}
+
+type compoundIntNode struct {
 	basicCompositeNode
 	val int64
 }
 
-func (n *negativeIntLiteralNode) value() interface{} {
+func (n *compoundIntNode) value() interface{} {
 	return n.val
 }
 
 type floatLiteralNode struct {
-	basicCompositeNode
+	basicNode
 	val float64
 }
 
@@ -403,16 +409,17 @@
 	return n.val
 }
 
-func (n *floatLiteralNode) popLeadingComment() *comment {
-	return n.first.(terminalNode).popLeadingComment()
+type compoundFloatNode struct {
+	basicCompositeNode
+	val float64
 }
 
-func (n *floatLiteralNode) pushTrailingComment(c *comment) {
-	n.last.(terminalNode).pushTrailingComment(c)
+func (n *compoundFloatNode) value() interface{} {
+	return n.val
 }
 
 type boolLiteralNode struct {
-	basicNode
+	*identNode
 	val bool
 }
 
@@ -446,7 +453,7 @@
 
 type aggregateNameNode struct {
 	basicCompositeNode
-	name        *identNode
+	name        *compoundIdentNode
 	isExtension bool
 }
 
@@ -460,11 +467,11 @@
 
 type fieldNode struct {
 	basicCompositeNode
-	label   *labelNode
-	fldType *identNode
+	label   fieldLabel
+	fldType *compoundIdentNode
 	name    *identNode
 	tag     *intLiteralNode
-	options []*optionNode
+	options *compactOptionsNode
 
 	// This field is populated after parsing, to allow lookup of extendee source
 	// locations when field extendees cannot be linked. (Otherwise, this is just
@@ -477,10 +484,10 @@
 	// proto3 fields and fields inside one-ofs will not have a label and we need
 	// this check in order to return a nil node -- otherwise we'd return a
 	// non-nil node that has a nil pointer value in it :/
-	if n.label == nil {
+	if n.label.identNode == nil {
 		return nil
 	}
-	return n.label
+	return n.label.identNode
 }
 
 func (n *fieldNode) fieldName() node {
@@ -506,8 +513,8 @@
 	return nil
 }
 
-type labelNode struct {
-	basicNode
+type fieldLabel struct {
+	*identNode
 	repeated bool
 	required bool
 }
@@ -515,17 +522,11 @@
 type groupNode struct {
 	basicCompositeNode
 	groupKeyword *identNode
-	label        *labelNode
+	label        fieldLabel
 	name         *identNode
 	tag          *intLiteralNode
 	decls        []*messageElement
 
-	// This field is populated after parsing, to make it easier to find them
-	// without searching decls. The parse result has a map of descriptors to
-	// nodes which makes the other declarations easily discoverable. But these
-	// elements do not map to descriptors -- they are just stored as strings in
-	// the message descriptor.
-	reserved []*stringLiteralNode
 	// This field is populated after parsing, to allow lookup of extendee source
 	// locations when field extendees cannot be linked. (Otherwise, this is just
 	// stored as a string in the field descriptors defined inside the extend
@@ -534,7 +535,11 @@
 }
 
 func (n *groupNode) fieldLabel() node {
-	return n.label
+	if n.label.identNode == nil {
+		// return nil interface to indicate absence, not a typed nil
+		return nil
+	}
+	return n.label.identNode
 }
 
 func (n *groupNode) fieldName() node {
@@ -542,7 +547,7 @@
 }
 
 func (n *groupNode) fieldType() node {
-	return n.name
+	return n.groupKeyword
 }
 
 func (n *groupNode) fieldTag() node {
@@ -564,10 +569,6 @@
 	return n.name
 }
 
-func (n *groupNode) reservedNames() []*stringLiteralNode {
-	return n.reserved
-}
-
 type oneOfNode struct {
 	basicCompositeNode
 	name  *identNode
@@ -578,6 +579,7 @@
 	// a discriminated union: only one field will be set
 	option *optionNode
 	field  *fieldNode
+	group  *groupNode
 	empty  *basicNode
 }
 
@@ -589,11 +591,11 @@
 	return n.get().end()
 }
 
-func (n *oneOfElement) leadingComments() []*comment {
+func (n *oneOfElement) leadingComments() []comment {
 	return n.get().leadingComments()
 }
 
-func (n *oneOfElement) trailingComments() []*comment {
+func (n *oneOfElement) trailingComments() []comment {
 	return n.get().trailingComments()
 }
 
@@ -608,18 +610,23 @@
 	}
 }
 
-type mapFieldNode struct {
+type mapTypeNode struct {
 	basicCompositeNode
 	mapKeyword *identNode
 	keyType    *identNode
-	valueType  *identNode
-	name       *identNode
-	tag        *intLiteralNode
-	options    []*optionNode
+	valueType  *compoundIdentNode
+}
+
+type mapFieldNode struct {
+	basicCompositeNode
+	mapType *mapTypeNode
+	name    *identNode
+	tag     *intLiteralNode
+	options *compactOptionsNode
 }
 
 func (n *mapFieldNode) fieldLabel() node {
-	return n.mapKeyword
+	return nil
 }
 
 func (n *mapFieldNode) fieldName() node {
@@ -627,7 +634,7 @@
 }
 
 func (n *mapFieldNode) fieldType() node {
-	return n.mapKeyword
+	return n.mapType
 }
 
 func (n *mapFieldNode) fieldTag() node {
@@ -646,32 +653,29 @@
 	return n.name
 }
 
-func (n *mapFieldNode) reservedNames() []*stringLiteralNode {
-	return nil
-}
-
 func (n *mapFieldNode) keyField() *syntheticMapField {
-	tag := &intLiteralNode{
-		basicNode: basicNode{
-			posRange: posRange{start: n.keyType.start(), end: n.keyType.end()},
-		},
-		val: 1,
-	}
-	return &syntheticMapField{ident: n.keyType, tag: tag}
+	k := n.mapType.keyType
+	t := &compoundIdentNode{val: k.val}
+	t.setRange(k, k)
+	return newSyntheticMapField(t, 1)
 }
 
 func (n *mapFieldNode) valueField() *syntheticMapField {
+	return newSyntheticMapField(n.mapType.valueType, 2)
+}
+
+func newSyntheticMapField(ident *compoundIdentNode, tagNum uint64) *syntheticMapField {
 	tag := &intLiteralNode{
 		basicNode: basicNode{
-			posRange: posRange{start: n.valueType.start(), end: n.valueType.end()},
+			posRange: posRange{start: *ident.start(), end: *ident.end()},
 		},
-		val: 2,
+		val: tagNum,
 	}
-	return &syntheticMapField{ident: n.valueType, tag: tag}
+	return &syntheticMapField{ident: ident, tag: tag}
 }
 
 type syntheticMapField struct {
-	ident *identNode
+	ident *compoundIdentNode
 	tag   *intLiteralNode
 }
 
@@ -683,11 +687,11 @@
 	return n.ident.end()
 }
 
-func (n *syntheticMapField) leadingComments() []*comment {
+func (n *syntheticMapField) leadingComments() []comment {
 	return nil
 }
 
-func (n *syntheticMapField) trailingComments() []*comment {
+func (n *syntheticMapField) trailingComments() []comment {
 	return nil
 }
 
@@ -718,7 +722,7 @@
 type extensionRangeNode struct {
 	basicCompositeNode
 	ranges  []*rangeNode
-	options []*optionNode
+	options *compactOptionsNode
 }
 
 type rangeNode struct {
@@ -738,20 +742,13 @@
 type reservedNode struct {
 	basicCompositeNode
 	ranges []*rangeNode
-	names  []*stringLiteralNode
+	names  []*compoundStringNode
 }
 
 type enumNode struct {
 	basicCompositeNode
 	name  *identNode
 	decls []*enumElement
-
-	// This field is populated after parsing, to make it easier to find them
-	// without searching decls. The parse result has a map of descriptors to
-	// nodes which makes the other declarations easily discoverable. But these
-	// elements do not map to descriptors -- they are just stored as strings in
-	// the message descriptor.
-	reserved []*stringLiteralNode
 }
 
 type enumElement struct {
@@ -770,11 +767,11 @@
 	return n.get().end()
 }
 
-func (n *enumElement) leadingComments() []*comment {
+func (n *enumElement) leadingComments() []comment {
 	return n.get().leadingComments()
 }
 
-func (n *enumElement) trailingComments() []*comment {
+func (n *enumElement) trailingComments() []comment {
 	return n.get().trailingComments()
 }
 
@@ -792,12 +789,8 @@
 type enumValueNode struct {
 	basicCompositeNode
 	name    *identNode
-	options []*optionNode
-
-	// only one of these two will be set:
-
-	numberP *intLiteralNode         // positive numeric value
-	numberN *negativeIntLiteralNode // negative numeric value
+	options *compactOptionsNode
+	number  *compoundIntNode
 }
 
 func (n *enumValueNode) getName() node {
@@ -805,33 +798,19 @@
 }
 
 func (n *enumValueNode) getNumber() node {
-	if n.numberP != nil {
-		return n.numberP
-	}
-	return n.numberN
+	return n.number
 }
 
 type messageNode struct {
 	basicCompositeNode
 	name  *identNode
 	decls []*messageElement
-
-	// This field is populated after parsing, to make it easier to find them
-	// without searching decls. The parse result has a map of descriptors to
-	// nodes which makes the other declarations easily discoverable. But these
-	// elements do not map to descriptors -- they are just stored as strings in
-	// the message descriptor.
-	reserved []*stringLiteralNode
 }
 
 func (n *messageNode) messageName() node {
 	return n.name
 }
 
-func (n *messageNode) reservedNames() []*stringLiteralNode {
-	return n.reserved
-}
-
 type messageElement struct {
 	// a discriminated union: only one field will be set
 	option         *optionNode
@@ -855,11 +834,11 @@
 	return n.get().end()
 }
 
-func (n *messageElement) leadingComments() []*comment {
+func (n *messageElement) leadingComments() []comment {
 	return n.get().leadingComments()
 }
 
-func (n *messageElement) trailingComments() []*comment {
+func (n *messageElement) trailingComments() []comment {
 	return n.get().trailingComments()
 }
 
@@ -892,7 +871,7 @@
 
 type extendNode struct {
 	basicCompositeNode
-	extendee *identNode
+	extendee *compoundIdentNode
 	decls    []*extendElement
 }
 
@@ -911,11 +890,11 @@
 	return n.get().end()
 }
 
-func (n *extendElement) leadingComments() []*comment {
+func (n *extendElement) leadingComments() []comment {
 	return n.get().leadingComments()
 }
 
-func (n *extendElement) trailingComments() []*comment {
+func (n *extendElement) trailingComments() []comment {
 	return n.get().trailingComments()
 }
 
@@ -951,11 +930,11 @@
 	return n.get().end()
 }
 
-func (n *serviceElement) leadingComments() []*comment {
+func (n *serviceElement) leadingComments() []comment {
 	return n.get().leadingComments()
 }
 
-func (n *serviceElement) trailingComments() []*comment {
+func (n *serviceElement) trailingComments() []comment {
 	return n.get().trailingComments()
 }
 
@@ -988,7 +967,7 @@
 
 type rpcTypeNode struct {
 	basicCompositeNode
-	msgType       *identNode
+	msgType       *compoundIdentNode
 	streamKeyword node
 }
 
@@ -1004,11 +983,11 @@
 	return n.pos
 }
 
-func (n noSourceNode) leadingComments() []*comment {
+func (n noSourceNode) leadingComments() []comment {
 	return nil
 }
 
-func (n noSourceNode) trailingComments() []*comment {
+func (n noSourceNode) trailingComments() []comment {
 	return nil
 }
 
@@ -1064,10 +1043,6 @@
 	return n
 }
 
-func (n noSourceNode) reservedNames() []*stringLiteralNode {
-	return nil
-}
-
 func (n noSourceNode) getInputType() node {
 	return n
 }
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/errors.go b/vendor/github.com/jhump/protoreflect/desc/protoparse/errors.go
new file mode 100644
index 0000000..07a6214
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/errors.go
@@ -0,0 +1,103 @@
+package protoparse
+
+import (
+	"errors"
+	"fmt"
+)
+
+// ErrInvalidSource is a sentinel error that is returned by calls to
+// Parser.ParseFiles and Parser.ParseFilesButDoNotLink in the event that syntax
+// or link errors are encountered, but the parser's configured ErrorReporter
+// always returns nil.
+var ErrInvalidSource = errors.New("parse failed: invalid proto source")
+
+// ErrorReporter is responsible for reporting the given error. If the reporter
+// returns a non-nil error, parsing/linking will abort with that error. If the
+// reporter returns nil, parsing will continue, allowing the parser to try to
+// report as many syntax and/or link errors as it can find.
+type ErrorReporter func(err ErrorWithPos) error
+
+func defaultErrorReporter(err ErrorWithPos) error {
+	// abort parsing after first error encountered
+	return err
+}
+
+type errorHandler struct {
+	reporter     ErrorReporter
+	errsReported bool
+	err          error
+}
+
+func newErrorHandler(reporter ErrorReporter) *errorHandler {
+	if reporter == nil {
+		reporter = defaultErrorReporter
+	}
+	return &errorHandler{
+		reporter: reporter,
+	}
+}
+
+func (h *errorHandler) handleError(err error) error {
+	if h.err != nil {
+		return h.err
+	}
+	if ewp, ok := err.(ErrorWithPos); ok {
+		h.errsReported = true
+		err = h.reporter(ewp)
+	}
+	h.err = err
+	return err
+}
+
+func (h *errorHandler) getError() error {
+	if h.errsReported && h.err == nil {
+		return ErrInvalidSource
+	}
+	return h.err
+}
+
+// ErrorWithPos is an error about a proto source file that includes information
+// about the location in the file that caused the error.
+//
+// The value of Error() will contain both the SourcePos and Underlying error.
+// The value of Unwrap() will only be the Underlying error.
+type ErrorWithPos interface {
+	error
+	GetPosition() SourcePos
+	Unwrap() error
+}
+
+// ErrorWithSourcePos is an error about a proto source file that includes
+// information about the location in the file that caused the error.
+//
+// Errors that include source location information *might* be of this type.
+// However, calling code that is trying to examine errors with location info
+// should instead look for instances of the ErrorWithPos interface, which
+// will find other kinds of errors. This type is only exported for backwards
+// compatibility.
+type ErrorWithSourcePos struct {
+	Underlying error
+	Pos        *SourcePos
+}
+
+// Error implements the error interface
+func (e ErrorWithSourcePos) Error() string {
+	if e.Pos.Line <= 0 || e.Pos.Col <= 0 {
+		return fmt.Sprintf("%s: %v", e.Pos.Filename, e.Underlying)
+	}
+	return fmt.Sprintf("%s:%d:%d: %v", e.Pos.Filename, e.Pos.Line, e.Pos.Col, e.Underlying)
+}
+
+// GetPosition implements the ErrorWithPos interface, supplying a location in
+// proto source that caused the error.
+func (e ErrorWithSourcePos) GetPosition() SourcePos {
+	return *e.Pos
+}
+
+// Unwrap implements the ErrorWithPos interface, supplying the underlying
+// error. This error will not include location information.
+func (e ErrorWithSourcePos) Unwrap() error {
+	return e.Underlying
+}
+
+var _ ErrorWithPos = ErrorWithSourcePos{}
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/lexer.go b/vendor/github.com/jhump/protoreflect/desc/protoparse/lexer.go
index c685e56..b0b5f5b 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoparse/lexer.go
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/lexer.go
@@ -39,15 +39,13 @@
 
 func lexError(l protoLexer, pos *SourcePos, err string) {
 	pl := l.(*protoLex)
-	if pl.err == nil {
-		pl.err = ErrorWithSourcePos{Underlying: errors.New(err), Pos: pos}
-	}
+	_ = pl.errs.handleError(ErrorWithSourcePos{Underlying: errors.New(err), Pos: pos})
 }
 
 type protoLex struct {
 	filename string
 	input    *runeReader
-	err      error
+	errs     *errorHandler
 	res      *fileNode
 
 	lineNo int
@@ -55,10 +53,23 @@
 	offset int
 
 	prevSym terminalNode
+
+	prevLineNo int
+	prevColNo  int
+	prevOffset int
+	comments   []comment
 }
 
-func newLexer(in io.Reader) *protoLex {
-	return &protoLex{input: &runeReader{rr: bufio.NewReader(in)}}
+func newTestLexer(in io.Reader) *protoLex {
+	return newLexer(in, "test.proto", newErrorHandler(nil))
+}
+
+func newLexer(in io.Reader, filename string, errs *errorHandler) *protoLex {
+	return &protoLex{
+		input:    &runeReader{rr: bufio.NewReader(in)},
+		filename: filename,
+		errs:     errs,
+	}
 }
 
 var keywords = map[string]int{
@@ -106,8 +117,8 @@
 	"returns":    _RETURNS,
 }
 
-func (l *protoLex) cur() *SourcePos {
-	return &SourcePos{
+func (l *protoLex) cur() SourcePos {
+	return SourcePos{
 		Filename: l.filename,
 		Offset:   l.offset,
 		Line:     l.lineNo + 1,
@@ -115,6 +126,25 @@
 	}
 }
 
+func (l *protoLex) adjustPos(consumedChars ...rune) {
+	for _, c := range consumedChars {
+		switch c {
+		case '\n':
+			// new line, back to first column
+			l.colNo = 0
+			l.lineNo++
+		case '\r':
+			// no adjustment
+		case '\t':
+			// advance to next tab stop
+			mod := l.colNo % 8
+			l.colNo += 8 - mod
+		default:
+			l.colNo++
+		}
+	}
+}
+
 func (l *protoLex) prev() *SourcePos {
 	if l.prevSym == nil {
 		return &SourcePos{
@@ -128,131 +158,16 @@
 }
 
 func (l *protoLex) Lex(lval *protoSymType) int {
-	if l.err != nil {
-		// if we are already in a failed state, bail
-		lval.err = l.err
-		return _ERROR
+	if l.errs.err != nil {
+		// if error reporter already returned non-nil error,
+		// we can skip the rest of the input
+		return 0
 	}
 
-	prevLineNo := l.lineNo
-	prevColNo := l.colNo
-	prevOffset := l.offset
-	var comments []*comment
-
-	pos := func() posRange {
-		return posRange{
-			start: &SourcePos{
-				Filename: l.filename,
-				Offset:   prevOffset,
-				Line:     prevLineNo + 1,
-				Col:      prevColNo + 1,
-			},
-			end: l.cur(),
-		}
-	}
-	basic := func() basicNode {
-		return basicNode{
-			posRange: pos(),
-			leading:  comments,
-		}
-	}
-	setPrev := func(n terminalNode) {
-		nStart := n.start().Line
-		if _, ok := n.(*basicNode); ok {
-			// if the node is a simple rune, don't attribute comments to it
-			// HACK: adjusting the start line makes leading comments appear
-			// detached so logic below will naturally associated trailing
-			// comment to previous symbol
-			nStart += 2
-		}
-		if l.prevSym != nil && len(n.leadingComments()) > 0 && l.prevSym.end().Line < nStart {
-			// we may need to re-attribute the first comment to
-			// instead be previous node's trailing comment
-			prevEnd := l.prevSym.end().Line
-			comments := n.leadingComments()
-			c := comments[0]
-			commentStart := c.start.Line
-			if commentStart == prevEnd {
-				// comment is on same line as previous symbol
-				n.popLeadingComment()
-				l.prevSym.pushTrailingComment(c)
-			} else if commentStart == prevEnd+1 {
-				// comment is right after previous symbol; see if it is detached
-				// and if so re-attribute
-				singleLineStyle := strings.HasPrefix(c.text, "//")
-				line := c.end.Line
-				groupEnd := -1
-				for i := 1; i < len(comments); i++ {
-					c := comments[i]
-					newGroup := false
-					if !singleLineStyle || c.start.Line > line+1 {
-						// we've found a gap between comments, which means the
-						// previous comments were detached
-						newGroup = true
-					} else {
-						line = c.end.Line
-						singleLineStyle = strings.HasPrefix(comments[i].text, "//")
-						if !singleLineStyle {
-							// we've found a switch from // comments to /*
-							// consider that a new group which means the
-							// previous comments were detached
-							newGroup = true
-						}
-					}
-					if newGroup {
-						groupEnd = i
-						break
-					}
-				}
-
-				if groupEnd == -1 {
-					// just one group of comments; we'll mark it as a trailing
-					// comment if it immediately follows previous symbol and is
-					// detached from current symbol
-					c1 := comments[0]
-					c2 := comments[len(comments)-1]
-					if c1.start.Line <= prevEnd+1 && c2.end.Line < nStart-1 {
-						groupEnd = len(comments)
-					}
-				}
-
-				for i := 0; i < groupEnd; i++ {
-					l.prevSym.pushTrailingComment(n.popLeadingComment())
-				}
-			}
-		}
-
-		l.prevSym = n
-	}
-	setString := func(val string) {
-		b := basic()
-		lval.str = &stringLiteralNode{val: val}
-		lval.str.setRange(&b, &b)
-		setPrev(lval.str)
-	}
-	setIdent := func(val string, kind identKind) {
-		lval.id = &identNode{basicNode: basic(), val: val, kind: kind}
-		setPrev(lval.id)
-	}
-	setInt := func(val uint64) {
-		lval.ui = &intLiteralNode{basicNode: basic(), val: val}
-		setPrev(lval.ui)
-	}
-	setFloat := func(val float64) {
-		b := basic()
-		lval.f = &floatLiteralNode{val: val}
-		lval.f.setRange(&b, &b)
-		setPrev(lval.f)
-	}
-	setRune := func() {
-		b := basic()
-		lval.b = &b
-		setPrev(lval.b)
-	}
-	setError := func(err error) {
-		lval.err = err
-		l.err = err
-	}
+	l.prevLineNo = l.lineNo
+	l.prevColNo = l.colNo
+	l.prevOffset = l.offset
+	l.comments = nil
 
 	for {
 		c, n, err := l.input.readRune()
@@ -260,58 +175,47 @@
 			// we're not actually returning a rune, but this will associate
 			// accumulated comments as a trailing comment on last symbol
 			// (if appropriate)
-			setRune()
+			l.setRune(lval)
 			return 0
 		} else if err != nil {
-			setError(err)
+			// we don't call setError because we don't want it wrapped
+			// with a source position because it's I/O, not syntax
+			lval.err = err
+			_ = l.errs.handleError(err)
 			return _ERROR
 		}
 
-		prevLineNo = l.lineNo
-		prevColNo = l.colNo
-		prevOffset = l.offset
+		l.prevLineNo = l.lineNo
+		l.prevColNo = l.colNo
+		l.prevOffset = l.offset
 
 		l.offset += n
-		if c == '\n' {
-			l.colNo = 0
-			l.lineNo++
-			continue
-		} else if c == '\r' {
-			continue
-		}
-		l.colNo++
-		if c == ' ' || c == '\t' {
+		l.adjustPos(c)
+		if strings.ContainsRune("\n\r\t ", c) {
 			continue
 		}
 
 		if c == '.' {
-			// tokens that start with a dot include type names and decimal literals
+			// decimal literals could start with a dot
 			cn, _, err := l.input.readRune()
 			if err != nil {
-				setRune()
+				l.setRune(lval)
 				return int(c)
 			}
-			if cn == '_' || (cn >= 'a' && cn <= 'z') || (cn >= 'A' && cn <= 'Z') {
-				l.colNo++
-				token := []rune{c, cn}
-				token = l.readIdentifier(token)
-				setIdent(string(token), identTypeName)
-				return _TYPENAME
-			}
 			if cn >= '0' && cn <= '9' {
-				l.colNo++
+				l.adjustPos(cn)
 				token := []rune{c, cn}
 				token = l.readNumber(token, false, true)
 				f, err := strconv.ParseFloat(string(token), 64)
 				if err != nil {
-					setError(err)
+					l.setError(lval, err)
 					return _ERROR
 				}
-				setFloat(f)
+				l.setFloat(lval, f)
 				return _FLOAT_LIT
 			}
 			l.input.unreadRune(cn)
-			setRune()
+			l.setRune(lval)
 			return int(c)
 		}
 
@@ -320,15 +224,11 @@
 			token := []rune{c}
 			token = l.readIdentifier(token)
 			str := string(token)
-			if strings.Contains(str, ".") {
-				setIdent(str, identQualified)
-				return _FQNAME
-			}
 			if t, ok := keywords[str]; ok {
-				setIdent(str, identSimpleName)
+				l.setIdent(lval, str)
 				return t
 			}
-			setIdent(str, identSimpleName)
+			l.setIdent(lval, str)
 			return _NAME
 		}
 
@@ -337,32 +237,32 @@
 			if c == '0' {
 				cn, _, err := l.input.readRune()
 				if err != nil {
-					setInt(0)
+					l.setInt(lval, 0)
 					return _INT_LIT
 				}
 				if cn == 'x' || cn == 'X' {
 					cnn, _, err := l.input.readRune()
 					if err != nil {
 						l.input.unreadRune(cn)
-						setInt(0)
+						l.setInt(lval, 0)
 						return _INT_LIT
 					}
 					if (cnn >= '0' && cnn <= '9') || (cnn >= 'a' && cnn <= 'f') || (cnn >= 'A' && cnn <= 'F') {
 						// hexadecimal!
-						l.colNo += 2
+						l.adjustPos(cn, cnn)
 						token := []rune{cnn}
 						token = l.readHexNumber(token)
 						ui, err := strconv.ParseUint(string(token), 16, 64)
 						if err != nil {
-							setError(err)
+							l.setError(lval, err)
 							return _ERROR
 						}
-						setInt(ui)
+						l.setInt(lval, ui)
 						return _INT_LIT
 					}
 					l.input.unreadRune(cnn)
 					l.input.unreadRune(cn)
-					setInt(0)
+					l.setInt(lval, 0)
 					return _INT_LIT
 				} else {
 					l.input.unreadRune(cn)
@@ -375,19 +275,19 @@
 				// floating point!
 				f, err := strconv.ParseFloat(numstr, 64)
 				if err != nil {
-					setError(err)
+					l.setError(lval, err)
 					return _ERROR
 				}
-				setFloat(f)
+				l.setFloat(lval, f)
 				return _FLOAT_LIT
 			}
 			// integer! (decimal or octal)
 			ui, err := strconv.ParseUint(numstr, 0, 64)
 			if err != nil {
-				setError(err)
+				l.setError(lval, err)
 				return _ERROR
 			}
-			setInt(ui)
+			l.setInt(lval, ui)
 			return _INT_LIT
 		}
 
@@ -395,10 +295,10 @@
 			// string literal
 			str, err := l.readStringLiteral(c)
 			if err != nil {
-				setError(err)
+				l.setError(lval, err)
 				return _ERROR
 			}
-			setString(str)
+			l.setString(lval, str)
 			return _STRING_LIT
 		}
 
@@ -406,39 +306,159 @@
 			// comment
 			cn, _, err := l.input.readRune()
 			if err != nil {
-				setRune()
+				l.setRune(lval)
 				return int(c)
 			}
 			if cn == '/' {
-				l.colNo++
+				l.adjustPos(cn)
 				hitNewline, txt := l.skipToEndOfLineComment()
-				commentPos := pos()
+				commentPos := l.posRange()
 				commentPos.end.Col++
 				if hitNewline {
-					l.colNo = 0
-					l.lineNo++
+					// we don't do this inside of skipToEndOfLineComment
+					// because we want to know the length of previous
+					// line for calculation above
+					l.adjustPos('\n')
 				}
-				comments = append(comments, &comment{posRange: commentPos, text: txt})
+				l.comments = append(l.comments, comment{posRange: commentPos, text: txt})
 				continue
 			}
 			if cn == '*' {
-				l.colNo++
+				l.adjustPos(cn)
 				if txt, ok := l.skipToEndOfBlockComment(); !ok {
-					setError(errors.New("block comment never terminates, unexpected EOF"))
+					l.setError(lval, errors.New("block comment never terminates, unexpected EOF"))
 					return _ERROR
 				} else {
-					comments = append(comments, &comment{posRange: pos(), text: txt})
+					l.comments = append(l.comments, comment{posRange: l.posRange(), text: txt})
 				}
 				continue
 			}
 			l.input.unreadRune(cn)
 		}
 
-		setRune()
+		l.setRune(lval)
 		return int(c)
 	}
 }
 
+func (l *protoLex) posRange() posRange {
+	return posRange{
+		start: SourcePos{
+			Filename: l.filename,
+			Offset:   l.prevOffset,
+			Line:     l.prevLineNo + 1,
+			Col:      l.prevColNo + 1,
+		},
+		end: l.cur(),
+	}
+}
+
+func (l *protoLex) newBasicNode() basicNode {
+	return basicNode{
+		posRange: l.posRange(),
+		leading:  l.comments,
+	}
+}
+
+func (l *protoLex) setPrev(n terminalNode) {
+	nStart := n.start().Line
+	if _, ok := n.(*basicNode); ok {
+		// if the node is a simple rune, don't attribute comments to it
+		// HACK: adjusting the start line makes leading comments appear
+		// detached so logic below will naturally associated trailing
+		// comment to previous symbol
+		nStart += 2
+	}
+	if l.prevSym != nil && len(n.leadingComments()) > 0 && l.prevSym.end().Line < nStart {
+		// we may need to re-attribute the first comment to
+		// instead be previous node's trailing comment
+		prevEnd := l.prevSym.end().Line
+		comments := n.leadingComments()
+		c := comments[0]
+		commentStart := c.start.Line
+		if commentStart == prevEnd {
+			// comment is on same line as previous symbol
+			n.popLeadingComment()
+			l.prevSym.pushTrailingComment(c)
+		} else if commentStart == prevEnd+1 {
+			// comment is right after previous symbol; see if it is detached
+			// and if so re-attribute
+			singleLineStyle := strings.HasPrefix(c.text, "//")
+			line := c.end.Line
+			groupEnd := -1
+			for i := 1; i < len(comments); i++ {
+				c := comments[i]
+				newGroup := false
+				if !singleLineStyle || c.start.Line > line+1 {
+					// we've found a gap between comments, which means the
+					// previous comments were detached
+					newGroup = true
+				} else {
+					line = c.end.Line
+					singleLineStyle = strings.HasPrefix(comments[i].text, "//")
+					if !singleLineStyle {
+						// we've found a switch from // comments to /*
+						// consider that a new group which means the
+						// previous comments were detached
+						newGroup = true
+					}
+				}
+				if newGroup {
+					groupEnd = i
+					break
+				}
+			}
+
+			if groupEnd == -1 {
+				// just one group of comments; we'll mark it as a trailing
+				// comment if it immediately follows previous symbol and is
+				// detached from current symbol
+				c1 := comments[0]
+				c2 := comments[len(comments)-1]
+				if c1.start.Line <= prevEnd+1 && c2.end.Line < nStart-1 {
+					groupEnd = len(comments)
+				}
+			}
+
+			for i := 0; i < groupEnd; i++ {
+				l.prevSym.pushTrailingComment(n.popLeadingComment())
+			}
+		}
+	}
+
+	l.prevSym = n
+}
+
+func (l *protoLex) setString(lval *protoSymType, val string) {
+	lval.s = &stringLiteralNode{basicNode: l.newBasicNode(), val: val}
+	l.setPrev(lval.s)
+}
+
+func (l *protoLex) setIdent(lval *protoSymType, val string) {
+	lval.id = &identNode{basicNode: l.newBasicNode(), val: val}
+	l.setPrev(lval.id)
+}
+
+func (l *protoLex) setInt(lval *protoSymType, val uint64) {
+	lval.i = &intLiteralNode{basicNode: l.newBasicNode(), val: val}
+	l.setPrev(lval.i)
+}
+
+func (l *protoLex) setFloat(lval *protoSymType, val float64) {
+	lval.f = &floatLiteralNode{basicNode: l.newBasicNode(), val: val}
+	l.setPrev(lval.f)
+}
+
+func (l *protoLex) setRune(lval *protoSymType) {
+	b := l.newBasicNode()
+	lval.b = &b
+	l.setPrev(lval.b)
+}
+
+func (l *protoLex) setError(lval *protoSymType, err error) {
+	lval.err = l.addSourceError(err)
+}
+
 func (l *protoLex) readNumber(sofar []rune, allowDot bool, allowExp bool) []rune {
 	token := sofar
 	for {
@@ -452,19 +472,6 @@
 				break
 			}
 			allowDot = false
-			cn, _, err := l.input.readRune()
-			if err != nil {
-				l.input.unreadRune(c)
-				break
-			}
-			if cn < '0' || cn > '9' {
-				l.input.unreadRune(cn)
-				l.input.unreadRune(c)
-				break
-			}
-			l.colNo++
-			token = append(token, c)
-			c = cn
 		} else if c == 'e' || c == 'E' {
 			if !allowExp {
 				l.input.unreadRune(c)
@@ -489,23 +496,22 @@
 					l.input.unreadRune(c)
 					break
 				}
-				l.colNo++
+				l.adjustPos(c)
 				token = append(token, c)
-				c = cn
-				cn = cnn
+				c, cn = cn, cnn
 			} else if cn < '0' || cn > '9' {
 				l.input.unreadRune(cn)
 				l.input.unreadRune(c)
 				break
 			}
-			l.colNo++
+			l.adjustPos(c)
 			token = append(token, c)
 			c = cn
 		} else if c < '0' || c > '9' {
 			l.input.unreadRune(c)
 			break
 		}
-		l.colNo++
+		l.adjustPos(c)
 		token = append(token, c)
 	}
 	return token
@@ -522,7 +528,7 @@
 			l.input.unreadRune(c)
 			break
 		}
-		l.colNo++
+		l.adjustPos(c)
 		token = append(token, c)
 	}
 	return token
@@ -535,25 +541,11 @@
 		if err != nil {
 			break
 		}
-		if c == '.' {
-			cn, _, err := l.input.readRune()
-			if err != nil {
-				l.input.unreadRune(c)
-				break
-			}
-			if cn != '_' && (cn < 'a' || cn > 'z') && (cn < 'A' || cn > 'Z') {
-				l.input.unreadRune(cn)
-				l.input.unreadRune(c)
-				break
-			}
-			l.colNo++
-			token = append(token, c)
-			c = cn
-		} else if c != '_' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') {
+		if c != '_' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') {
 			l.input.unreadRune(c)
 			break
 		}
-		l.colNo++
+		l.adjustPos(c)
 		token = append(token, c)
 	}
 	return token
@@ -570,11 +562,9 @@
 			return "", err
 		}
 		if c == '\n' {
-			l.colNo = 0
-			l.lineNo++
 			return "", errors.New("encountered end-of-line before end of string literal")
 		}
-		l.colNo++
+		l.adjustPos(c)
 		if c == quote {
 			break
 		}
@@ -587,14 +577,14 @@
 			if err != nil {
 				return "", err
 			}
-			l.colNo++
+			l.adjustPos(c)
 			if c == 'x' || c == 'X' {
 				// hex escape
 				c, _, err := l.input.readRune()
 				if err != nil {
 					return "", err
 				}
-				l.colNo++
+				l.adjustPos(c)
 				c2, _, err := l.input.readRune()
 				if err != nil {
 					return "", err
@@ -604,7 +594,7 @@
 					l.input.unreadRune(c2)
 					hex = string(c)
 				} else {
-					l.colNo++
+					l.adjustPos(c2)
 					hex = string([]rune{c, c2})
 				}
 				i, err := strconv.ParseInt(hex, 16, 32)
@@ -624,7 +614,7 @@
 					l.input.unreadRune(c2)
 					octal = string(c)
 				} else {
-					l.colNo++
+					l.adjustPos(c2)
 					c3, _, err := l.input.readRune()
 					if err != nil {
 						return "", err
@@ -633,7 +623,7 @@
 						l.input.unreadRune(c3)
 						octal = string([]rune{c, c2})
 					} else {
-						l.colNo++
+						l.adjustPos(c3)
 						octal = string([]rune{c, c2, c3})
 					}
 				}
@@ -654,7 +644,7 @@
 					if err != nil {
 						return "", err
 					}
-					l.colNo++
+					l.adjustPos(c)
 					u[i] = c
 				}
 				i, err := strconv.ParseInt(string(u), 16, 32)
@@ -671,7 +661,7 @@
 					if err != nil {
 						return "", err
 					}
-					l.colNo++
+					l.adjustPos(c)
 					u[i] = c
 				}
 				i, err := strconv.ParseInt(string(u), 16, 32)
@@ -723,9 +713,9 @@
 			return false, string(txt)
 		}
 		if c == '\n' {
-			return true, string(txt)
+			return true, string(append(txt, '\n'))
 		}
-		l.colNo++
+		l.adjustPos(c)
 		txt = append(txt, c)
 	}
 }
@@ -737,12 +727,7 @@
 		if err != nil {
 			return "", false
 		}
-		if c == '\n' {
-			l.colNo = 0
-			l.lineNo++
-		} else {
-			l.colNo++
-		}
+		l.adjustPos(c)
 		txt = append(txt, c)
 		if c == '*' {
 			c, _, err := l.input.readRune()
@@ -750,7 +735,7 @@
 				return "", false
 			}
 			if c == '/' {
-				l.colNo++
+				l.adjustPos(c)
 				txt = append(txt, c)
 				return string(txt), true
 			}
@@ -759,8 +744,15 @@
 	}
 }
 
-func (l *protoLex) Error(s string) {
-	if l.err == nil {
-		l.err = ErrorWithSourcePos{Underlying: errors.New(s), Pos: l.prevSym.start()}
+func (l *protoLex) addSourceError(err error) ErrorWithPos {
+	ewp, ok := err.(ErrorWithPos)
+	if !ok {
+		ewp = ErrorWithSourcePos{Pos: l.prev(), Underlying: err}
 	}
+	_ = l.errs.handleError(ewp)
+	return ewp
+}
+
+func (l *protoLex) Error(s string) {
+	_ = l.addSourceError(errors.New(s))
 }
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/linker.go b/vendor/github.com/jhump/protoreflect/desc/protoparse/linker.go
index c150936..a990f4f 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoparse/linker.go
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/linker.go
@@ -15,12 +15,14 @@
 
 type linker struct {
 	files          map[string]*parseResult
+	filenames      []string
+	errs           *errorHandler
 	descriptorPool map[*dpb.FileDescriptorProto]map[string]proto.Message
 	extensions     map[string]map[int32]string
 }
 
-func newLinker(files map[string]*parseResult) *linker {
-	return &linker{files: files}
+func newLinker(files *parseResults, errs *errorHandler) *linker {
+	return &linker{files: files.resultsByFilename, filenames: files.filenames, errs: errs}
 }
 
 func (l *linker) linkFiles() (map[string]*desc.FileDescriptor, error) {
@@ -41,6 +43,12 @@
 		return nil, err
 	}
 
+	if err := l.errs.getError(); err != nil {
+		// we won't be able to create real descriptors if we've encountered
+		// errors up to this point, so bail at this point
+		return nil, err
+	}
+
 	// Now we've validated the descriptors, so we can link them into rich
 	// descriptors. This is a little redundant since that step does similar
 	// checking of symbols. But, without breaking encapsulation (e.g. exporting
@@ -65,7 +73,8 @@
 
 func (l *linker) createDescriptorPool() error {
 	l.descriptorPool = map[*dpb.FileDescriptorProto]map[string]proto.Message{}
-	for _, r := range l.files {
+	for _, filename := range l.filenames {
+		r := l.files[filename]
 		fd := r.fd
 		pool := map[string]proto.Message{}
 		l.descriptorPool[fd] = pool
@@ -74,22 +83,22 @@
 			prefix += "."
 		}
 		for _, md := range fd.MessageType {
-			if err := addMessageToPool(r, pool, prefix, md); err != nil {
+			if err := addMessageToPool(r, pool, l.errs, prefix, md); err != nil {
 				return err
 			}
 		}
 		for _, fld := range fd.Extension {
-			if err := addFieldToPool(r, pool, prefix, fld); err != nil {
+			if err := addFieldToPool(r, pool, l.errs, prefix, fld); err != nil {
 				return err
 			}
 		}
 		for _, ed := range fd.EnumType {
-			if err := addEnumToPool(r, pool, prefix, ed); err != nil {
+			if err := addEnumToPool(r, pool, l.errs, prefix, ed); err != nil {
 				return err
 			}
 		}
 		for _, sd := range fd.Service {
-			if err := addServiceToPool(r, pool, prefix, sd); err != nil {
+			if err := addServiceToPool(r, pool, l.errs, prefix, sd); err != nil {
 				return err
 			}
 		}
@@ -101,8 +110,16 @@
 		msg  proto.Message
 	}
 	pool := map[string]entry{}
-	for f, p := range l.descriptorPool {
-		for k, v := range p {
+	for _, filename := range l.filenames {
+		f := l.files[filename].fd
+		p := l.descriptorPool[f]
+		keys := make([]string, 0, len(p))
+		for k := range p {
+			keys = append(keys, k)
+		}
+		sort.Strings(keys) // for deterministic error reporting
+		for _, k := range keys {
+			v := p[k]
 			if e, ok := pool[k]; ok {
 				desc1 := e.msg
 				file1 := e.file
@@ -113,7 +130,9 @@
 					desc1, desc2 = desc2, desc1
 				}
 				node := l.files[file2].nodes[desc2]
-				return ErrorWithSourcePos{Pos: node.start(), Underlying: fmt.Errorf("duplicate symbol %s: already defined as %s in %q", k, descriptorType(desc1), file1)}
+				if err := l.errs.handleError(ErrorWithSourcePos{Pos: node.start(), Underlying: fmt.Errorf("duplicate symbol %s: already defined as %s in %q", k, descriptorType(desc1), file1)}); err != nil {
+					return err
+				}
 			}
 			pool[k] = entry{file: f.GetName(), msg: v}
 		}
@@ -122,72 +141,74 @@
 	return nil
 }
 
-func addMessageToPool(r *parseResult, pool map[string]proto.Message, prefix string, md *dpb.DescriptorProto) error {
+func addMessageToPool(r *parseResult, pool map[string]proto.Message, errs *errorHandler, prefix string, md *dpb.DescriptorProto) error {
 	fqn := prefix + md.GetName()
-	if err := addToPool(r, pool, fqn, md); err != nil {
+	if err := addToPool(r, pool, errs, fqn, md); err != nil {
 		return err
 	}
 	prefix = fqn + "."
 	for _, fld := range md.Field {
-		if err := addFieldToPool(r, pool, prefix, fld); err != nil {
+		if err := addFieldToPool(r, pool, errs, prefix, fld); err != nil {
 			return err
 		}
 	}
 	for _, fld := range md.Extension {
-		if err := addFieldToPool(r, pool, prefix, fld); err != nil {
+		if err := addFieldToPool(r, pool, errs, prefix, fld); err != nil {
 			return err
 		}
 	}
 	for _, nmd := range md.NestedType {
-		if err := addMessageToPool(r, pool, prefix, nmd); err != nil {
+		if err := addMessageToPool(r, pool, errs, prefix, nmd); err != nil {
 			return err
 		}
 	}
 	for _, ed := range md.EnumType {
-		if err := addEnumToPool(r, pool, prefix, ed); err != nil {
+		if err := addEnumToPool(r, pool, errs, prefix, ed); err != nil {
 			return err
 		}
 	}
 	return nil
 }
 
-func addFieldToPool(r *parseResult, pool map[string]proto.Message, prefix string, fld *dpb.FieldDescriptorProto) error {
+func addFieldToPool(r *parseResult, pool map[string]proto.Message, errs *errorHandler, prefix string, fld *dpb.FieldDescriptorProto) error {
 	fqn := prefix + fld.GetName()
-	return addToPool(r, pool, fqn, fld)
+	return addToPool(r, pool, errs, fqn, fld)
 }
 
-func addEnumToPool(r *parseResult, pool map[string]proto.Message, prefix string, ed *dpb.EnumDescriptorProto) error {
+func addEnumToPool(r *parseResult, pool map[string]proto.Message, errs *errorHandler, prefix string, ed *dpb.EnumDescriptorProto) error {
 	fqn := prefix + ed.GetName()
-	if err := addToPool(r, pool, fqn, ed); err != nil {
+	if err := addToPool(r, pool, errs, fqn, ed); err != nil {
 		return err
 	}
 	for _, evd := range ed.Value {
 		vfqn := fqn + "." + evd.GetName()
-		if err := addToPool(r, pool, vfqn, evd); err != nil {
+		if err := addToPool(r, pool, errs, vfqn, evd); err != nil {
 			return err
 		}
 	}
 	return nil
 }
 
-func addServiceToPool(r *parseResult, pool map[string]proto.Message, prefix string, sd *dpb.ServiceDescriptorProto) error {
+func addServiceToPool(r *parseResult, pool map[string]proto.Message, errs *errorHandler, prefix string, sd *dpb.ServiceDescriptorProto) error {
 	fqn := prefix + sd.GetName()
-	if err := addToPool(r, pool, fqn, sd); err != nil {
+	if err := addToPool(r, pool, errs, fqn, sd); err != nil {
 		return err
 	}
 	for _, mtd := range sd.Method {
 		mfqn := fqn + "." + mtd.GetName()
-		if err := addToPool(r, pool, mfqn, mtd); err != nil {
+		if err := addToPool(r, pool, errs, mfqn, mtd); err != nil {
 			return err
 		}
 	}
 	return nil
 }
 
-func addToPool(r *parseResult, pool map[string]proto.Message, fqn string, dsc proto.Message) error {
+func addToPool(r *parseResult, pool map[string]proto.Message, errs *errorHandler, fqn string, dsc proto.Message) error {
 	if d, ok := pool[fqn]; ok {
 		node := r.nodes[dsc]
-		return ErrorWithSourcePos{Pos: node.start(), Underlying: fmt.Errorf("duplicate symbol %s: already defined as %s", fqn, descriptorType(d))}
+		if err := errs.handleError(ErrorWithSourcePos{Pos: node.start(), Underlying: fmt.Errorf("duplicate symbol %s: already defined as %s", fqn, descriptorType(d))}); err != nil {
+			return err
+		}
 	}
 	pool[fqn] = dsc
 	return nil
@@ -223,7 +244,8 @@
 
 func (l *linker) resolveReferences() error {
 	l.extensions = map[string]map[int32]string{}
-	for _, r := range l.files {
+	for _, filename := range l.filenames {
+		r := l.files[filename]
 		fd := r.fd
 		prefix := fd.GetPackage()
 		scopes := []scope{fileScope(fd, l)}
@@ -326,14 +348,15 @@
 	node := r.getFieldNode(fld)
 	elemType := "field"
 	if fld.GetExtendee() != "" {
+		elemType = "extension"
 		fqn, dsc, _ := l.resolve(fd, fld.GetExtendee(), isMessage, scopes)
 		if dsc == nil {
-			return ErrorWithSourcePos{Pos: node.fieldExtendee().start(), Underlying: fmt.Errorf("unknown extendee type %s", fld.GetExtendee())}
+			return l.errs.handleError(ErrorWithSourcePos{Pos: node.fieldExtendee().start(), Underlying: fmt.Errorf("unknown extendee type %s", fld.GetExtendee())})
 		}
 		extd, ok := dsc.(*dpb.DescriptorProto)
 		if !ok {
 			otherType := descriptorType(dsc)
-			return ErrorWithSourcePos{Pos: node.fieldExtendee().start(), Underlying: fmt.Errorf("extendee is invalid: %s is a %s, not a message", fqn, otherType)}
+			return l.errs.handleError(ErrorWithSourcePos{Pos: node.fieldExtendee().start(), Underlying: fmt.Errorf("extendee is invalid: %s is a %s, not a message", fqn, otherType)})
 		}
 		fld.Extendee = proto.String("." + fqn)
 		// make sure the tag number is in range
@@ -346,19 +369,24 @@
 			}
 		}
 		if !found {
-			return ErrorWithSourcePos{Pos: node.fieldTag().start(), Underlying: fmt.Errorf("%s: tag %d is not in valid range for extended type %s", scope, tag, fqn)}
+			if err := l.errs.handleError(ErrorWithSourcePos{Pos: node.fieldTag().start(), Underlying: fmt.Errorf("%s: tag %d is not in valid range for extended type %s", scope, tag, fqn)}); err != nil {
+				return err
+			}
+		} else {
+			// make sure tag is not a duplicate
+			usedExtTags := l.extensions[fqn]
+			if usedExtTags == nil {
+				usedExtTags = map[int32]string{}
+				l.extensions[fqn] = usedExtTags
+			}
+			if other := usedExtTags[fld.GetNumber()]; other != "" {
+				if err := l.errs.handleError(ErrorWithSourcePos{Pos: node.fieldTag().start(), Underlying: fmt.Errorf("%s: duplicate extension: %s and %s are both using tag %d", scope, other, thisName, fld.GetNumber())}); err != nil {
+					return err
+				}
+			} else {
+				usedExtTags[fld.GetNumber()] = thisName
+			}
 		}
-		// make sure tag is not a duplicate
-		usedExtTags := l.extensions[fqn]
-		if usedExtTags == nil {
-			usedExtTags = map[int32]string{}
-			l.extensions[fqn] = usedExtTags
-		}
-		if other := usedExtTags[fld.GetNumber()]; other != "" {
-			return ErrorWithSourcePos{Pos: node.fieldTag().start(), Underlying: fmt.Errorf("%s: duplicate extension: %s and %s are both using tag %d", scope, other, thisName, fld.GetNumber())}
-		}
-		usedExtTags[fld.GetNumber()] = thisName
-		elemType = "extension"
 	}
 
 	if fld.Options != nil {
@@ -374,18 +402,22 @@
 
 	fqn, dsc, proto3 := l.resolve(fd, fld.GetTypeName(), isType, scopes)
 	if dsc == nil {
-		return ErrorWithSourcePos{Pos: node.fieldType().start(), Underlying: fmt.Errorf("%s: unknown type %s", scope, fld.GetTypeName())}
+		return l.errs.handleError(ErrorWithSourcePos{Pos: node.fieldType().start(), Underlying: fmt.Errorf("%s: unknown type %s", scope, fld.GetTypeName())})
 	}
 	switch dsc := dsc.(type) {
 	case *dpb.DescriptorProto:
 		fld.TypeName = proto.String("." + fqn)
+		// if type was tentatively unset, we now know it's actually a message
+		if fld.Type == nil {
+			fld.Type = dpb.FieldDescriptorProto_TYPE_MESSAGE.Enum()
+		}
 	case *dpb.EnumDescriptorProto:
 		if fld.GetExtendee() == "" && isProto3(fd) && !proto3 {
 			// fields in a proto3 message cannot refer to proto2 enums
 			return ErrorWithSourcePos{Pos: node.fieldType().start(), Underlying: fmt.Errorf("%s: cannot use proto2 enum %s in a proto3 message", scope, fld.GetTypeName())}
 		}
 		fld.TypeName = proto.String("." + fqn)
-		// the type was tentatively set to message, but now we know it's actually an enum
+		// the type was tentatively unset, but now we know it's actually an enum
 		fld.Type = dpb.FieldDescriptorProto_TYPE_ENUM.Enum()
 	default:
 		otherType := descriptorType(dsc)
@@ -412,23 +444,31 @@
 		node := r.getMethodNode(mtd)
 		fqn, dsc, _ := l.resolve(fd, mtd.GetInputType(), isMessage, scopes)
 		if dsc == nil {
-			return ErrorWithSourcePos{Pos: node.getInputType().start(), Underlying: fmt.Errorf("%s: unknown request type %s", scope, mtd.GetInputType())}
-		}
-		if _, ok := dsc.(*dpb.DescriptorProto); !ok {
+			if err := l.errs.handleError(ErrorWithSourcePos{Pos: node.getInputType().start(), Underlying: fmt.Errorf("%s: unknown request type %s", scope, mtd.GetInputType())}); err != nil {
+				return err
+			}
+		} else if _, ok := dsc.(*dpb.DescriptorProto); !ok {
 			otherType := descriptorType(dsc)
-			return ErrorWithSourcePos{Pos: node.getInputType().start(), Underlying: fmt.Errorf("%s: invalid request type: %s is a %s, not a message", scope, fqn, otherType)}
+			if err := l.errs.handleError(ErrorWithSourcePos{Pos: node.getInputType().start(), Underlying: fmt.Errorf("%s: invalid request type: %s is a %s, not a message", scope, fqn, otherType)}); err != nil {
+				return err
+			}
+		} else {
+			mtd.InputType = proto.String("." + fqn)
 		}
-		mtd.InputType = proto.String("." + fqn)
 
 		fqn, dsc, _ = l.resolve(fd, mtd.GetOutputType(), isMessage, scopes)
 		if dsc == nil {
-			return ErrorWithSourcePos{Pos: node.getOutputType().start(), Underlying: fmt.Errorf("%s: unknown response type %s", scope, mtd.GetOutputType())}
-		}
-		if _, ok := dsc.(*dpb.DescriptorProto); !ok {
+			if err := l.errs.handleError(ErrorWithSourcePos{Pos: node.getOutputType().start(), Underlying: fmt.Errorf("%s: unknown response type %s", scope, mtd.GetOutputType())}); err != nil {
+				return err
+			}
+		} else if _, ok := dsc.(*dpb.DescriptorProto); !ok {
 			otherType := descriptorType(dsc)
-			return ErrorWithSourcePos{Pos: node.getOutputType().start(), Underlying: fmt.Errorf("%s: invalid response type: %s is a %s, not a message", scope, fqn, otherType)}
+			if err := l.errs.handleError(ErrorWithSourcePos{Pos: node.getOutputType().start(), Underlying: fmt.Errorf("%s: invalid response type: %s is a %s, not a message", scope, fqn, otherType)}); err != nil {
+				return err
+			}
+		} else {
+			mtd.OutputType = proto.String("." + fqn)
 		}
-		mtd.OutputType = proto.String("." + fqn)
 	}
 	return nil
 }
@@ -438,19 +478,29 @@
 	if elemType != "file" {
 		scope = fmt.Sprintf("%s %s: ", elemType, elemName)
 	}
+opts:
 	for _, opt := range opts {
 		for _, nm := range opt.Name {
 			if nm.GetIsExtension() {
 				node := r.getOptionNamePartNode(nm)
 				fqn, dsc, _ := l.resolve(fd, nm.GetNamePart(), isField, scopes)
 				if dsc == nil {
-					return ErrorWithSourcePos{Pos: node.start(), Underlying: fmt.Errorf("%sunknown extension %s", scope, nm.GetNamePart())}
+					if err := l.errs.handleError(ErrorWithSourcePos{Pos: node.start(), Underlying: fmt.Errorf("%sunknown extension %s", scope, nm.GetNamePart())}); err != nil {
+						return err
+					}
+					continue opts
 				}
 				if ext, ok := dsc.(*dpb.FieldDescriptorProto); !ok {
 					otherType := descriptorType(dsc)
-					return ErrorWithSourcePos{Pos: node.start(), Underlying: fmt.Errorf("%sinvalid extension: %s is a %s, not an extension", scope, nm.GetNamePart(), otherType)}
+					if err := l.errs.handleError(ErrorWithSourcePos{Pos: node.start(), Underlying: fmt.Errorf("%sinvalid extension: %s is a %s, not an extension", scope, nm.GetNamePart(), otherType)}); err != nil {
+						return err
+					}
+					continue opts
 				} else if ext.GetExtendee() == "" {
-					return ErrorWithSourcePos{Pos: node.start(), Underlying: fmt.Errorf("%sinvalid extension: %s is a field but not an extension", scope, nm.GetNamePart())}
+					if err := l.errs.handleError(ErrorWithSourcePos{Pos: node.start(), Underlying: fmt.Errorf("%sinvalid extension: %s is a field but not an extension", scope, nm.GetNamePart())}); err != nil {
+						return err
+					}
+					continue opts
 				}
 				nm.NamePart = proto.String("." + fqn)
 			}
@@ -599,14 +649,14 @@
 	sort.Strings(names)
 	linked := map[string]*desc.FileDescriptor{}
 	for _, name := range names {
-		if _, err := l.linkFile(name, nil, linked); err != nil {
+		if _, err := l.linkFile(name, nil, nil, linked); err != nil {
 			return nil, err
 		}
 	}
 	return linked, nil
 }
 
-func (l *linker) linkFile(name string, seen []string, linked map[string]*desc.FileDescriptor) (*desc.FileDescriptor, error) {
+func (l *linker) linkFile(name string, rootImportLoc *SourcePos, seen []string, linked map[string]*desc.FileDescriptor) (*desc.FileDescriptor, error) {
 	// check for import cycle
 	for _, s := range seen {
 		if name == s {
@@ -621,7 +671,10 @@
 				fmt.Fprintf(&msg, "%q", s)
 			}
 			fmt.Fprintf(&msg, " -> %q", name)
-			return nil, fmt.Errorf("cycle found in imports: %s", msg.String())
+			return nil, ErrorWithSourcePos{
+				Underlying: fmt.Errorf("cycle found in imports: %s", msg.String()),
+				Pos:        rootImportLoc,
+			}
 		}
 	}
 	seen = append(seen, name)
@@ -636,12 +689,38 @@
 		return nil, fmt.Errorf("no descriptor found for %q, imported by %q", name, importer)
 	}
 	var deps []*desc.FileDescriptor
-	for _, dep := range r.fd.Dependency {
-		ldep, err := l.linkFile(dep, seen, linked)
-		if err != nil {
-			return nil, err
+	if rootImportLoc == nil {
+		// try to find a source location for this "root" import
+		decl := r.getFileNode(r.fd)
+		fnode, ok := decl.(*fileNode)
+		if ok {
+			for _, dep := range fnode.imports {
+				ldep, err := l.linkFile(dep.name.val, dep.name.start(), seen, linked)
+				if err != nil {
+					return nil, err
+				}
+				deps = append(deps, ldep)
+			}
+		} else {
+			// no AST? just use the descriptor
+			for _, dep := range r.fd.Dependency {
+				ldep, err := l.linkFile(dep, decl.start(), seen, linked)
+				if err != nil {
+					return nil, err
+				}
+				deps = append(deps, ldep)
+			}
 		}
-		deps = append(deps, ldep)
+	} else {
+		// we can just use the descriptor since we don't need source location
+		// (we'll just attribute any import cycles found to the "root" import)
+		for _, dep := range r.fd.Dependency {
+			ldep, err := l.linkFile(dep, rootImportLoc, seen, linked)
+			if err != nil {
+				return nil, err
+			}
+			deps = append(deps, ldep)
+		}
 	}
 	lfd, err := desc.CreateFileDescriptor(r.fd, deps...)
 	if err != nil {
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/options.go b/vendor/github.com/jhump/protoreflect/desc/protoparse/options.go
index be287f6..04530dc 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoparse/options.go
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/options.go
@@ -1004,7 +1004,7 @@
 
 	} else {
 		// not lenient: try to convert into the passed in message
-		// and fail is not successful
+		// and fail if not successful
 		if err := dm.ConvertTo(opts); err != nil {
 			node := res.nodes[element.AsProto()]
 			return nil, ErrorWithSourcePos{Pos: node.start(), Underlying: err}
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/parser.go b/vendor/github.com/jhump/protoreflect/desc/protoparse/parser.go
index ce9a3e4..6eb1acc 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoparse/parser.go
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/parser.go
@@ -21,8 +21,6 @@
 
 //go:generate goyacc -o proto.y.go -p proto proto.y
 
-var errNoImportPathsForAbsoluteFilePath = errors.New("must specify at least one import path if any absolute file paths are given")
-
 func init() {
 	protoErrorVerbose = true
 
@@ -31,8 +29,6 @@
 	setTokenName(_INT_LIT, "int literal")
 	setTokenName(_FLOAT_LIT, "float literal")
 	setTokenName(_NAME, "identifier")
-	setTokenName(_FQNAME, "fully-qualified name")
-	setTokenName(_TYPENAME, "type name")
 	setTokenName(_ERROR, "error")
 	// for keywords, just show the keyword itself wrapped in quotes
 	for str, i := range keywords {
@@ -88,49 +84,6 @@
 	}
 }
 
-// ResolveFilenames tries to resolve fileNames into paths that are relative to
-// directories in the given importPaths. The returned slice has the results in
-// the same order as they are supplied in fileNames.
-//
-// The resulting names should be suitable for passing to Parser.ParseFiles.
-//
-// If importPaths is empty and any path is absolute, this returns error.
-// If importPaths is empty and all paths are relative, this returns the original fileNames.
-func ResolveFilenames(importPaths []string, fileNames ...string) ([]string, error) {
-	if len(importPaths) == 0 {
-		if containsAbsFilePath(fileNames) {
-			// We have to do this as otherwise parseProtoFiles can result in duplicate symbols.
-			// For example, assume we import "foo/bar/bar.proto" in a file "/home/alice/dev/foo/bar/baz.proto"
-			// as we call ParseFiles("/home/alice/dev/foo/bar/bar.proto","/home/alice/dev/foo/bar/baz.proto")
-			// with "/home/alice/dev" as our current directory. Due to the recursive nature of parseProtoFiles,
-			// it will discover the import "foo/bar/bar.proto" in the input file, and call parse on this,
-			// adding "foo/bar/bar.proto" to the parsed results, as well as "/home/alice/dev/foo/bar/bar.proto"
-			// from the input file list. This will result in a
-			// 'duplicate symbol SYMBOL: already defined as field in "/home/alice/dev/foo/bar/bar.proto'
-			// error being returned from ParseFiles.
-			return nil, errNoImportPathsForAbsoluteFilePath
-		}
-		return fileNames, nil
-	}
-	absImportPaths, err := absoluteFilePaths(importPaths)
-	if err != nil {
-		return nil, err
-	}
-	absFileNames, err := absoluteFilePaths(fileNames)
-	if err != nil {
-		return nil, err
-	}
-	resolvedFileNames := make([]string, 0, len(fileNames))
-	for _, absFileName := range absFileNames {
-		resolvedFileName, err := resolveAbsFilename(absImportPaths, absFileName)
-		if err != nil {
-			return nil, err
-		}
-		resolvedFileNames = append(resolvedFileNames, resolvedFileName)
-	}
-	return resolvedFileNames, nil
-}
-
 // Parser parses proto source into descriptors.
 type Parser struct {
 	// The paths used to search for dependencies that are referenced in import
@@ -179,6 +132,14 @@
 	// fields, excluding enums. (Interpreting default values for enum fields
 	// requires resolving enum names, which requires linking.)
 	InterpretOptionsInUnlinkedFiles bool
+
+	// A custom reporter of syntax and link errors. If not specified, the
+	// default reporter just returns the reported error, which causes parsing
+	// to abort after encountering a single error.
+	//
+	// The reporter is not invoked for system or I/O errors, only for syntax and
+	// link errors.
+	ErrorReporter ErrorReporter
 }
 
 // ParseFiles parses the named files into descriptors. The returned slice has
@@ -191,6 +152,12 @@
 // files -- e.g. google/protobuf/*.proto -- without needing to supply sources
 // for these files. Like protoc, this parser has a built-in version of these
 // files it can use if they aren't explicitly supplied.
+//
+// If the Parser has no ErrorReporter set and a syntax or link error occurs,
+// parsing will abort with the first such error encountered. If there is an
+// ErrorReporter configured and it returns non-nil, parsing will abort with the
+// error it returns. If syntax or link errors are encountered but the configured
+// ErrorReporter always returns nil, the parse fails with ErrInvalidSource.
 func (p Parser) ParseFiles(filenames ...string) ([]*desc.FileDescriptor, error) {
 	accessor := p.Accessor
 	if accessor == nil {
@@ -218,14 +185,17 @@
 	}
 
 	protos := map[string]*parseResult{}
-	err := parseProtoFiles(accessor, filenames, true, true, protos)
-	if err != nil {
+	results := &parseResults{resultsByFilename: protos}
+	errs := newErrorHandler(p.ErrorReporter)
+	parseProtoFiles(accessor, filenames, errs, true, true, results)
+	if err := errs.getError(); err != nil {
 		return nil, err
 	}
 	if p.InferImportPaths {
+		// TODO: if this re-writes one of the names in filenames, lookups below will break
 		protos = fixupFilenames(protos)
 	}
-	linkedProtos, err := newLinker(protos).linkFiles()
+	linkedProtos, err := newLinker(results, errs).linkFiles()
 	if err != nil {
 		return nil, err
 	}
@@ -269,6 +239,12 @@
 // This method will still validate the syntax of parsed files. If the parser's
 // ValidateUnlinkedFiles field is true, additional checks, beyond syntax will
 // also be performed.
+//
+// If the Parser has no ErrorReporter set and a syntax or link error occurs,
+// parsing will abort with the first such error encountered. If there is an
+// ErrorReporter configured and it returns non-nil, parsing will abort with the
+// error it returns. If syntax or link errors are encountered but the configured
+// ErrorReporter always returns nil, the parse fails with ErrInvalidSource.
 func (p Parser) ParseFilesButDoNotLink(filenames ...string) ([]*dpb.FileDescriptorProto, error) {
 	accessor := p.Accessor
 	if accessor == nil {
@@ -278,11 +254,13 @@
 	}
 
 	protos := map[string]*parseResult{}
-	err := parseProtoFiles(accessor, filenames, false, p.ValidateUnlinkedFiles, protos)
-	if err != nil {
+	errs := newErrorHandler(p.ErrorReporter)
+	parseProtoFiles(accessor, filenames, errs, false, p.ValidateUnlinkedFiles, &parseResults{resultsByFilename: protos})
+	if err := errs.getError(); err != nil {
 		return nil, err
 	}
 	if p.InferImportPaths {
+		// TODO: if this re-writes one of the names in filenames, lookups below will break
 		protos = fixupFilenames(protos)
 	}
 	fds := make([]*dpb.FileDescriptorProto, len(filenames))
@@ -291,7 +269,7 @@
 		fd := pr.fd
 		if p.InterpretOptionsInUnlinkedFiles {
 			pr.lenient = true
-			interpretFileOptions(pr, poorFileDescriptorish{FileDescriptorProto: fd})
+			_ = interpretFileOptions(pr, poorFileDescriptorish{FileDescriptorProto: fd})
 		}
 		if p.IncludeSourceCodeInfo {
 			fd.SourceCodeInfo = pr.generateSourceCodeInfo()
@@ -301,57 +279,6 @@
 	return fds, nil
 }
 
-func containsAbsFilePath(filePaths []string) bool {
-	for _, filePath := range filePaths {
-		if filepath.IsAbs(filePath) {
-			return true
-		}
-	}
-	return false
-}
-
-func absoluteFilePaths(filePaths []string) ([]string, error) {
-	absFilePaths := make([]string, 0, len(filePaths))
-	for _, filePath := range filePaths {
-		absFilePath, err := filepath.Abs(filePath)
-		if err != nil {
-			return nil, err
-		}
-		absFilePaths = append(absFilePaths, absFilePath)
-	}
-	return absFilePaths, nil
-}
-
-func resolveAbsFilename(absImportPaths []string, absFileName string) (string, error) {
-	for _, absImportPath := range absImportPaths {
-		if isDescendant(absImportPath, absFileName) {
-			resolvedPath, err := filepath.Rel(absImportPath, absFileName)
-			if err != nil {
-				return "", err
-			}
-			return resolvedPath, nil
-		}
-	}
-	return "", fmt.Errorf("%s does not reside in any import path", absFileName)
-}
-
-// isDescendant returns true if file is a descendant of dir.
-func isDescendant(dir, file string) bool {
-	dir = filepath.Clean(dir)
-	cur := file
-	for {
-		d := filepath.Dir(cur)
-		if d == dir {
-			return true
-		}
-		if d == "." || d == cur {
-			// we've run out of path elements
-			return false
-		}
-		cur = d
-	}
-}
-
 func fixupFilenames(protos map[string]*parseResult) map[string]*parseResult {
 	// In the event that the given filenames (keys in the supplied map) do not
 	// match the actual paths used in 'import' statements in the files, we try
@@ -460,37 +387,103 @@
 	return revisedProtos
 }
 
-func parseProtoFiles(acc FileAccessor, filenames []string, recursive, validate bool, parsed map[string]*parseResult) error {
+func parseProtoFiles(acc FileAccessor, filenames []string, errs *errorHandler, recursive, validate bool, parsed *parseResults) {
 	for _, name := range filenames {
-		if _, ok := parsed[name]; ok {
-			continue
+		parseProtoFile(acc, name, nil, errs, recursive, validate, parsed)
+		if errs.err != nil {
+			return
 		}
-		in, err := acc(name)
-		if err != nil {
-			if d, ok := standardImports[name]; ok {
-				parsed[name] = &parseResult{fd: d}
-				continue
-			}
-			return err
-		}
+	}
+}
+
+func parseProtoFile(acc FileAccessor, filename string, importLoc *SourcePos, errs *errorHandler, recursive, validate bool, parsed *parseResults) {
+	if parsed.has(filename) {
+		return
+	}
+	in, err := acc(filename)
+	var result *parseResult
+	if err == nil {
+		// try to parse the bytes accessed
 		func() {
-			defer in.Close()
-			parsed[name], err = parseProto(name, in, validate)
+			defer func() {
+				// if we've already parsed contents, an error
+				// closing need not fail this operation
+				_ = in.Close()
+			}()
+			result = parseProto(filename, in, errs, validate)
 		}()
-		if err != nil {
-			return err
+	} else if d, ok := standardImports[filename]; ok {
+		// it's a well-known import
+		// (we clone it to make sure we're not sharing state with other
+		//  parsers, which could result in unsafe races if multiple
+		//  parsers are trying to access it concurrently)
+		result = &parseResult{fd: proto.Clone(d).(*dpb.FileDescriptorProto)}
+	} else {
+		if !strings.Contains(err.Error(), filename) {
+			// an error message that doesn't indicate the file is awful!
+			err = fmt.Errorf("%s: %v", filename, err)
 		}
-		if recursive {
-			err = parseProtoFiles(acc, parsed[name].fd.Dependency, true, validate, parsed)
-			if err != nil {
-				return fmt.Errorf("failed to load imports for %q: %s", name, err)
+		if _, ok := err.(ErrorWithPos); !ok && importLoc != nil {
+			// error has no source position? report it as the import line
+			err = ErrorWithSourcePos{
+				Pos:        importLoc,
+				Underlying: err,
+			}
+		}
+		_ = errs.handleError(err)
+		return
+	}
+
+	parsed.add(filename, result)
+
+	if errs.getError() != nil {
+		return // abort
+	}
+
+	if recursive {
+		fd := result.fd
+		decl := result.getFileNode(fd)
+		fnode, ok := decl.(*fileNode)
+		if !ok {
+			// no AST for this file? use imports in descriptor
+			for _, dep := range fd.Dependency {
+				parseProtoFile(acc, dep, decl.start(), errs, true, validate, parsed)
+				if errs.getError() != nil {
+					return // abort
+				}
+			}
+			return
+		}
+		// we have an AST; use it so we can report import location in errors
+		for _, dep := range fnode.imports {
+			parseProtoFile(acc, dep.name.val, dep.name.start(), errs, true, validate, parsed)
+			if errs.getError() != nil {
+				return // abort
 			}
 		}
 	}
-	return nil
+}
+
+type parseResults struct {
+	resultsByFilename map[string]*parseResult
+	filenames         []string
+}
+
+func (r *parseResults) has(filename string) bool {
+	_, ok := r.resultsByFilename[filename]
+	return ok
+}
+
+func (r *parseResults) add(filename string, result *parseResult) {
+	r.resultsByFilename[filename] = result
+	r.filenames = append(r.filenames, filename)
 }
 
 type parseResult struct {
+	// handles any errors encountered during parsing, construction of file descriptor,
+	// or validation
+	errs *errorHandler
+
 	// the parsed file descriptor
 	fd *dpb.FileDescriptorProto
 
@@ -529,13 +522,6 @@
 	return r.nodes[o]
 }
 
-func (r *parseResult) getMessageNode(m *dpb.DescriptorProto) msgDecl {
-	if r.nodes == nil {
-		return noSourceNode{pos: unknownPos(r.fd.GetName())}
-	}
-	return r.nodes[m].(msgDecl)
-}
-
 func (r *parseResult) getFieldNode(f *dpb.FieldDescriptorProto) fieldDecl {
 	if r.nodes == nil {
 		return noSourceNode{pos: unknownPos(r.fd.GetName())}
@@ -543,13 +529,6 @@
 	return r.nodes[f].(fieldDecl)
 }
 
-func (r *parseResult) getOneOfNode(o *dpb.OneofDescriptorProto) node {
-	if r.nodes == nil {
-		return noSourceNode{pos: unknownPos(r.fd.GetName())}
-	}
-	return r.nodes[o]
-}
-
 func (r *parseResult) getExtensionRangeNode(e *dpb.DescriptorProto_ExtensionRange) rangeDecl {
 	if r.nodes == nil {
 		return noSourceNode{pos: unknownPos(r.fd.GetName())}
@@ -564,13 +543,6 @@
 	return r.nodes[rr].(rangeDecl)
 }
 
-func (r *parseResult) getEnumNode(e *dpb.EnumDescriptorProto) node {
-	if r.nodes == nil {
-		return noSourceNode{pos: unknownPos(r.fd.GetName())}
-	}
-	return r.nodes[e]
-}
-
 func (r *parseResult) getEnumValueNode(e *dpb.EnumValueDescriptorProto) enumValueDecl {
 	if r.nodes == nil {
 		return noSourceNode{pos: unknownPos(r.fd.GetName())}
@@ -585,13 +557,6 @@
 	return r.nodes[rr].(rangeDecl)
 }
 
-func (r *parseResult) getServiceNode(s *dpb.ServiceDescriptorProto) node {
-	if r.nodes == nil {
-		return noSourceNode{pos: unknownPos(r.fd.GetName())}
-	}
-	return r.nodes[s]
-}
-
 func (r *parseResult) getMethodNode(m *dpb.MethodDescriptorProto) methodDecl {
 	if r.nodes == nil {
 		return noSourceNode{pos: unknownPos(r.fd.GetName())}
@@ -651,46 +616,38 @@
 	r.nodes[m] = n
 }
 
-func parseProto(filename string, r io.Reader, validate bool) (*parseResult, error) {
-	lx := newLexer(r)
-	lx.filename = filename
+func parseProto(filename string, r io.Reader, errs *errorHandler, validate bool) *parseResult {
+	lx := newLexer(r, filename, errs)
 	protoParse(lx)
-	if lx.err != nil {
-		if _, ok := lx.err.(ErrorWithSourcePos); ok {
-			return nil, lx.err
-		} else {
-			return nil, ErrorWithSourcePos{Pos: lx.prev(), Underlying: lx.err}
-		}
-	}
-	// parser will not return an error if input is empty, so we
-	// need to also check if the result is non-nil
-	if lx.res == nil {
-		return nil, ErrorWithSourcePos{Pos: lx.prev(), Underlying: errors.New("input is empty")}
+
+	res := createParseResult(filename, lx.res, errs)
+	if validate {
+		basicValidate(res)
 	}
 
-	res, err := createParseResult(filename, lx.res)
-	if err != nil {
-		return nil, err
-	}
-	if validate {
-		if err := basicValidate(res); err != nil {
-			return nil, err
-		}
-	}
-	return res, nil
+	return res
 }
 
-func createParseResult(filename string, file *fileNode) (*parseResult, error) {
+func createParseResult(filename string, file *fileNode, errs *errorHandler) *parseResult {
 	res := &parseResult{
+		errs:               errs,
 		nodes:              map[proto.Message]node{},
 		interpretedOptions: map[*optionNode][]int32{},
 	}
-	err := res.createFileDescriptor(filename, file)
-	return res, err
+	if file == nil {
+		// nil AST means there was an error that prevented any parsing
+		// or the file was empty; synthesize empty non-nil AST
+		file = &fileNode{}
+		n := noSourceNode{pos: unknownPos(filename)}
+		file.setRange(&n, &n)
+	}
+	res.createFileDescriptor(filename, file)
+	return res
 }
 
-func (r *parseResult) createFileDescriptor(filename string, file *fileNode) error {
+func (r *parseResult) createFileDescriptor(filename string, file *fileNode) {
 	fd := &dpb.FileDescriptorProto{Name: proto.String(filename)}
+	r.fd = fd
 	r.putFileNode(fd, file)
 
 	isProto3 := false
@@ -727,17 +684,19 @@
 			fd.Service = append(fd.Service, r.asServiceDescriptor(decl.service))
 		} else if decl.pkg != nil {
 			if fd.Package != nil {
-				return ErrorWithSourcePos{Pos: decl.pkg.start(), Underlying: errors.New("files should have only one package declaration")}
+				if r.errs.handleError(ErrorWithSourcePos{Pos: decl.pkg.start(), Underlying: errors.New("files should have only one package declaration")}) != nil {
+					return
+				}
 			}
-			file.pkg = decl.pkg
 			fd.Package = proto.String(decl.pkg.name.val)
 		}
 	}
-	r.fd = fd
-	return nil
 }
 
 func (r *parseResult) asUninterpretedOptions(nodes []*optionNode) []*dpb.UninterpretedOption {
+	if len(nodes) == 0 {
+		return nil
+	}
 	opts := make([]*dpb.UninterpretedOption, len(nodes))
 	for i, n := range nodes {
 		opts[i] = r.asUninterpretedOption(n)
@@ -810,8 +769,8 @@
 	}
 }
 
-func asLabel(lbl *labelNode) *dpb.FieldDescriptorProto_Label {
-	if lbl == nil {
+func asLabel(lbl *fieldLabel) *dpb.FieldDescriptorProto_Label {
+	if lbl.identNode == nil {
 		return nil
 	}
 	switch {
@@ -825,14 +784,32 @@
 }
 
 func (r *parseResult) asFieldDescriptor(node *fieldNode) *dpb.FieldDescriptorProto {
-	fd := newFieldDescriptor(node.name.val, node.fldType.val, int32(node.tag.val), asLabel(node.label))
+	fd := newFieldDescriptor(node.name.val, node.fldType.val, int32(node.tag.val), asLabel(&node.label))
 	r.putFieldNode(fd, node)
-	if len(node.options) > 0 {
-		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(node.options)}
+	if opts := node.options.Elements(); len(opts) > 0 {
+		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
 	}
 	return fd
 }
 
+var fieldTypes = map[string]dpb.FieldDescriptorProto_Type{
+	"double":   dpb.FieldDescriptorProto_TYPE_DOUBLE,
+	"float":    dpb.FieldDescriptorProto_TYPE_FLOAT,
+	"int32":    dpb.FieldDescriptorProto_TYPE_INT32,
+	"int64":    dpb.FieldDescriptorProto_TYPE_INT64,
+	"uint32":   dpb.FieldDescriptorProto_TYPE_UINT32,
+	"uint64":   dpb.FieldDescriptorProto_TYPE_UINT64,
+	"sint32":   dpb.FieldDescriptorProto_TYPE_SINT32,
+	"sint64":   dpb.FieldDescriptorProto_TYPE_SINT64,
+	"fixed32":  dpb.FieldDescriptorProto_TYPE_FIXED32,
+	"fixed64":  dpb.FieldDescriptorProto_TYPE_FIXED64,
+	"sfixed32": dpb.FieldDescriptorProto_TYPE_SFIXED32,
+	"sfixed64": dpb.FieldDescriptorProto_TYPE_SFIXED64,
+	"bool":     dpb.FieldDescriptorProto_TYPE_BOOL,
+	"string":   dpb.FieldDescriptorProto_TYPE_STRING,
+	"bytes":    dpb.FieldDescriptorProto_TYPE_BYTES,
+}
+
 func newFieldDescriptor(name string, fieldType string, tag int32, lbl *dpb.FieldDescriptorProto_Label) *dpb.FieldDescriptorProto {
 	fd := &dpb.FieldDescriptorProto{
 		Name:     proto.String(name),
@@ -840,41 +817,13 @@
 		Number:   proto.Int32(tag),
 		Label:    lbl,
 	}
-	switch fieldType {
-	case "double":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_DOUBLE.Enum()
-	case "float":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_FLOAT.Enum()
-	case "int32":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_INT32.Enum()
-	case "int64":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_INT64.Enum()
-	case "uint32":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_UINT32.Enum()
-	case "uint64":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_UINT64.Enum()
-	case "sint32":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_SINT32.Enum()
-	case "sint64":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_SINT64.Enum()
-	case "fixed32":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_FIXED32.Enum()
-	case "fixed64":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_FIXED64.Enum()
-	case "sfixed32":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_SFIXED32.Enum()
-	case "sfixed64":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_SFIXED64.Enum()
-	case "bool":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_BOOL.Enum()
-	case "string":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_STRING.Enum()
-	case "bytes":
-		fd.Type = dpb.FieldDescriptorProto_TYPE_BYTES.Enum()
-	default:
-		// NB: we don't have enough info to determine whether this is an enum or a message type,
-		// so we'll change it to enum later once we can ascertain if it's an enum reference
-		fd.Type = dpb.FieldDescriptorProto_TYPE_MESSAGE.Enum()
+	t, ok := fieldTypes[fieldType]
+	if ok {
+		fd.Type = t.Enum()
+	} else {
+		// NB: we don't have enough info to determine whether this is an enum
+		// or a message type, so we'll leave Type nil and set it later
+		// (during linking)
 		fd.TypeName = proto.String(fieldType)
 	}
 	return fd
@@ -886,14 +835,14 @@
 		Name:     proto.String(fieldName),
 		JsonName: proto.String(internal.JsonName(fieldName)),
 		Number:   proto.Int32(int32(group.tag.val)),
-		Label:    asLabel(group.label),
+		Label:    asLabel(&group.label),
 		Type:     dpb.FieldDescriptorProto_TYPE_GROUP.Enum(),
 		TypeName: proto.String(group.name.val),
 	}
 	r.putFieldNode(fd, group)
 	md := &dpb.DescriptorProto{Name: proto.String(group.name.val)}
 	r.putMessageNode(md, group)
-	r.addMessageDecls(md, &group.reserved, group.decls, isProto3)
+	r.addMessageDecls(md, group.decls, isProto3)
 	return fd, md
 }
 
@@ -902,14 +851,14 @@
 	if !isProto3 {
 		lbl = dpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum()
 	}
-	keyFd := newFieldDescriptor("key", mapField.keyType.val, 1, lbl)
+	keyFd := newFieldDescriptor("key", mapField.mapType.keyType.val, 1, lbl)
 	r.putFieldNode(keyFd, mapField.keyField())
-	valFd := newFieldDescriptor("value", mapField.valueType.val, 2, lbl)
+	valFd := newFieldDescriptor("value", mapField.mapType.valueType.val, 2, lbl)
 	r.putFieldNode(valFd, mapField.valueField())
 	entryName := internal.InitCap(internal.JsonName(mapField.name.val)) + "Entry"
 	fd := newFieldDescriptor(mapField.name.val, entryName, int32(mapField.tag.val), dpb.FieldDescriptorProto_LABEL_REPEATED.Enum())
-	if len(mapField.options) > 0 {
-		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(mapField.options)}
+	if opts := mapField.options.Elements(); len(opts) > 0 {
+		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
 	}
 	r.putFieldNode(fd, mapField)
 	md := &dpb.DescriptorProto{
@@ -922,7 +871,7 @@
 }
 
 func (r *parseResult) asExtensionRanges(node *extensionRangeNode) []*dpb.DescriptorProto_ExtensionRange {
-	opts := r.asUninterpretedOptions(node.options)
+	opts := r.asUninterpretedOptions(node.options.Elements())
 	ers := make([]*dpb.DescriptorProto_ExtensionRange, len(node.ranges))
 	for i, rng := range node.ranges {
 		er := &dpb.DescriptorProto_ExtensionRange{
@@ -939,16 +888,11 @@
 }
 
 func (r *parseResult) asEnumValue(ev *enumValueNode) *dpb.EnumValueDescriptorProto {
-	var num int32
-	if ev.numberP != nil {
-		num = int32(ev.numberP.val)
-	} else {
-		num = int32(ev.numberN.val)
-	}
+	num := int32(ev.number.val)
 	evd := &dpb.EnumValueDescriptorProto{Name: proto.String(ev.name.val), Number: proto.Int32(num)}
 	r.putEnumValueNode(evd, ev)
-	if len(ev.options) > 0 {
-		evd.Options = &dpb.EnumValueOptions{UninterpretedOption: r.asUninterpretedOptions(ev.options)}
+	if opts := ev.options.Elements(); len(opts) > 0 {
+		evd.Options = &dpb.EnumValueOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
 	}
 	return evd
 }
@@ -989,7 +933,6 @@
 			ed.Value = append(ed.Value, r.asEnumValue(decl.value))
 		} else if decl.reserved != nil {
 			for _, n := range decl.reserved.names {
-				en.reserved = append(en.reserved, n)
 				ed.ReservedName = append(ed.ReservedName, n.val)
 			}
 			for _, rng := range decl.reserved.ranges {
@@ -1012,11 +955,11 @@
 func (r *parseResult) asMessageDescriptor(node *messageNode, isProto3 bool) *dpb.DescriptorProto {
 	msgd := &dpb.DescriptorProto{Name: proto.String(node.name.val)}
 	r.putMessageNode(msgd, node)
-	r.addMessageDecls(msgd, &node.reserved, node.decls, isProto3)
+	r.addMessageDecls(msgd, node.decls, isProto3)
 	return msgd
 }
 
-func (r *parseResult) addMessageDecls(msgd *dpb.DescriptorProto, reservedNames *[]*stringLiteralNode, decls []*messageElement, isProto3 bool) {
+func (r *parseResult) addMessageDecls(msgd *dpb.DescriptorProto, decls []*messageElement, isProto3 bool) {
 	for _, decl := range decls {
 		if decl.enum != nil {
 			msgd.EnumType = append(msgd.EnumType, r.asEnumDescriptor(decl.enum))
@@ -1049,6 +992,11 @@
 					fd := r.asFieldDescriptor(oodecl.field)
 					fd.OneofIndex = proto.Int32(int32(oodIndex))
 					msgd.Field = append(msgd.Field, fd)
+				} else if oodecl.group != nil {
+					fd, md := r.asGroupDescriptors(oodecl.group, isProto3)
+					fd.OneofIndex = proto.Int32(int32(oodIndex))
+					msgd.Field = append(msgd.Field, fd)
+					msgd.NestedType = append(msgd.NestedType, md)
 				}
 			}
 		} else if decl.option != nil {
@@ -1060,7 +1008,6 @@
 			msgd.NestedType = append(msgd.NestedType, r.asMessageDescriptor(decl.nested, isProto3))
 		} else if decl.reserved != nil {
 			for _, n := range decl.reserved.names {
-				*reservedNames = append(*reservedNames, n)
 				msgd.ReservedName = append(msgd.ReservedName, n.val)
 			}
 			for _, rng := range decl.reserved.ranges {
@@ -1095,7 +1042,7 @@
 	return sd
 }
 
-func toNameParts(ident *identNode, offset int) []*optionNamePartNode {
+func toNameParts(ident *compoundIdentNode, offset int) []*optionNamePartNode {
 	parts := strings.Split(ident.val[offset:], ".")
 	ret := make([]*optionNamePartNode, len(parts))
 	for i, p := range parts {
@@ -1119,7 +1066,9 @@
 }
 
 func checkTag(lex protoLexer, pos *SourcePos, v uint64) {
-	if v > internal.MaxTag {
+	if v < 1 {
+		lexError(lex, pos, fmt.Sprintf("tag number %d must be greater than zero", v))
+	} else if v > internal.MaxTag {
 		lexError(lex, pos, fmt.Sprintf("tag number %d is higher than max allowed tag number (%d)", v, internal.MaxTag))
 	} else if v >= internal.SpecialReservedStart && v <= internal.SpecialReservedEnd {
 		lexError(lex, pos, fmt.Sprintf("tag number %d is in disallowed reserved range %d-%d", v, internal.SpecialReservedStart, internal.SpecialReservedEnd))
@@ -1206,28 +1155,27 @@
 	}
 }
 
-func basicValidate(res *parseResult) error {
+func basicValidate(res *parseResult) {
 	fd := res.fd
 	isProto3 := fd.GetSyntax() == "proto3"
 
 	for _, md := range fd.MessageType {
-		if err := validateMessage(res, isProto3, "", md); err != nil {
-			return err
+		if validateMessage(res, isProto3, "", md) != nil {
+			return
 		}
 	}
 
 	for _, ed := range fd.EnumType {
-		if err := validateEnum(res, isProto3, "", ed); err != nil {
-			return err
+		if validateEnum(res, isProto3, "", ed) != nil {
+			return
 		}
 	}
 
 	for _, fld := range fd.Extension {
-		if err := validateField(res, isProto3, "", fld); err != nil {
-			return err
+		if validateField(res, isProto3, "", fld) != nil {
+			return
 		}
 	}
-	return nil
 }
 
 func validateMessage(res *parseResult, isProto3 bool, prefix string, md *dpb.DescriptorProto) error {
@@ -1258,11 +1206,15 @@
 
 	if isProto3 && len(md.ExtensionRange) > 0 {
 		n := res.getExtensionRangeNode(md.ExtensionRange[0])
-		return ErrorWithSourcePos{Pos: n.start(), Underlying: fmt.Errorf("%s: extension ranges are not allowed in proto3", scope)}
+		if err := res.errs.handleError(ErrorWithSourcePos{Pos: n.start(), Underlying: fmt.Errorf("%s: extension ranges are not allowed in proto3", scope)}); err != nil {
+			return err
+		}
 	}
 
 	if index, err := findOption(res, scope, md.Options.GetUninterpretedOption(), "map_entry"); err != nil {
-		return err
+		if err := res.errs.handleError(err); err != nil {
+			return err
+		}
 	} else if index >= 0 {
 		opt := md.Options.UninterpretedOption[index]
 		optn := res.getOptionNode(opt)
@@ -1270,14 +1222,19 @@
 		valid := false
 		if opt.IdentifierValue != nil {
 			if opt.GetIdentifierValue() == "true" {
-				return ErrorWithSourcePos{Pos: optn.getValue().start(), Underlying: fmt.Errorf("%s: map_entry option should not be set explicitly; use map type instead", scope)}
-			} else if opt.GetIdentifierValue() == "false" {
-				md.Options.MapEntry = proto.Bool(false)
 				valid = true
+				if err := res.errs.handleError(ErrorWithSourcePos{Pos: optn.getValue().start(), Underlying: fmt.Errorf("%s: map_entry option should not be set explicitly; use map type instead", scope)}); err != nil {
+					return err
+				}
+			} else if opt.GetIdentifierValue() == "false" {
+				valid = true
+				md.Options.MapEntry = proto.Bool(false)
 			}
 		}
 		if !valid {
-			return ErrorWithSourcePos{Pos: optn.getValue().start(), Underlying: fmt.Errorf("%s: expecting bool value for map_entry option", scope)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: optn.getValue().start(), Underlying: fmt.Errorf("%s: expecting bool value for map_entry option", scope)}); err != nil {
+				return err
+			}
 		}
 	}
 
@@ -1291,7 +1248,9 @@
 	sort.Sort(rsvd)
 	for i := 1; i < len(rsvd); i++ {
 		if rsvd[i].start < rsvd[i-1].end {
-			return ErrorWithSourcePos{Pos: rsvd[i].node.start(), Underlying: fmt.Errorf("%s: reserved ranges overlap: %d to %d and %d to %d", scope, rsvd[i-1].start, rsvd[i-1].end-1, rsvd[i].start, rsvd[i].end-1)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: rsvd[i].node.start(), Underlying: fmt.Errorf("%s: reserved ranges overlap: %d to %d and %d to %d", scope, rsvd[i-1].start, rsvd[i-1].end-1, rsvd[i].start, rsvd[i].end-1)}); err != nil {
+				return err
+			}
 		}
 	}
 
@@ -1304,7 +1263,9 @@
 	sort.Sort(exts)
 	for i := 1; i < len(exts); i++ {
 		if exts[i].start < exts[i-1].end {
-			return ErrorWithSourcePos{Pos: exts[i].node.start(), Underlying: fmt.Errorf("%s: extension ranges overlap: %d to %d and %d to %d", scope, exts[i-1].start, exts[i-1].end-1, exts[i].start, exts[i].end-1)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: exts[i].node.start(), Underlying: fmt.Errorf("%s: extension ranges overlap: %d to %d and %d to %d", scope, exts[i-1].start, exts[i-1].end-1, exts[i].start, exts[i].end-1)}); err != nil {
+				return err
+			}
 		}
 	}
 
@@ -1321,7 +1282,9 @@
 				pos = exts[j].node.start()
 			}
 			// ranges overlap
-			return ErrorWithSourcePos{Pos: pos, Underlying: fmt.Errorf("%s: extension range %d to %d overlaps reserved range %d to %d", scope, exts[j].start, exts[j].end-1, rsvd[i].start, rsvd[i].end-1)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: pos, Underlying: fmt.Errorf("%s: extension range %d to %d overlaps reserved range %d to %d", scope, exts[j].start, exts[j].end-1, rsvd[i].start, rsvd[i].end-1)}); err != nil {
+				return err
+			}
 		}
 		if rsvd[i].start < exts[j].start {
 			i++
@@ -1340,21 +1303,29 @@
 	for _, fld := range md.Field {
 		fn := res.getFieldNode(fld)
 		if _, ok := rsvdNames[fld.GetName()]; ok {
-			return ErrorWithSourcePos{Pos: fn.fieldName().start(), Underlying: fmt.Errorf("%s: field %s is using a reserved name", scope, fld.GetName())}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: fn.fieldName().start(), Underlying: fmt.Errorf("%s: field %s is using a reserved name", scope, fld.GetName())}); err != nil {
+				return err
+			}
 		}
 		if existing := fieldTags[fld.GetNumber()]; existing != "" {
-			return ErrorWithSourcePos{Pos: fn.fieldTag().start(), Underlying: fmt.Errorf("%s: fields %s and %s both have the same tag %d", scope, existing, fld.GetName(), fld.GetNumber())}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: fn.fieldTag().start(), Underlying: fmt.Errorf("%s: fields %s and %s both have the same tag %d", scope, existing, fld.GetName(), fld.GetNumber())}); err != nil {
+				return err
+			}
 		}
 		fieldTags[fld.GetNumber()] = fld.GetName()
 		// check reserved ranges
 		r := sort.Search(len(rsvd), func(index int) bool { return rsvd[index].end > fld.GetNumber() })
 		if r < len(rsvd) && rsvd[r].start <= fld.GetNumber() {
-			return ErrorWithSourcePos{Pos: fn.fieldTag().start(), Underlying: fmt.Errorf("%s: field %s is using tag %d which is in reserved range %d to %d", scope, fld.GetName(), fld.GetNumber(), rsvd[r].start, rsvd[r].end-1)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: fn.fieldTag().start(), Underlying: fmt.Errorf("%s: field %s is using tag %d which is in reserved range %d to %d", scope, fld.GetName(), fld.GetNumber(), rsvd[r].start, rsvd[r].end-1)}); err != nil {
+				return err
+			}
 		}
 		// and check extension ranges
 		e := sort.Search(len(exts), func(index int) bool { return exts[index].end > fld.GetNumber() })
 		if e < len(exts) && exts[e].start <= fld.GetNumber() {
-			return ErrorWithSourcePos{Pos: fn.fieldTag().start(), Underlying: fmt.Errorf("%s: field %s is using tag %d which is in extension range %d to %d", scope, fld.GetName(), fld.GetNumber(), exts[e].start, exts[e].end-1)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: fn.fieldTag().start(), Underlying: fmt.Errorf("%s: field %s is using tag %d which is in extension range %d to %d", scope, fld.GetName(), fld.GetNumber(), exts[e].start, exts[e].end-1)}); err != nil {
+				return err
+			}
 		}
 	}
 
@@ -1364,39 +1335,46 @@
 func validateEnum(res *parseResult, isProto3 bool, prefix string, ed *dpb.EnumDescriptorProto) error {
 	scope := fmt.Sprintf("enum %s%s", prefix, ed.GetName())
 
+	allowAlias := false
 	if index, err := findOption(res, scope, ed.Options.GetUninterpretedOption(), "allow_alias"); err != nil {
-		return err
+		if err := res.errs.handleError(err); err != nil {
+			return err
+		}
 	} else if index >= 0 {
 		opt := ed.Options.UninterpretedOption[index]
-		ed.Options.UninterpretedOption = removeOption(ed.Options.UninterpretedOption, index)
 		valid := false
 		if opt.IdentifierValue != nil {
 			if opt.GetIdentifierValue() == "true" {
-				ed.Options.AllowAlias = proto.Bool(true)
+				allowAlias = true
 				valid = true
 			} else if opt.GetIdentifierValue() == "false" {
-				ed.Options.AllowAlias = proto.Bool(false)
 				valid = true
 			}
 		}
 		if !valid {
 			optNode := res.getOptionNode(opt)
-			return ErrorWithSourcePos{Pos: optNode.getValue().start(), Underlying: fmt.Errorf("%s: expecting bool value for allow_alias option", scope)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: optNode.getValue().start(), Underlying: fmt.Errorf("%s: expecting bool value for allow_alias option", scope)}); err != nil {
+				return err
+			}
 		}
 	}
 
 	if isProto3 && ed.Value[0].GetNumber() != 0 {
 		evNode := res.getEnumValueNode(ed.Value[0])
-		return ErrorWithSourcePos{Pos: evNode.getNumber().start(), Underlying: fmt.Errorf("%s: proto3 requires that first value in enum have numeric value of 0", scope)}
+		if err := res.errs.handleError(ErrorWithSourcePos{Pos: evNode.getNumber().start(), Underlying: fmt.Errorf("%s: proto3 requires that first value in enum have numeric value of 0", scope)}); err != nil {
+			return err
+		}
 	}
 
-	if !ed.Options.GetAllowAlias() {
+	if !allowAlias {
 		// make sure all value numbers are distinct
 		vals := map[int32]string{}
 		for _, evd := range ed.Value {
 			if existing := vals[evd.GetNumber()]; existing != "" {
 				evNode := res.getEnumValueNode(evd)
-				return ErrorWithSourcePos{Pos: evNode.getNumber().start(), Underlying: fmt.Errorf("%s: values %s and %s both have the same numeric value %d; use allow_alias option if intentional", scope, existing, evd.GetName(), evd.GetNumber())}
+				if err := res.errs.handleError(ErrorWithSourcePos{Pos: evNode.getNumber().start(), Underlying: fmt.Errorf("%s: values %s and %s both have the same numeric value %d; use allow_alias option if intentional", scope, existing, evd.GetName(), evd.GetNumber())}); err != nil {
+					return err
+				}
 			}
 			vals[evd.GetNumber()] = evd.GetName()
 		}
@@ -1411,7 +1389,9 @@
 	sort.Sort(rsvd)
 	for i := 1; i < len(rsvd); i++ {
 		if rsvd[i].start <= rsvd[i-1].end {
-			return ErrorWithSourcePos{Pos: rsvd[i].node.start(), Underlying: fmt.Errorf("%s: reserved ranges overlap: %d to %d and %d to %d", scope, rsvd[i-1].start, rsvd[i-1].end, rsvd[i].start, rsvd[i].end)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: rsvd[i].node.start(), Underlying: fmt.Errorf("%s: reserved ranges overlap: %d to %d and %d to %d", scope, rsvd[i-1].start, rsvd[i-1].end, rsvd[i].start, rsvd[i].end)}); err != nil {
+				return err
+			}
 		}
 	}
 
@@ -1424,12 +1404,16 @@
 	for _, ev := range ed.Value {
 		evn := res.getEnumValueNode(ev)
 		if _, ok := rsvdNames[ev.GetName()]; ok {
-			return ErrorWithSourcePos{Pos: evn.getName().start(), Underlying: fmt.Errorf("%s: value %s is using a reserved name", scope, ev.GetName())}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: evn.getName().start(), Underlying: fmt.Errorf("%s: value %s is using a reserved name", scope, ev.GetName())}); err != nil {
+				return err
+			}
 		}
 		// check reserved ranges
 		r := sort.Search(len(rsvd), func(index int) bool { return rsvd[index].end >= ev.GetNumber() })
 		if r < len(rsvd) && rsvd[r].start <= ev.GetNumber() {
-			return ErrorWithSourcePos{Pos: evn.getNumber().start(), Underlying: fmt.Errorf("%s: value %s is using number %d which is in reserved range %d to %d", scope, ev.GetName(), ev.GetNumber(), rsvd[r].start, rsvd[r].end)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: evn.getNumber().start(), Underlying: fmt.Errorf("%s: value %s is using number %d which is in reserved range %d to %d", scope, ev.GetName(), ev.GetNumber(), rsvd[r].start, rsvd[r].end)}); err != nil {
+				return err
+			}
 		}
 	}
 
@@ -1443,23 +1427,34 @@
 	if isProto3 {
 		if fld.GetType() == dpb.FieldDescriptorProto_TYPE_GROUP {
 			n := node.(*groupNode)
-			return ErrorWithSourcePos{Pos: n.groupKeyword.start(), Underlying: fmt.Errorf("%s: groups are not allowed in proto3", scope)}
-		}
-		if fld.Label != nil && fld.GetLabel() != dpb.FieldDescriptorProto_LABEL_REPEATED {
-			return ErrorWithSourcePos{Pos: node.fieldLabel().start(), Underlying: fmt.Errorf("%s: field has label %v, but proto3 should omit labels other than 'repeated'", scope, fld.GetLabel())}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: n.groupKeyword.start(), Underlying: fmt.Errorf("%s: groups are not allowed in proto3", scope)}); err != nil {
+				return err
+			}
+		} else if fld.Label != nil && fld.GetLabel() != dpb.FieldDescriptorProto_LABEL_REPEATED {
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: node.fieldLabel().start(), Underlying: fmt.Errorf("%s: field has label %v, but proto3 must omit labels other than 'repeated'", scope, fld.GetLabel())}); err != nil {
+				return err
+			}
 		}
 		if index, err := findOption(res, scope, fld.Options.GetUninterpretedOption(), "default"); err != nil {
-			return err
+			if err := res.errs.handleError(err); err != nil {
+				return err
+			}
 		} else if index >= 0 {
 			optNode := res.getOptionNode(fld.Options.GetUninterpretedOption()[index])
-			return ErrorWithSourcePos{Pos: optNode.getName().start(), Underlying: fmt.Errorf("%s: default values are not allowed in proto3", scope)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: optNode.getName().start(), Underlying: fmt.Errorf("%s: default values are not allowed in proto3", scope)}); err != nil {
+				return err
+			}
 		}
 	} else {
 		if fld.Label == nil && fld.OneofIndex == nil {
-			return ErrorWithSourcePos{Pos: node.fieldName().start(), Underlying: fmt.Errorf("%s: field has no label, but proto2 must indicate 'optional' or 'required'", scope)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: node.fieldName().start(), Underlying: fmt.Errorf("%s: field has no label, but proto2 must indicate 'optional' or 'required'", scope)}); err != nil {
+				return err
+			}
 		}
 		if fld.GetExtendee() != "" && fld.Label != nil && fld.GetLabel() == dpb.FieldDescriptorProto_LABEL_REQUIRED {
-			return ErrorWithSourcePos{Pos: node.fieldLabel().start(), Underlying: fmt.Errorf("%s: extension fields cannot be 'required'", scope)}
+			if err := res.errs.handleError(ErrorWithSourcePos{Pos: node.fieldLabel().start(), Underlying: fmt.Errorf("%s: extension fields cannot be 'required'", scope)}); err != nil {
+				return err
+			}
 		}
 	}
 
@@ -1467,6 +1462,7 @@
 	if fld.Label == nil {
 		fld.Label = dpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum()
 	}
+
 	return nil
 }
 
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/proto.y b/vendor/github.com/jhump/protoreflect/desc/protoparse/proto.y
index faf49d9..a795fe7 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoparse/proto.y
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/proto.y
@@ -25,6 +25,7 @@
 	msgDecls  []*messageElement
 	fld       *fieldNode
 	mapFld    *mapFieldNode
+	mapType   *mapTypeNode
 	grp       *groupNode
 	oo        *oneOfNode
 	ooDecls   []*oneOfElement
@@ -41,15 +42,18 @@
 	rpcType   *rpcTypeNode
 	opts      []*optionNode
 	optNm     []*optionNamePartNode
+	cmpctOpts *compactOptionsNode
 	rngs      []*rangeNode
-	names     []*stringLiteralNode
+	names     []*compoundStringNode
+	cid       *compoundIdentNode
 	sl        []valueNode
 	agg       []*aggregateEntryNode
 	aggName   *aggregateNameNode
 	v         valueNode
-	str       *stringLiteralNode
-	i         *negativeIntLiteralNode
-	ui        *intLiteralNode
+	il        *compoundIntNode
+	str       *compoundStringNode
+	s         *stringLiteralNode
+	i         *intLiteralNode
 	f         *floatLiteralNode
 	id        *identNode
 	b         *basicNode
@@ -63,20 +67,21 @@
 %type <fileDecls> fileDecl fileDecls
 %type <imprt>     import
 %type <pkg>       package
-%type <opts>      option fieldOption fieldOptions rpcOption rpcOptions
+%type <opts>      option compactOption compactOptionDecls rpcOption rpcOptions
 %type <optNm>     optionName optionNameRest optionNameComponent
-%type <v>         constant scalarConstant aggregate
-%type <id>        name ident typeIdent keyType
+%type <cmpctOpts> compactOptions
+%type <v>         constant scalarConstant aggregate uintLit floatLit
+%type <il>        intLit negIntLit
+%type <id>        name keyType
+%type <cid>       ident typeIdent
 %type <aggName>   aggName
-%type <i>         negIntLit
-%type <ui>        intLit
-%type <f>         floatLit
 %type <sl>        constantList
 %type <agg>       aggFields aggField aggFieldEntry
 %type <fld>       field oneofField
 %type <oo>        oneof
-%type <grp>       group
+%type <grp>       group oneofGroup
 %type <mapFld>    mapField
+%type <mapType>   mapType
 %type <msg>       message
 %type <msgDecls>  messageItem messageBody
 %type <ooDecls>   oneofItem oneofBody
@@ -96,10 +101,10 @@
 %type <rpcType>   rpcType
 
 // same for terminals
-%token <str> _STRING_LIT
-%token <ui>  _INT_LIT
+%token <s> _STRING_LIT
+%token <i>  _INT_LIT
 %token <f>   _FLOAT_LIT
-%token <id>  _NAME _FQNAME _TYPENAME
+%token <id>  _NAME
 %token <id>  _SYNTAX _IMPORT _WEAK _PUBLIC _PACKAGE _OPTION _TRUE _FALSE _INF _NAN _REPEATED _OPTIONAL _REQUIRED
 %token <id>  _DOUBLE _FLOAT _INT32 _INT64 _UINT32 _UINT64 _SINT32 _SINT64 _FIXED32 _FIXED64 _SFIXED32 _SFIXED64
 %token <id>  _BOOL _STRING _BYTES _GROUP _ONEOF _MAP _EXTENSIONS _TO _MAX _RESERVED _ENUM _MESSAGE _EXTEND
@@ -166,6 +171,10 @@
 	| ';' {
 		$$ = []*fileElement{{empty: $1}}
 	}
+	| error ';' {
+	}
+	| error {
+	}
 
 syntax : _SYNTAX '=' stringLit ';' {
 		if $3.val != "proto2" && $3.val != "proto3" {
@@ -193,8 +202,14 @@
 		$$.setRange($1, $3)
 	}
 
-ident : name
-	| _FQNAME
+ident : name {
+        $$ = &compoundIdentNode{val: $1.val}
+        $$.setRange($1, $1)
+    }
+	| ident '.' name {
+        $$ = &compoundIdentNode{val: $1.val + "." + $3.val}
+        $$.setRange($1, $3)
+	}
 
 option : _OPTION optionName '=' constant ';' {
 		n := &optionNameNode{parts: $2}
@@ -225,7 +240,7 @@
 		$$ = append($1, $2...)
 	}
 
-optionNameComponent : _TYPENAME {
+optionNameComponent : typeIdent {
 		$$ = toNameParts($1, 1 /* exclude leading dot */)
 	}
 	| '.' '(' typeIdent ')' {
@@ -240,26 +255,22 @@
 scalarConstant : stringLit {
 		$$ = $1
 	}
-	| intLit {
-		$$ = $1
-	}
+	| uintLit
 	| negIntLit {
-		$$ = $1
+	    $$ = $1
 	}
-	| floatLit {
-		$$ = $1
-	}
+	| floatLit
 	| name {
 		if $1.val == "true" {
-			$$ = &boolLiteralNode{basicNode: $1.basicNode, val: true}
+			$$ = &boolLiteralNode{identNode: $1, val: true}
 		} else if $1.val == "false" {
-			$$ = &boolLiteralNode{basicNode: $1.basicNode, val: false}
+			$$ = &boolLiteralNode{identNode: $1, val: false}
 		} else if $1.val == "inf" {
-			f := &floatLiteralNode{val: math.Inf(1)}
+			f := &compoundFloatNode{val: math.Inf(1)}
 			f.setRange($1, $1)
 			$$ = f
 		} else if $1.val == "nan" {
-			f := &floatLiteralNode{val: math.NaN()}
+			f := &compoundFloatNode{val: math.NaN()}
 			f.setRange($1, $1)
 			$$ = f
 		} else {
@@ -267,40 +278,65 @@
 		}
 	}
 
-intLit : _INT_LIT
+uintLit : _INT_LIT {
+        i := &compoundUintNode{val: $1.val}
+        i.setRange($1, $1)
+        $$ = i
+    }
 	| '+' _INT_LIT {
-		$$ = $2
+        i := &compoundUintNode{val: $2.val}
+        i.setRange($1, $2)
+        $$ = i
 	}
 
 negIntLit : '-' _INT_LIT {
 		if $2.val > math.MaxInt64 + 1 {
 			lexError(protolex, $2.start(), fmt.Sprintf("numeric constant %d would underflow (allowed range is %d to %d)", $2.val, int64(math.MinInt64), int64(math.MaxInt64)))
 		}
-		$$ = &negativeIntLiteralNode{val: -int64($2.val)}
-		$$.setRange($1, $2)
+		i := &compoundIntNode{val: -int64($2.val)}
+		i.setRange($1, $2)
+		$$ = i
 	}
 
-floatLit : _FLOAT_LIT
+intLit : negIntLit
+    | _INT_LIT {
+        // we don't allow uintLit because this is for enum numeric vals, which don't allow '+'
+        checkUint64InInt32Range(protolex, $1.start(), $1.val)
+		i := &compoundIntNode{val: int64($1.val)}
+		i.setRange($1, $1)
+		$$ = i
+    }
+
+floatLit : _FLOAT_LIT {
+        $$ = $1
+    }
 	| '-' _FLOAT_LIT {
-		$$ = &floatLiteralNode{val: -$2.val}
-		$$.setRange($1, $2)
+		f := &compoundFloatNode{val: -$2.val}
+		f.setRange($1, $2)
+		$$ = f
 	}
 	| '+' _FLOAT_LIT {
-		$$ = &floatLiteralNode{val: $2.val}
-		$$.setRange($1, $2)
+		f := &compoundFloatNode{val: $2.val}
+		f.setRange($1, $2)
+		$$ = f
 	}
 	| '+' _INF {
-		$$ = &floatLiteralNode{val: math.Inf(1)}
-		$$.setRange($1, $2)
+		f := &compoundFloatNode{val: math.Inf(1)}
+		f.setRange($1, $2)
+		$$ = f
 	}
 	| '-' _INF {
-		$$ = &floatLiteralNode{val: math.Inf(-1)}
-		$$.setRange($1, $2)
+		f := &compoundFloatNode{val: math.Inf(-1)}
+		f.setRange($1, $2)
+		$$ = f
 	}
 
-stringLit : _STRING_LIT
+stringLit : _STRING_LIT {
+        $$ = &compoundStringNode{val: $1.val}
+        $$.setRange($1, $1)
+    }
     | stringLit _STRING_LIT {
-        $$ = &stringLiteralNode{val: $1.val + $2.val}
+        $$ = &compoundStringNode{val: $1.val + $2.val}
         $$.setRange($1, $2)
     }
 
@@ -325,6 +361,12 @@
 	| aggFieldEntry ';' {
 		$$ = $1
 	}
+	| error ',' {
+	}
+	| error ';' {
+	}
+	| error {
+	}
 
 aggFieldEntry : aggName ':' scalarConstant {
 		a := &aggregateEntryNode{name: $1, val: $3}
@@ -345,6 +387,8 @@
 		a.setRange($1, $5)
 		$$ = []*aggregateEntryNode{a}
 	}
+	| aggName ':' '[' error ']' {
+	}
 	| aggName ':' aggregate {
 		a := &aggregateEntryNode{name: $1, val: $3}
 		a.setRange($1, $3)
@@ -369,15 +413,23 @@
 		a.setRange($1, $4)
 		$$ = []*aggregateEntryNode{a}
 	}
+	| aggName ':' '<' error '>' {
+	}
+	| aggName '<' error '>' {
+	}
 
 aggName : name {
-		$$ = &aggregateNameNode{name: $1}
+        n := &compoundIdentNode{val: $1.val}
+        n.setRange($1, $1)
+		$$ = &aggregateNameNode{name: n}
 		$$.setRange($1, $1)
 	}
-	| '[' ident ']' {
+	| '[' typeIdent ']' {
 		$$ = &aggregateNameNode{name: $2, isExtension: true}
 		$$.setRange($1, $3)
 	}
+	| '[' error ']' {
+	}
 
 constantList : constant {
 		$$ = []valueNode{$1}
@@ -403,25 +455,34 @@
 		s.setRange($3, $5)
 		$$ = append($1, s)
 	}
+	| '<' error '>' {
+	}
+	| constantList ','  '<' error '>' {
+	}
+	| constantList ';'  '<' error '>' {
+	}
 
 typeIdent : ident
-	| _TYPENAME
+    | '.' ident {
+          $$ = &compoundIdentNode{val: "." + $2.val}
+          $$.setRange($1, $2)
+    }
 
 field : _REQUIRED typeIdent name '=' _INT_LIT ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{basicNode: $1.basicNode, required: true}
+		lbl := fieldLabel{identNode: $1, required: true}
 		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5}
 		$$.setRange($1, $6)
 	}
 	| _OPTIONAL typeIdent name '=' _INT_LIT ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{basicNode: $1.basicNode}
+		lbl := fieldLabel{identNode: $1}
 		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5}
 		$$.setRange($1, $6)
 	}
 	| _REPEATED typeIdent name '=' _INT_LIT ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{basicNode: $1.basicNode, repeated: true}
+		lbl := fieldLabel{identNode: $1, repeated: true}
 		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5}
 		$$.setRange($1, $6)
 	}
@@ -430,36 +491,41 @@
 		$$ = &fieldNode{fldType: $1, name: $2, tag: $4}
 		$$.setRange($1, $5)
 	}
-	| _REQUIRED typeIdent name '=' _INT_LIT '[' fieldOptions ']' ';' {
+	| _REQUIRED typeIdent name '=' _INT_LIT compactOptions ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{basicNode: $1.basicNode, required: true}
-		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $7}
-		$$.setRange($1, $9)
+		lbl := fieldLabel{identNode: $1, required: true}
+		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $6}
+		$$.setRange($1, $7)
 	}
-	| _OPTIONAL typeIdent name '=' _INT_LIT '[' fieldOptions ']' ';' {
+	| _OPTIONAL typeIdent name '=' _INT_LIT compactOptions ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{basicNode: $1.basicNode}
-		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $7}
-		$$.setRange($1, $9)
+		lbl := fieldLabel{identNode: $1}
+		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $6}
+		$$.setRange($1, $7)
 	}
-	| _REPEATED typeIdent name '=' _INT_LIT '[' fieldOptions ']' ';' {
+	| _REPEATED typeIdent name '=' _INT_LIT compactOptions ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{basicNode: $1.basicNode, repeated: true}
-		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $7}
-		$$.setRange($1, $9)
+		lbl := fieldLabel{identNode: $1, repeated: true}
+		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $6}
+		$$.setRange($1, $7)
 	}
-	| typeIdent name '=' _INT_LIT '[' fieldOptions ']' ';' {
+	| typeIdent name '=' _INT_LIT compactOptions ';' {
 		checkTag(protolex, $4.start(), $4.val)
-		$$ = &fieldNode{fldType: $1, name: $2, tag: $4, options: $6}
-		$$.setRange($1, $8)
+		$$ = &fieldNode{fldType: $1, name: $2, tag: $4, options: $5}
+		$$.setRange($1, $6)
 	}
 
-fieldOptions : fieldOptions ',' fieldOption {
+compactOptions: '[' compactOptionDecls ']' {
+        $$ = &compactOptionsNode{decls: $2}
+        $$.setRange($1, $3)
+    }
+
+compactOptionDecls : compactOptionDecls ',' compactOption {
 		$$ = append($1, $3...)
 	}
-	| fieldOption
+	| compactOption
 
-fieldOption: optionName '=' constant {
+compactOption: optionName '=' constant {
 		n := &optionNameNode{parts: $1}
 		n.setRange($1[0], $1[len($1)-1])
 		o := &optionNode{name: n, val: $3}
@@ -472,7 +538,7 @@
 		if !unicode.IsUpper(rune($3.val[0])) {
 			lexError(protolex, $3.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", $3.val))
 		}
-		lbl := &labelNode{basicNode: $1.basicNode, required: true}
+		lbl := fieldLabel{identNode: $1, required: true}
 		$$ = &groupNode{groupKeyword: $2, label: lbl, name: $3, tag: $5, decls: $7}
 		$$.setRange($1, $8)
 	}
@@ -481,7 +547,7 @@
 		if !unicode.IsUpper(rune($3.val[0])) {
 			lexError(protolex, $3.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", $3.val))
 		}
-		lbl := &labelNode{basicNode: $1.basicNode}
+		lbl := fieldLabel{identNode: $1}
 		$$ = &groupNode{groupKeyword: $2, label: lbl, name: $3, tag: $5, decls: $7}
 		$$.setRange($1, $8)
 	}
@@ -490,7 +556,7 @@
 		if !unicode.IsUpper(rune($3.val[0])) {
 			lexError(protolex, $3.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", $3.val))
 		}
-		lbl := &labelNode{basicNode: $1.basicNode, repeated: true}
+		lbl := fieldLabel{identNode: $1, repeated: true}
 		$$ = &groupNode{groupKeyword: $2, label: lbl, name: $3, tag: $5, decls: $7}
 		$$.setRange($1, $8)
 	}
@@ -523,31 +589,52 @@
 	| oneofField {
 		$$ = []*oneOfElement{{field: $1}}
 	}
+	| oneofGroup {
+		$$ = []*oneOfElement{{group: $1}}
+	}
 	| ';' {
 		$$ = []*oneOfElement{{empty: $1}}
 	}
+	| error ';' {
+	}
+	| error {
+	}
 
 oneofField : typeIdent name '=' _INT_LIT ';' {
 		checkTag(protolex, $4.start(), $4.val)
 		$$ = &fieldNode{fldType: $1, name: $2, tag: $4}
 		$$.setRange($1, $5)
 	}
-	| typeIdent name '=' _INT_LIT '[' fieldOptions ']' ';' {
+	| typeIdent name '=' _INT_LIT compactOptions ';' {
 		checkTag(protolex, $4.start(), $4.val)
-		$$ = &fieldNode{fldType: $1, name: $2, tag: $4, options: $6}
-		$$.setRange($1, $8)
+		$$ = &fieldNode{fldType: $1, name: $2, tag: $4, options: $5}
+		$$.setRange($1, $6)
 	}
 
-mapField : _MAP '<' keyType ',' typeIdent '>' name '=' _INT_LIT ';' {
-		checkTag(protolex, $9.start(), $9.val)
-		$$ = &mapFieldNode{mapKeyword: $1, keyType: $3, valueType: $5, name: $7, tag: $9}
-		$$.setRange($1, $10)
+oneofGroup : _GROUP name '=' _INT_LIT '{' messageBody '}' {
+		checkTag(protolex, $4.start(), $4.val)
+		if !unicode.IsUpper(rune($2.val[0])) {
+			lexError(protolex, $2.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", $2.val))
+		}
+		$$ = &groupNode{groupKeyword: $1, name: $2, tag: $4, decls: $6}
+		$$.setRange($1, $7)
 	}
-	| _MAP '<' keyType ',' typeIdent '>' name '=' _INT_LIT '[' fieldOptions ']' ';' {
-		checkTag(protolex, $9.start(), $9.val)
-		$$ = &mapFieldNode{mapKeyword: $1, keyType: $3, valueType: $5, name: $7, tag: $9, options: $11}
-		$$.setRange($1, $13)
+
+mapField : mapType name '=' _INT_LIT ';' {
+		checkTag(protolex, $4.start(), $4.val)
+		$$ = &mapFieldNode{mapType: $1, name: $2, tag: $4}
+		$$.setRange($1, $5)
 	}
+	| mapType name '=' _INT_LIT compactOptions ';' {
+		checkTag(protolex, $4.start(), $4.val)
+		$$ = &mapFieldNode{mapType: $1, name: $2, tag: $4, options: $5}
+		$$.setRange($1, $6)
+	}
+
+mapType : _MAP '<' keyType ',' typeIdent '>' {
+        $$ = &mapTypeNode{mapKeyword: $1, keyType: $3, valueType: $5}
+        $$.setRange($1, $6)
+}
 
 keyType : _INT32
 	| _INT64
@@ -566,9 +653,9 @@
 		$$ = &extensionRangeNode{ranges: $2}
 		$$.setRange($1, $3)
 	}
-	| _EXTENSIONS tagRanges '[' fieldOptions ']' ';' {
-		$$ = &extensionRangeNode{ranges: $2, options: $4}
-		$$.setRange($1, $6)
+	| _EXTENSIONS tagRanges compactOptions ';' {
+		$$ = &extensionRangeNode{ranges: $2, options: $3}
+		$$.setRange($1, $4)
 	}
 
 tagRanges : tagRanges ',' tagRange {
@@ -612,29 +699,13 @@
 	}
 	| enumRange
 
-enumRange : _INT_LIT {
-		checkUint64InInt32Range(protolex, $1.start(), $1.val)
-		r := &rangeNode{stNode: $1, enNode: $1, st: int32($1.val), en: int32($1.val)}
-		r.setRange($1, $1)
-		$$ = []*rangeNode{r}
-	}
-	| negIntLit {
+enumRange : intLit {
 		checkInt64InInt32Range(protolex, $1.start(), $1.val)
 		r := &rangeNode{stNode: $1, enNode: $1, st: int32($1.val), en: int32($1.val)}
 		r.setRange($1, $1)
 		$$ = []*rangeNode{r}
 	}
-	| _INT_LIT _TO _INT_LIT {
-		checkUint64InInt32Range(protolex, $1.start(), $1.val)
-		checkUint64InInt32Range(protolex, $3.start(), $3.val)
-		if $1.val > $3.val {
-			lexError(protolex, $1.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", $1.val, $3.val))
-		}
-		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: int32($3.val)}
-		r.setRange($1, $3)
-		$$ = []*rangeNode{r}
-	}
-	| negIntLit _TO negIntLit {
+	| intLit _TO intLit {
 		checkInt64InInt32Range(protolex, $1.start(), $1.val)
 		checkInt64InInt32Range(protolex, $3.start(), $3.val)
 		if $1.val > $3.val {
@@ -644,20 +715,7 @@
 		r.setRange($1, $3)
 		$$ = []*rangeNode{r}
 	}
-	| negIntLit _TO _INT_LIT {
-		checkInt64InInt32Range(protolex, $1.start(), $1.val)
-		checkUint64InInt32Range(protolex, $3.start(), $3.val)
-		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: int32($3.val)}
-		r.setRange($1, $3)
-		$$ = []*rangeNode{r}
-	}
-	| _INT_LIT _TO _MAX {
-		checkUint64InInt32Range(protolex, $1.start(), $1.val)
-		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: math.MaxInt32}
-		r.setRange($1, $3)
-		$$ = []*rangeNode{r}
-	}
-	| negIntLit _TO _MAX {
+	| intLit _TO _MAX {
 		checkInt64InInt32Range(protolex, $1.start(), $1.val)
 		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: math.MaxInt32}
 		r.setRange($1, $3)
@@ -693,7 +751,7 @@
 		$$ = append($1, $3)
 	}
 	| stringLit {
-		$$ = []*stringLiteralNode{$1}
+		$$ = []*compoundStringNode{$1}
 	}
 
 enum : _ENUM name '{' enumBody '}' {
@@ -730,26 +788,20 @@
 	| ';' {
 		$$ = []*enumElement{{empty: $1}}
 	}
+	| error ';' {
+	}
+	| error {
+	}
 
-enumField : name '=' _INT_LIT ';' {
-		checkUint64InInt32Range(protolex, $3.start(), $3.val)
-		$$ = &enumValueNode{name: $1, numberP: $3}
+enumField : name '=' intLit ';' {
+		checkInt64InInt32Range(protolex, $3.start(), $3.val)
+		$$ = &enumValueNode{name: $1, number: $3}
 		$$.setRange($1, $4)
 	}
-	|  name '=' _INT_LIT '[' fieldOptions ']' ';' {
-		checkUint64InInt32Range(protolex, $3.start(), $3.val)
-		$$ = &enumValueNode{name: $1, numberP: $3, options: $5}
-		$$.setRange($1, $7)
-	}
-	| name '=' negIntLit ';' {
+	|  name '=' intLit compactOptions ';' {
 		checkInt64InInt32Range(protolex, $3.start(), $3.val)
-		$$ = &enumValueNode{name: $1, numberN: $3}
-		$$.setRange($1, $4)
-	}
-	|  name '=' negIntLit '[' fieldOptions ']' ';' {
-		checkInt64InInt32Range(protolex, $3.start(), $3.val)
-		$$ = &enumValueNode{name: $1, numberN: $3, options: $5}
-		$$.setRange($1, $7)
+		$$ = &enumValueNode{name: $1, number: $3, options: $4}
+		$$.setRange($1, $5)
 	}
 
 message : _MESSAGE name '{' messageBody '}' {
@@ -798,6 +850,10 @@
 	| ';' {
 		$$ = []*messageElement{{empty: $1}}
 	}
+	| error ';' {
+	}
+	| error {
+	}
 
 extend : _EXTEND typeIdent '{' extendBody '}' {
 		c := 0
@@ -830,6 +886,10 @@
 	| ';' {
 		$$ = []*extendElement{{empty: $1}}
 	}
+	| error ';' {
+	}
+	| error {
+	}
 
 service : _SERVICE name '{' serviceBody '}' {
 		$$ = &serviceNode{name: $2, decls: $4}
@@ -856,6 +916,10 @@
 	| ';' {
 		$$ = []*serviceElement{{empty: $1}}
 	}
+	| error ';' {
+	}
+	| error {
+	}
 
 rpc : _RPC name '(' rpcType ')' _RETURNS '(' rpcType ')' ';' {
 		$$ = &methodNode{name: $2, input: $4, output: $8}
@@ -889,6 +953,10 @@
 	| ';' {
 		$$ = []*optionNode{}
 	}
+	| error ';' {
+	}
+	| error {
+	}
 
 name : _NAME
 	| _SYNTAX
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/proto.y.go b/vendor/github.com/jhump/protoreflect/desc/protoparse/proto.y.go
index 6b8a4e6..843df01 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoparse/proto.y.go
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/proto.y.go
@@ -29,6 +29,7 @@
 	msgDecls  []*messageElement
 	fld       *fieldNode
 	mapFld    *mapFieldNode
+	mapType   *mapTypeNode
 	grp       *groupNode
 	oo        *oneOfNode
 	ooDecls   []*oneOfElement
@@ -45,15 +46,18 @@
 	rpcType   *rpcTypeNode
 	opts      []*optionNode
 	optNm     []*optionNamePartNode
+	cmpctOpts *compactOptionsNode
 	rngs      []*rangeNode
-	names     []*stringLiteralNode
+	names     []*compoundStringNode
+	cid       *compoundIdentNode
 	sl        []valueNode
 	agg       []*aggregateEntryNode
 	aggName   *aggregateNameNode
 	v         valueNode
-	str       *stringLiteralNode
-	i         *negativeIntLiteralNode
-	ui        *intLiteralNode
+	il        *compoundIntNode
+	str       *compoundStringNode
+	s         *stringLiteralNode
+	i         *intLiteralNode
 	f         *floatLiteralNode
 	id        *identNode
 	b         *basicNode
@@ -64,51 +68,49 @@
 const _INT_LIT = 57347
 const _FLOAT_LIT = 57348
 const _NAME = 57349
-const _FQNAME = 57350
-const _TYPENAME = 57351
-const _SYNTAX = 57352
-const _IMPORT = 57353
-const _WEAK = 57354
-const _PUBLIC = 57355
-const _PACKAGE = 57356
-const _OPTION = 57357
-const _TRUE = 57358
-const _FALSE = 57359
-const _INF = 57360
-const _NAN = 57361
-const _REPEATED = 57362
-const _OPTIONAL = 57363
-const _REQUIRED = 57364
-const _DOUBLE = 57365
-const _FLOAT = 57366
-const _INT32 = 57367
-const _INT64 = 57368
-const _UINT32 = 57369
-const _UINT64 = 57370
-const _SINT32 = 57371
-const _SINT64 = 57372
-const _FIXED32 = 57373
-const _FIXED64 = 57374
-const _SFIXED32 = 57375
-const _SFIXED64 = 57376
-const _BOOL = 57377
-const _STRING = 57378
-const _BYTES = 57379
-const _GROUP = 57380
-const _ONEOF = 57381
-const _MAP = 57382
-const _EXTENSIONS = 57383
-const _TO = 57384
-const _MAX = 57385
-const _RESERVED = 57386
-const _ENUM = 57387
-const _MESSAGE = 57388
-const _EXTEND = 57389
-const _SERVICE = 57390
-const _RPC = 57391
-const _STREAM = 57392
-const _RETURNS = 57393
-const _ERROR = 57394
+const _SYNTAX = 57350
+const _IMPORT = 57351
+const _WEAK = 57352
+const _PUBLIC = 57353
+const _PACKAGE = 57354
+const _OPTION = 57355
+const _TRUE = 57356
+const _FALSE = 57357
+const _INF = 57358
+const _NAN = 57359
+const _REPEATED = 57360
+const _OPTIONAL = 57361
+const _REQUIRED = 57362
+const _DOUBLE = 57363
+const _FLOAT = 57364
+const _INT32 = 57365
+const _INT64 = 57366
+const _UINT32 = 57367
+const _UINT64 = 57368
+const _SINT32 = 57369
+const _SINT64 = 57370
+const _FIXED32 = 57371
+const _FIXED64 = 57372
+const _SFIXED32 = 57373
+const _SFIXED64 = 57374
+const _BOOL = 57375
+const _STRING = 57376
+const _BYTES = 57377
+const _GROUP = 57378
+const _ONEOF = 57379
+const _MAP = 57380
+const _EXTENSIONS = 57381
+const _TO = 57382
+const _MAX = 57383
+const _RESERVED = 57384
+const _ENUM = 57385
+const _MESSAGE = 57386
+const _EXTEND = 57387
+const _SERVICE = 57388
+const _RPC = 57389
+const _STREAM = 57390
+const _RETURNS = 57391
+const _ERROR = 57392
 
 var protoToknames = [...]string{
 	"$end",
@@ -118,8 +120,6 @@
 	"_INT_LIT",
 	"_FLOAT_LIT",
 	"_NAME",
-	"_FQNAME",
-	"_TYPENAME",
 	"_SYNTAX",
 	"_IMPORT",
 	"_WEAK",
@@ -198,433 +198,562 @@
 const protoErrCode = 2
 const protoInitialStackSize = 16
 
-//line proto.y:937
+//line proto.y:1005
 
 //line yacctab:1
 var protoExca = [...]int{
+	-1, 0,
+	1, 4,
+	-2, 0,
 	-1, 1,
 	1, -1,
 	-2, 0,
+	-1, 2,
+	1, 1,
+	-2, 0,
+	-1, 3,
+	1, 2,
+	-2, 0,
+	-1, 22,
+	1, 3,
+	-2, 0,
+	-1, 93,
+	55, 162,
+	-2, 0,
+	-1, 94,
+	55, 150,
+	-2, 0,
+	-1, 95,
+	55, 179,
+	-2, 0,
+	-1, 97,
+	55, 188,
+	-2, 0,
+	-1, 110,
+	55, 54,
+	-2, 0,
+	-1, 229,
+	61, 54,
+	-2, 0,
+	-1, 246,
+	55, 103,
+	-2, 0,
+	-1, 272,
+	61, 54,
+	-2, 0,
+	-1, 316,
+	61, 54,
+	-2, 0,
+	-1, 354,
+	55, 162,
+	-2, 0,
+	-1, 357,
+	55, 162,
+	-2, 0,
+	-1, 360,
+	55, 162,
+	-2, 0,
+	-1, 370,
+	61, 54,
+	-2, 0,
+	-1, 372,
+	61, 54,
+	-2, 0,
+	-1, 393,
+	55, 162,
+	-2, 0,
+	-1, 404,
+	55, 200,
+	-2, 0,
 }
 
 const protoPrivate = 57344
 
-const protoLast = 2050
+const protoLast = 2634
 
 var protoAct = [...]int{
 
-	120, 8, 288, 8, 8, 386, 264, 80, 128, 113,
-	159, 160, 265, 271, 103, 196, 185, 112, 100, 101,
-	29, 171, 8, 28, 75, 119, 99, 114, 79, 153,
-	137, 148, 266, 184, 24, 139, 306, 255, 77, 78,
-	319, 82, 306, 83, 389, 86, 87, 306, 318, 74,
-	378, 306, 98, 306, 306, 363, 317, 306, 306, 361,
-	306, 359, 351, 222, 379, 338, 337, 366, 307, 328,
-	377, 224, 325, 322, 304, 280, 278, 286, 223, 380,
-	315, 356, 367, 197, 329, 90, 243, 326, 323, 305,
-	281, 279, 297, 140, 111, 154, 27, 197, 249, 214,
-	209, 106, 188, 336, 246, 276, 241, 330, 240, 211,
-	105, 173, 245, 144, 242, 287, 224, 208, 381, 150,
-	382, 149, 176, 146, 327, 207, 324, 163, 16, 226,
-	94, 93, 92, 91, 177, 179, 181, 16, 199, 140,
-	79, 75, 85, 392, 199, 383, 368, 199, 374, 183,
-	78, 77, 373, 154, 16, 187, 191, 372, 199, 144,
-	198, 365, 157, 174, 85, 191, 74, 156, 355, 146,
-	189, 206, 212, 150, 193, 149, 388, 354, 204, 201,
-	163, 210, 203, 14, 333, 158, 15, 16, 157, 85,
-	85, 88, 97, 156, 213, 16, 202, 335, 215, 216,
-	217, 218, 219, 220, 308, 262, 261, 4, 14, 244,
-	260, 15, 16, 376, 96, 259, 258, 18, 17, 19,
-	20, 257, 254, 256, 221, 339, 13, 272, 252, 194,
-	105, 75, 163, 248, 388, 275, 250, 390, 283, 95,
-	84, 267, 18, 17, 19, 20, 89, 23, 247, 225,
-	352, 13, 268, 303, 168, 169, 27, 186, 290, 302,
-	198, 282, 277, 285, 295, 301, 206, 170, 300, 5,
-	299, 272, 105, 22, 163, 163, 284, 117, 11, 275,
-	11, 11, 165, 166, 310, 312, 313, 75, 314, 75,
-	269, 22, 27, 155, 298, 167, 311, 186, 316, 11,
-	25, 26, 263, 168, 293, 320, 85, 206, 27, 152,
-	12, 147, 331, 75, 75, 163, 163, 3, 141, 332,
-	21, 115, 10, 138, 10, 10, 118, 195, 142, 105,
-	345, 75, 206, 347, 75, 123, 349, 75, 190, 105,
-	105, 163, 346, 10, 270, 348, 116, 9, 350, 9,
-	9, 122, 357, 121, 358, 273, 176, 353, 176, 369,
-	176, 334, 163, 161, 163, 290, 292, 104, 9, 206,
-	206, 340, 342, 102, 375, 75, 162, 227, 163, 163,
-	172, 385, 7, 387, 6, 2, 387, 384, 75, 1,
-	0, 391, 27, 107, 110, 31, 0, 0, 32, 33,
+	31, 124, 8, 406, 8, 8, 116, 117, 169, 75,
+	309, 288, 293, 209, 196, 107, 210, 103, 181, 78,
+	79, 161, 83, 104, 8, 168, 123, 81, 133, 118,
+	155, 195, 102, 142, 105, 145, 391, 358, 346, 331,
+	241, 355, 352, 242, 30, 76, 345, 330, 243, 80,
+	26, 244, 244, 338, 344, 244, 244, 244, 328, 84,
+	347, 304, 87, 88, 276, 275, 401, 212, 244, 342,
+	321, 29, 212, 244, 115, 383, 244, 268, 212, 227,
+	110, 226, 203, 367, 303, 226, 90, 412, 229, 225,
+	398, 101, 109, 225, 396, 151, 146, 266, 393, 162,
+	226, 360, 399, 308, 226, 265, 92, 226, 225, 374,
+	96, 173, 225, 351, 357, 225, 320, 403, 354, 404,
+	89, 249, 157, 379, 186, 156, 213, 90, 153, 250,
+	248, 213, 377, 246, 194, 79, 78, 213, 243, 226,
+	198, 199, 224, 97, 183, 151, 146, 225, 95, 94,
+	223, 93, 165, 375, 366, 361, 86, 341, 335, 188,
+	190, 192, 162, 17, 14, 80, 76, 220, 211, 173,
+	4, 15, 165, 200, 16, 17, 202, 222, 153, 86,
+	205, 157, 218, 17, 156, 215, 86, 202, 409, 234,
+	235, 236, 237, 238, 239, 86, 228, 166, 285, 17,
+	219, 232, 164, 230, 100, 19, 18, 20, 21, 409,
+	216, 183, 96, 206, 13, 187, 167, 166, 25, 365,
+	17, 368, 164, 211, 264, 217, 14, 99, 109, 364,
+	173, 332, 283, 15, 98, 282, 16, 17, 408, 281,
+	280, 410, 290, 85, 279, 269, 278, 247, 294, 240,
+	207, 271, 91, 24, 289, 273, 267, 245, 286, 408,
+	29, 197, 277, 382, 381, 327, 326, 19, 18, 20,
+	21, 109, 76, 173, 173, 299, 13, 325, 291, 306,
+	324, 211, 222, 211, 307, 302, 121, 11, 323, 11,
+	11, 322, 119, 10, 294, 10, 10, 311, 317, 301,
+	336, 337, 5, 315, 197, 334, 23, 284, 305, 11,
+	178, 178, 179, 175, 176, 10, 86, 173, 173, 29,
+	163, 299, 180, 29, 177, 23, 222, 160, 329, 27,
+	28, 3, 340, 109, 22, 12, 154, 147, 144, 343,
+	122, 289, 348, 362, 208, 339, 109, 109, 148, 173,
+	127, 120, 9, 201, 9, 9, 292, 222, 140, 76,
+	126, 376, 296, 125, 378, 363, 353, 380, 356, 295,
+	359, 173, 170, 173, 9, 313, 172, 251, 369, 371,
+	108, 106, 182, 405, 186, 173, 186, 173, 186, 287,
+	7, 6, 2, 222, 394, 222, 384, 1, 386, 0,
+	400, 0, 0, 0, 0, 0, 407, 407, 186, 411,
+	0, 0, 311, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 314, 392, 29, 111, 114, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 0, 0, 0, 0, 110, 0, 0, 0,
+	0, 0, 0, 0, 316, 112, 113, 0, 0, 0,
+	312, 29, 111, 114, 32, 33, 34, 35, 36, 37,
+	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+	68, 69, 70, 71, 72, 73, 74, 0, 0, 0,
+	0, 110, 0, 0, 0, 0, 0, 0, 0, 272,
+	112, 113, 0, 0, 270, 29, 111, 114, 32, 33,
 	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
 	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
 	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
-	0, 0, 0, 0, 106, 0, 0, 0, 0, 0,
-	0, 0, 294, 108, 109, 0, 0, 0, 291, 27,
-	107, 110, 31, 0, 0, 32, 33, 34, 35, 36,
-	37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
-	47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
-	57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
-	67, 68, 69, 70, 71, 72, 73, 0, 0, 0,
-	0, 106, 0, 0, 0, 0, 0, 0, 0, 253,
-	108, 109, 0, 0, 251, 27, 107, 110, 31, 0,
-	0, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
-	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-	61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
-	71, 72, 73, 0, 0, 0, 0, 106, 0, 0,
-	0, 0, 0, 0, 0, 343, 108, 109, 27, 107,
-	110, 31, 0, 0, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 0, 0, 0, 0,
-	106, 0, 0, 0, 0, 0, 0, 0, 341, 108,
-	109, 27, 107, 110, 31, 0, 0, 32, 33, 34,
+	74, 0, 0, 0, 0, 110, 0, 0, 0, 0,
+	0, 0, 0, 372, 112, 113, 29, 111, 114, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 0, 0, 0, 0, 110, 0, 0, 0,
+	0, 0, 171, 0, 370, 112, 113, 32, 33, 34,
 	35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
 	45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
 	55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
-	65, 66, 67, 68, 69, 70, 71, 72, 73, 0,
-	0, 0, 0, 106, 0, 0, 0, 0, 0, 0,
-	0, 31, 108, 109, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 371, 0, 0,
-	0, 31, 0, 164, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 370, 0, 0,
-	0, 31, 0, 164, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 344, 0, 0,
-	0, 31, 0, 164, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 321, 0, 0,
-	0, 31, 0, 164, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 296, 0, 0,
-	0, 31, 0, 164, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 0, 0, 0, 0,
-	0, 205, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 31, 0, 164, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 228, 229, 230, 231,
-	232, 233, 234, 235, 236, 237, 238, 239, 0, 0,
-	0, 31, 30, 164, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 0, 0, 0, 0,
+	65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 76, 31, 30, 81, 32, 33, 34, 35, 36,
-	133, 38, 39, 40, 41, 127, 126, 125, 45, 46,
-	47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
-	57, 58, 59, 60, 134, 135, 132, 64, 65, 136,
-	129, 130, 131, 70, 71, 72, 73, 0, 0, 124,
-	0, 0, 364, 31, 30, 81, 32, 33, 34, 35,
-	36, 133, 38, 39, 40, 41, 127, 126, 125, 45,
-	46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
-	56, 57, 58, 59, 60, 134, 135, 132, 64, 65,
-	136, 129, 130, 131, 70, 71, 72, 73, 0, 0,
-	124, 0, 0, 362, 31, 30, 81, 32, 33, 34,
-	35, 36, 133, 38, 39, 40, 41, 127, 126, 125,
-	45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
-	55, 56, 57, 58, 59, 60, 134, 135, 132, 64,
-	65, 136, 129, 130, 131, 70, 71, 72, 73, 0,
-	0, 124, 0, 0, 360, 31, 30, 81, 32, 33,
-	34, 35, 36, 133, 38, 39, 40, 41, 42, 43,
+	0, 397, 0, 171, 0, 0, 0, 174, 32, 33,
+	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
 	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
 	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
-	0, 0, 274, 0, 0, 309, 31, 30, 81, 32,
-	33, 34, 35, 36, 37, 38, 39, 40, 41, 127,
-	126, 125, 45, 46, 47, 48, 49, 50, 51, 52,
+	74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 395, 0, 171, 0, 0, 0, 174, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
 	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
 	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
-	73, 0, 0, 151, 0, 0, 200, 31, 30, 81,
-	32, 33, 34, 35, 36, 133, 38, 39, 40, 41,
-	127, 126, 125, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 134,
-	135, 132, 64, 65, 136, 129, 130, 131, 70, 71,
-	72, 73, 0, 0, 124, 31, 0, 175, 32, 33,
-	34, 35, 36, 133, 38, 39, 40, 41, 42, 43,
-	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-	64, 65, 145, 67, 68, 69, 70, 71, 72, 73,
-	0, 0, 143, 0, 0, 192, 31, 30, 81, 32,
-	33, 34, 35, 36, 133, 38, 39, 40, 41, 127,
-	126, 125, 45, 46, 47, 48, 49, 50, 51, 52,
-	53, 54, 55, 56, 57, 58, 59, 60, 134, 135,
-	132, 64, 65, 136, 129, 130, 131, 70, 71, 72,
-	73, 0, 0, 124, 31, 30, 81, 32, 33, 34,
-	35, 36, 133, 38, 39, 40, 41, 42, 43, 44,
-	45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
-	55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
-	65, 66, 67, 68, 69, 70, 71, 72, 73, 0,
-	0, 274, 31, 30, 81, 32, 33, 34, 35, 36,
-	37, 38, 39, 40, 41, 127, 126, 125, 45, 46,
+	73, 74, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 373, 0, 0, 0, 0, 0, 174,
+	29, 111, 114, 32, 33, 34, 35, 36, 37, 38,
+	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+	69, 70, 71, 72, 73, 74, 0, 0, 0, 0,
+	110, 0, 0, 0, 0, 0, 171, 0, 0, 112,
+	113, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+	61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+	71, 72, 73, 74, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 350, 0, 171, 0, 0,
+	0, 174, 32, 33, 34, 35, 36, 37, 38, 39,
+	40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+	60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+	70, 71, 72, 73, 74, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 319, 0, 171, 0,
+	0, 0, 174, 32, 33, 34, 35, 36, 37, 38,
+	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+	69, 70, 71, 72, 73, 74, 0, 0, 0, 0,
+	0, 221, 0, 0, 0, 0, 0, 0, 0, 387,
+	0, 0, 0, 174, 32, 33, 34, 35, 36, 37,
+	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+	68, 69, 70, 71, 72, 73, 74, 252, 253, 254,
+	255, 256, 257, 258, 259, 260, 261, 262, 263, 0,
+	385, 0, 0, 0, 174, 32, 33, 34, 35, 36,
+	37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
 	47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
 	57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
-	67, 68, 69, 70, 71, 72, 73, 31, 0, 151,
-	32, 33, 34, 35, 36, 133, 38, 39, 40, 41,
+	67, 68, 69, 70, 71, 72, 73, 74, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 349, 0, 0, 0, 174, 32, 33, 34, 35,
+	36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+	46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+	66, 67, 68, 69, 70, 71, 72, 73, 74, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 318, 0, 0, 0, 174, 32, 33, 34,
+	35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+	45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+	55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+	65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 274, 0, 0, 0, 174, 32, 33,
+	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+	74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 171, 0, 0, 0, 174, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 174,
+	32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
 	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 145, 67, 68, 69, 70, 71,
-	72, 73, 0, 0, 143, 31, 30, 81, 32, 33,
+	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+	72, 73, 74, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 77, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 129, 0, 0, 0, 233, 32, 33,
+	34, 35, 36, 37, 138, 39, 40, 41, 42, 132,
+	131, 130, 46, 47, 48, 49, 50, 51, 52, 53,
+	54, 55, 56, 57, 58, 59, 60, 61, 139, 143,
+	137, 65, 66, 141, 134, 135, 136, 71, 72, 73,
+	74, 0, 0, 128, 0, 0, 402, 129, 0, 0,
+	82, 0, 32, 33, 34, 35, 36, 37, 138, 39,
+	40, 41, 42, 132, 131, 130, 46, 47, 48, 49,
+	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+	60, 61, 139, 143, 137, 65, 66, 141, 134, 135,
+	136, 71, 72, 73, 74, 0, 0, 128, 0, 0,
+	390, 129, 0, 0, 82, 0, 32, 33, 34, 35,
+	36, 37, 138, 39, 40, 41, 42, 132, 131, 130,
+	46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 139, 143, 137, 65,
+	66, 141, 134, 135, 136, 71, 72, 73, 74, 0,
+	0, 128, 0, 0, 389, 129, 0, 0, 82, 0,
+	32, 33, 34, 35, 36, 37, 138, 39, 40, 41,
+	42, 132, 131, 130, 46, 47, 48, 49, 50, 51,
+	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+	139, 143, 137, 65, 66, 141, 134, 135, 136, 71,
+	72, 73, 74, 0, 0, 128, 0, 0, 388, 298,
+	0, 0, 82, 0, 32, 33, 34, 35, 36, 37,
+	138, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+	58, 59, 60, 300, 62, 63, 64, 65, 66, 67,
+	68, 69, 70, 71, 72, 73, 74, 0, 0, 297,
+	0, 0, 333, 159, 0, 0, 82, 0, 32, 33,
+	34, 35, 36, 37, 38, 39, 40, 41, 42, 132,
+	131, 130, 46, 47, 48, 49, 50, 51, 52, 53,
+	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+	74, 0, 0, 158, 0, 0, 214, 129, 0, 0,
+	82, 0, 32, 33, 34, 35, 36, 37, 138, 39,
+	40, 41, 42, 132, 131, 130, 46, 47, 48, 49,
+	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+	60, 61, 139, 143, 137, 65, 66, 141, 134, 135,
+	136, 71, 72, 73, 74, 0, 0, 128, 0, 0,
+	185, 129, 0, 0, 82, 0, 32, 33, 34, 35,
+	36, 37, 138, 39, 40, 41, 42, 132, 131, 130,
+	46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 139, 143, 137, 65,
+	66, 141, 134, 135, 136, 71, 72, 73, 74, 0,
+	0, 128, 0, 0, 298, 0, 0, 0, 82, 32,
+	33, 34, 35, 36, 37, 138, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60, 300, 62,
+	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 0, 0, 297, 0, 0, 159, 0, 0,
+	0, 82, 32, 33, 34, 35, 36, 37, 38, 39,
+	40, 41, 42, 132, 131, 130, 46, 47, 48, 49,
+	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+	60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+	70, 71, 72, 73, 74, 0, 0, 158, 0, 0,
+	231, 0, 0, 0, 82, 32, 33, 34, 35, 36,
+	37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+	47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+	57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+	67, 68, 69, 70, 71, 72, 73, 74, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 82, 32, 33,
 	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
 	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
 	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-	64, 65, 66, 67, 68, 69, 70, 71, 289, 73,
-	31, 30, 81, 32, 33, 34, 35, 36, 37, 38,
+	64, 65, 66, 67, 68, 69, 70, 71, 72, 310,
+	74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	82, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+	61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+	71, 72, 73, 74, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 82, 32, 33, 34, 35, 36, 37,
+	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+	68, 69, 70, 71, 72, 73, 74, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 184, 32, 33, 34,
+	35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+	45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+	55, 56, 57, 58, 59, 60, 193, 62, 63, 64,
+	65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 82,
+	32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+	52, 53, 54, 55, 56, 57, 58, 59, 60, 191,
+	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+	72, 73, 74, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 82, 32, 33, 34, 35, 36, 37, 38,
 	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
 	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 31, 30, 81, 32, 33,
-	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
-	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-	54, 55, 56, 57, 58, 59, 182, 61, 62, 63,
-	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
-	31, 30, 81, 32, 33, 34, 35, 36, 37, 38,
-	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 180, 61, 62, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 31, 30, 81, 32, 33,
-	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
-	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-	54, 55, 56, 57, 58, 59, 178, 61, 62, 63,
-	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
-	31, 30, 0, 32, 33, 34, 35, 36, 37, 38,
-	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 31, 0, 0, 32, 33,
-	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
-	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+	59, 60, 189, 62, 63, 64, 65, 66, 67, 68,
+	69, 70, 71, 72, 73, 74, 0, 0, 0, 0,
+	0, 150, 0, 0, 0, 82, 32, 33, 34, 35,
+	36, 37, 138, 39, 40, 41, 42, 43, 44, 45,
+	46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+	66, 152, 68, 69, 70, 71, 72, 73, 74, 0,
+	150, 149, 0, 0, 204, 32, 33, 34, 35, 36,
+	37, 138, 39, 40, 41, 42, 43, 44, 45, 46,
+	47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+	57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+	152, 68, 69, 70, 71, 72, 73, 74, 0, 0,
+	149, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+	61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+	71, 72, 73, 74,
 }
 var protoPact = [...]int{
 
-	197, -1000, 172, 172, 194, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, -1000, -1000, 288, 1953, 1124, 1998, 1998, 1773,
-	1998, 172, -1000, 304, 186, 304, 304, -1000, 137, -1000,
+	162, -1000, 224, 224, 202, -1000, -1000, -1000, -1000, -1000,
+	-1000, -1000, -1000, -1000, 166, 319, 2584, 1463, 2584, 2584,
+	2224, 2584, 224, -1000, 315, -1000, 191, 315, 315, -1000,
+	68, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
 	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
 	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
 	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, -1000, -1000, 193, -1000, 1773, 77, 76, 75,
-	-1000, -1000, 74, 185, -1000, -1000, 160, 138, -1000, 647,
-	26, 1539, 1680, 1635, 113, -1000, -1000, -1000, 131, -1000,
-	-1000, 302, -1000, -1000, -1000, -1000, 1064, -1000, 277, 249,
-	-1000, 102, 1440, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, -1000, -1000, -1000, 1908, 1863, 1818, 1998, 1998,
-	1998, 1773, 292, 1124, 1998, 38, 252, -1000, 1488, -1000,
-	-1000, -1000, -1000, -1000, 176, 92, -1000, 1389, -1000, -1000,
-	-1000, -1000, 139, -1000, -1000, -1000, -1000, 1998, -1000, 1004,
-	-1000, 63, 45, -1000, 1953, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, 102, -1000, 32, -1000, -1000, 1998, 1998, 1998,
-	1998, 1998, 1998, 171, 9, -1000, 207, 73, 1091, 54,
-	52, 302, -1000, -1000, 81, 50, -1000, 206, 191, 298,
-	-1000, -1000, -1000, -1000, 31, -1000, -1000, -1000, -1000, 455,
-	-1000, 1064, -33, -1000, 1773, 168, 163, 162, 157, 153,
-	152, 297, -1000, 1124, 292, 247, 1587, 43, -1000, -1000,
-	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, 304, 22, 21, 78, -1000, 233, 72, 1728,
-	-1000, 388, -1000, 1064, 944, -1000, 24, 289, 265, 263,
-	260, 254, 248, 20, -2, -1000, 151, -1000, -1000, -1000,
-	1338, -1000, -1000, -1000, -1000, 1998, 1773, 302, -1000, 1124,
-	-1000, 1124, -1000, -1000, -1000, -1000, -1000, -1000, 12, 1773,
-	-1000, -1000, -14, -1000, 1064, 884, -1000, -1000, 19, 70,
-	18, 68, 15, 51, -1000, 1124, 1124, 130, 647, -1000,
-	-1000, 144, 40, -4, -5, 174, -1000, -1000, 584, 521,
-	824, -1000, -1000, 1124, 1539, -1000, 1124, 1539, -1000, 1124,
-	1539, -8, -1000, -1000, -1000, 245, 1998, 123, 114, 14,
-	-1000, 1064, -1000, 1064, -1000, -9, 1287, -11, 1236, -15,
-	1185, 107, 13, 93, -1000, -1000, 1728, 764, 704, 103,
-	-1000, 98, -1000, 94, -1000, -1000, -1000, 1124, 208, 2,
-	-1000, -1000, -1000, -1000, -1000, -20, 10, 64, 91, -1000,
-	1124, -1000, 122, -1000, -26, 180, -1000, -1000, -1000, 89,
+	-1000, -1000, -1000, -1000, -1000, 201, 27, 2224, 97, 95,
+	94, 27, 2584, 89, 182, -1000, -1000, 175, 152, -1000,
+	2584, 856, 8, 1959, 2538, 2065, 27, 150, -1000, -1000,
+	-1000, -1000, 164, -1000, -1000, 312, -1000, -1000, -1000, -1000,
+	1402, -1000, 308, 306, -1000, 2277, 1905, -1000, -1000, -1000,
+	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 163,
+	2436, 2383, 2330, 2584, 2584, 2584, 2224, 299, 1463, 2584,
+	2584, 256, -1000, 20, 2489, -1000, -1000, -1000, -1000, -1000,
+	161, 199, 67, -1000, 1851, -1000, -1000, -1000, -1000, 158,
+	170, -1000, -1000, -1000, -1000, 148, 2584, -1000, 1036, -1000,
+	90, 87, 26, -1000, 2118, -1000, -1000, -1000, -1000, -1000,
+	-1000, -1000, 2277, -1000, 1522, -1000, -1000, -1000, 2584, 2584,
+	2584, 2584, 2584, 2584, 198, -12, -1000, 217, 79, 196,
+	78, 69, 312, 1124, -1000, -1000, -1000, 73, 45, -1000,
+	216, -1000, -1000, 305, -1000, -1000, -1000, -1000, -1000, -1000,
+	12, -1000, -1000, -1000, -1000, -1000, -1000, 487, -1000, 1341,
+	-3, -4, -1000, 2224, 195, 193, 189, 188, 184, 181,
+	302, -1000, 146, 299, 1463, 237, 2012, 294, -1000, -1000,
+	315, 24, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+	-1000, -1000, -1000, -1000, 9, 73, -1000, 62, 2171, -1000,
+	422, -1000, 1280, 975, 55, -1000, -1000, 4, 286, 283,
+	275, 272, 261, 260, 6, -1000, -1000, -21, -1000, 180,
+	-1000, -1000, 1797, -1000, -1000, -1000, -1000, -1000, 106, 2584,
+	2584, 1, 312, 2224, -1000, 105, -1000, -1000, -1000, 3,
+	2224, -1000, -1000, -14, -8, -1000, 1219, 914, 52, -1000,
+	-1000, -1000, -10, 64, -11, 60, -15, 47, -1000, 103,
+	-1000, 1463, 856, -1000, -1000, -1000, 178, 168, -1000, 102,
+	22, -1000, 172, -1000, -1000, 612, 551, -1000, 792, 48,
+	-1000, -1000, -1000, 101, 1959, -1000, 80, 1959, -1000, 71,
+	1959, -1000, -1000, -1000, 259, 258, -1000, -1000, 10, -1000,
+	1158, -1000, 1097, -1000, -1000, -1000, 1743, -1000, 1689, -1000,
+	1635, -16, 44, 2171, 731, 33, 670, 29, -1000, -1000,
+	-1000, -1000, 50, 1959, 0, -1000, -1000, -1000, -1000, -1000,
+	1581, 65, -1000, -1000, 207, 186, -1000, -1000, -1000, 35,
 	-1000, -1000, -1000,
 }
 var protoPgo = [...]int{
 
-	0, 389, 385, 269, 317, 384, 382, 0, 12, 6,
-	5, 381, 32, 21, 380, 52, 26, 18, 20, 7,
-	8, 377, 376, 14, 373, 367, 366, 10, 11, 363,
-	27, 355, 353, 25, 351, 346, 9, 17, 13, 344,
-	338, 335, 328, 30, 16, 33, 15, 327, 326, 321,
-	35, 323, 318, 277, 31, 311, 19, 310, 29, 309,
-	293, 2,
+	0, 397, 392, 302, 331, 391, 390, 1, 11, 389,
+	3, 383, 9, 18, 382, 43, 32, 17, 23, 381,
+	380, 16, 15, 0, 377, 27, 28, 376, 375, 25,
+	8, 372, 29, 369, 363, 26, 362, 360, 358, 351,
+	7, 6, 12, 356, 353, 350, 348, 33, 14, 31,
+	13, 344, 340, 292, 35, 338, 337, 286, 30, 336,
+	34, 335, 21, 327, 320, 10,
 }
 var protoR1 = [...]int{
 
 	0, 1, 1, 1, 1, 4, 4, 3, 3, 3,
-	3, 3, 3, 3, 3, 2, 5, 5, 5, 6,
-	19, 19, 7, 12, 12, 12, 13, 13, 14, 14,
-	15, 15, 16, 16, 16, 16, 16, 24, 24, 23,
-	25, 25, 25, 25, 25, 56, 56, 17, 27, 27,
-	27, 28, 28, 28, 29, 29, 29, 29, 29, 29,
-	29, 22, 22, 26, 26, 26, 26, 26, 26, 20,
-	20, 30, 30, 30, 30, 30, 30, 30, 30, 9,
-	9, 8, 33, 33, 33, 32, 39, 39, 39, 38,
-	38, 38, 31, 31, 34, 34, 21, 21, 21, 21,
-	21, 21, 21, 21, 21, 21, 21, 21, 48, 48,
-	45, 45, 44, 44, 44, 47, 47, 46, 46, 46,
-	46, 46, 46, 46, 41, 41, 42, 42, 43, 40,
-	40, 49, 51, 51, 51, 50, 50, 50, 50, 52,
-	52, 52, 52, 35, 37, 37, 37, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 36, 53, 55,
-	55, 55, 54, 54, 54, 57, 59, 59, 59, 58,
-	58, 58, 60, 60, 61, 61, 11, 11, 11, 10,
-	10, 18, 18, 18, 18, 18, 18, 18, 18, 18,
-	18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
-	18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
-	18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
-	18, 18, 18, 18,
+	3, 3, 3, 3, 3, 3, 3, 2, 5, 5,
+	5, 6, 25, 25, 7, 12, 12, 12, 13, 13,
+	14, 14, 16, 16, 17, 17, 17, 17, 17, 19,
+	19, 22, 21, 21, 20, 20, 20, 20, 20, 60,
+	60, 18, 29, 29, 29, 30, 30, 30, 30, 30,
+	30, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+	31, 27, 27, 27, 28, 28, 28, 28, 28, 28,
+	28, 28, 28, 26, 26, 32, 32, 32, 32, 32,
+	32, 32, 32, 15, 9, 9, 8, 35, 35, 35,
+	34, 43, 43, 43, 42, 42, 42, 42, 42, 42,
+	33, 33, 36, 37, 37, 38, 24, 24, 24, 24,
+	24, 24, 24, 24, 24, 24, 24, 24, 52, 52,
+	49, 49, 48, 48, 48, 51, 51, 50, 50, 50,
+	45, 45, 46, 46, 47, 44, 44, 53, 55, 55,
+	55, 54, 54, 54, 54, 54, 54, 56, 56, 39,
+	41, 41, 41, 40, 40, 40, 40, 40, 40, 40,
+	40, 40, 40, 40, 40, 40, 57, 59, 59, 59,
+	58, 58, 58, 58, 58, 61, 63, 63, 63, 62,
+	62, 62, 62, 62, 64, 64, 65, 65, 11, 11,
+	11, 10, 10, 10, 10, 23, 23, 23, 23, 23,
+	23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	23, 23, 23, 23, 23, 23, 23, 23,
 }
 var protoR2 = [...]int{
 
 	0, 1, 1, 2, 0, 2, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 4, 3, 4, 4, 3,
-	1, 1, 5, 1, 3, 4, 1, 2, 1, 4,
-	1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
-	1, 2, 2, 2, 2, 1, 2, 3, 1, 2,
-	0, 1, 2, 2, 3, 4, 5, 3, 2, 5,
-	4, 1, 3, 1, 3, 3, 3, 5, 5, 1,
-	1, 6, 6, 6, 5, 9, 9, 9, 8, 3,
-	1, 3, 8, 8, 8, 5, 2, 1, 0, 1,
-	1, 1, 5, 8, 10, 13, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1, 3, 6,
-	3, 1, 1, 3, 3, 3, 1, 1, 1, 3,
-	3, 3, 3, 3, 3, 1, 3, 1, 3, 3,
-	1, 5, 2, 1, 0, 1, 1, 1, 1, 4,
-	7, 4, 7, 5, 2, 1, 0, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1, 5, 2,
-	1, 0, 1, 1, 1, 5, 2, 1, 0, 1,
-	1, 1, 10, 12, 2, 1, 2, 1, 0, 1,
+	1, 1, 1, 1, 1, 2, 1, 4, 3, 4,
+	4, 3, 1, 3, 5, 1, 3, 4, 1, 2,
+	1, 4, 1, 1, 1, 1, 1, 1, 1, 1,
+	2, 2, 1, 1, 1, 2, 2, 2, 2, 1,
+	2, 3, 1, 2, 0, 1, 2, 2, 2, 2,
+	1, 3, 4, 5, 5, 3, 2, 5, 4, 5,
+	4, 1, 3, 3, 1, 3, 3, 3, 5, 5,
+	3, 5, 5, 1, 2, 6, 6, 6, 5, 7,
+	7, 7, 6, 3, 3, 1, 3, 8, 8, 8,
+	5, 2, 1, 0, 1, 1, 1, 1, 2, 1,
+	5, 6, 7, 5, 6, 6, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 3, 4,
+	3, 1, 1, 3, 3, 3, 1, 1, 3, 3,
+	3, 1, 3, 1, 3, 3, 1, 5, 2, 1,
+	0, 1, 1, 1, 1, 2, 1, 4, 5, 5,
+	2, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 2, 1, 5, 2, 1, 0,
+	1, 1, 1, 2, 1, 5, 2, 1, 0, 1,
+	1, 1, 2, 1, 10, 12, 2, 1, 2, 1,
+	0, 1, 1, 2, 1, 1, 1, 1, 1, 1,
 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
 }
 var protoChk = [...]int{
 
-	-1000, -1, -2, -4, 10, -3, -5, -6, -7, -35,
-	-49, -53, -57, 54, 11, 14, 15, 46, 45, 47,
-	48, -4, -3, 53, -56, 12, 13, 4, -19, -18,
-	8, 7, 10, 11, 12, 13, 14, 15, 16, 17,
-	18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
-	28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, -12, -19, 67, -18, -18, -20,
-	-19, 9, -18, -56, 54, 4, -56, -56, 54, 53,
-	-20, 56, 56, 56, 56, 54, 54, 54, -15, -16,
-	-17, -56, -24, -23, -25, -18, 56, 5, 65, 66,
-	6, 68, -37, -36, -30, -49, -35, -53, -48, -33,
-	-7, -32, -34, -41, 54, 22, 21, 20, -20, 45,
-	46, 47, 41, 15, 39, 40, 44, -43, -51, -50,
-	-7, -52, -42, 54, -18, 44, -43, -55, -54, -30,
-	-33, 54, -59, -58, -7, -60, 54, 49, 54, -27,
-	-28, -29, -22, -18, 69, 5, 6, 18, 5, 6,
-	18, -13, -14, 9, 61, 57, -36, -20, 38, -20,
-	38, -20, 38, -18, -45, -44, 5, -18, 64, -45,
-	-40, -56, 57, -50, 53, -47, -46, 5, -23, 66,
-	57, -54, 57, -58, -18, 57, -28, 62, 54, 55,
-	-17, 64, -19, -13, 67, -18, -18, -18, -18, -18,
-	-18, 53, 54, 69, 62, 42, 56, -21, 25, 26,
-	27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
-	54, 54, 62, 5, -23, 62, 54, 42, 42, 67,
-	-16, 69, -17, 64, -27, 70, -20, 53, 53, 53,
-	53, 53, 53, 5, -9, -8, -12, -44, 5, 43,
-	-39, -38, -7, -31, 54, -20, 62, -56, 54, 69,
-	54, 69, -46, 5, 43, -23, 5, 43, -61, 50,
-	-20, 70, -26, -15, 64, -27, 63, 68, 5, 5,
-	5, 5, 5, 5, 54, 69, 62, 70, 53, 57,
-	-38, -18, -20, -9, -9, 68, -20, 70, 62, 54,
-	-27, 63, 54, 69, 56, 54, 69, 56, 54, 69,
-	56, -9, -8, 54, -15, 53, 63, 70, 70, 51,
-	-15, 64, -15, 64, 63, -9, -37, -9, -37, -9,
-	-37, 70, 5, -18, 54, 54, 67, -27, -27, 70,
-	57, 70, 57, 70, 57, 54, 54, 69, 53, -61,
-	63, 63, 54, 54, 54, -9, 5, 68, 70, 54,
-	69, 54, 56, 54, -9, -11, -10, -7, 54, 70,
-	57, -10, 54,
+	-1000, -1, -2, -4, 8, -3, -5, -6, -7, -39,
+	-53, -57, -61, 52, 2, 9, 12, 13, 44, 43,
+	45, 46, -4, -3, 51, 52, -60, 10, 11, 4,
+	-25, -23, 7, 8, 9, 10, 11, 12, 13, 14,
+	15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+	25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+	35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+	45, 46, 47, 48, 49, -12, -25, 65, -23, -23,
+	-26, -25, 59, -23, -60, 52, 4, -60, -60, 52,
+	59, 51, -26, 54, 54, 54, -25, 54, 52, 52,
+	52, -23, -16, -17, -18, -60, -19, -22, -20, -23,
+	54, 5, 63, 64, 6, 66, -41, -40, -32, -53,
+	-39, -57, -52, -35, -7, -34, -37, -45, 52, 2,
+	20, 19, 18, -26, 43, 44, 45, 39, 13, 37,
+	-38, 42, -47, 38, -55, -54, -7, -56, -46, 52,
+	2, -23, 42, -47, -59, -58, -32, -35, 52, 2,
+	-63, -62, -7, -64, 52, 2, 47, 52, -29, -30,
+	-31, 2, -27, -23, 67, 5, 6, 16, 5, 6,
+	16, -13, -14, -26, 59, 55, -40, 52, -26, 36,
+	-26, 36, -26, 36, -23, -49, -48, 5, -23, -23,
+	-49, -44, -60, 62, 55, -54, 52, 51, -51, -50,
+	-21, -22, 5, 64, 55, -58, 52, 55, -62, 52,
+	-23, 55, -30, 60, 52, 60, 52, 53, -18, 62,
+	-26, 2, -13, 65, -23, -23, -23, -23, -23, -23,
+	51, 52, -15, 60, 67, 40, 54, 51, 52, 52,
+	60, -24, 23, 24, 25, 26, 27, 28, 29, 30,
+	31, 32, 33, 34, -21, 60, 52, 40, 65, -17,
+	67, -18, 62, -29, 2, 68, 68, -26, 51, 51,
+	51, 51, 51, 51, 5, 52, -48, -9, -8, -12,
+	5, 41, -43, -42, -7, -33, -36, 52, 2, -26,
+	36, 5, -60, 60, 52, -15, -50, -21, 41, -65,
+	48, -26, 68, -28, 2, -16, 62, -29, 2, 61,
+	61, 66, 5, 5, 5, 5, 5, 5, 52, -15,
+	68, 60, 51, 55, -42, 52, -23, -23, 52, -15,
+	-26, 52, 66, -26, 68, 60, 52, 68, -29, 2,
+	61, 61, 52, -15, 54, 52, -15, 54, 52, -15,
+	54, 52, -8, -16, 51, 51, 52, 61, 49, -16,
+	62, -16, 62, 61, 61, 52, -41, 52, -41, 52,
+	-41, 5, 5, 65, -29, 2, -29, 2, 55, 55,
+	55, 52, -15, 54, -65, 61, 61, 61, 61, 52,
+	-41, 66, 55, 52, 54, -11, -10, -7, 52, 2,
+	55, -10, 52,
 }
 var protoDef = [...]int{
 
-	4, -2, 1, 2, 0, 6, 7, 8, 9, 10,
-	11, 12, 13, 14, 0, 0, 0, 0, 0, 0,
-	0, 3, 5, 0, 0, 0, 0, 45, 0, 20,
-	21, 181, 182, 183, 184, 185, 186, 187, 188, 189,
-	190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
-	200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
-	210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
-	220, 221, 222, 223, 0, 23, 0, 0, 0, 0,
-	69, 70, 0, 0, 16, 46, 0, 0, 19, 0,
-	0, 146, 134, 161, 168, 15, 17, 18, 0, 30,
-	31, 32, 33, 34, 35, 36, 50, 37, 0, 0,
-	40, 24, 0, 145, 147, 148, 149, 150, 151, 152,
-	153, 154, 155, 156, 157, 0, 0, 0, 0, 0,
-	0, 0, 213, 187, 0, 212, 216, 125, 0, 133,
-	135, 136, 137, 138, 0, 216, 127, 0, 160, 162,
-	163, 164, 0, 167, 169, 170, 171, 0, 22, 0,
-	48, 51, 0, 61, 0, 38, 42, 43, 39, 41,
-	44, 25, 26, 28, 0, 143, 144, 0, 0, 0,
-	0, 0, 0, 0, 0, 111, 112, 0, 0, 0,
-	0, 130, 131, 132, 0, 0, 116, 117, 118, 0,
-	158, 159, 165, 166, 0, 47, 49, 52, 53, 0,
-	58, 50, 0, 27, 0, 0, 0, 0, 0, 0,
-	0, 0, 108, 0, 0, 0, 88, 0, 96, 97,
-	98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
-	124, 128, 0, 0, 0, 0, 126, 0, 0, 0,
-	54, 0, 57, 50, 0, 62, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 80, 0, 110, 113, 114,
-	0, 87, 89, 90, 91, 0, 0, 129, 139, 0,
-	141, 0, 115, 119, 122, 120, 121, 123, 0, 222,
-	175, 55, 0, 63, 50, 0, 60, 29, 0, 0,
-	0, 0, 0, 0, 74, 0, 0, 0, 0, 85,
-	86, 0, 0, 0, 0, 0, 174, 56, 0, 0,
-	0, 59, 71, 0, 146, 72, 0, 146, 73, 0,
-	146, 0, 79, 109, 81, 0, 0, 0, 0, 0,
-	64, 50, 65, 50, 66, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 140, 142, 0, 0, 0, 0,
-	82, 0, 83, 0, 84, 78, 92, 0, 0, 0,
-	67, 68, 75, 76, 77, 0, 0, 0, 0, 94,
-	0, 172, 178, 93, 0, 0, 177, 179, 180, 0,
-	173, 176, 95,
+	-2, -2, -2, -2, 0, 6, 7, 8, 9, 10,
+	11, 12, 13, 14, 16, 0, 0, 0, 0, 0,
+	0, 0, -2, 5, 0, 15, 0, 0, 0, 49,
+	0, 22, 205, 206, 207, 208, 209, 210, 211, 212,
+	213, 214, 215, 216, 217, 218, 219, 220, 221, 222,
+	223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
+	233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
+	243, 244, 245, 246, 247, 0, 25, 0, 0, 0,
+	0, 83, 0, 0, 0, 18, 50, 0, 0, 21,
+	0, 0, 0, -2, -2, -2, 84, -2, 17, 19,
+	20, 23, 0, 32, 33, 34, 35, 36, 37, 38,
+	-2, 39, 0, 0, 44, 26, 0, 161, 163, 164,
+	165, 166, 167, 168, 169, 170, 171, 172, 173, 175,
+	0, 0, 0, 0, 241, 242, 0, 237, 211, 235,
+	0, 240, 141, 236, 0, 149, 151, 152, 153, 154,
+	156, 0, 240, 143, 0, 178, 180, 181, 182, 184,
+	0, 187, 189, 190, 191, 193, 0, 24, 0, 52,
+	55, 60, 0, 71, 0, 40, 46, 47, 41, 45,
+	48, 27, 28, 30, 0, 159, 160, 174, 0, 234,
+	0, 234, 0, 234, 0, 0, 131, 132, 0, 0,
+	0, 0, 146, 0, 147, 148, 155, 0, 0, 136,
+	137, 42, 43, 0, 176, 177, 183, 185, 186, 192,
+	0, 51, 53, 56, 57, 58, 59, 0, 66, -2,
+	0, 0, 29, 0, 0, 0, 0, 0, 0, 0,
+	0, 128, 0, 0, 0, 0, -2, 0, 140, 144,
+	0, 0, 116, 117, 118, 119, 120, 121, 122, 123,
+	124, 125, 126, 127, 0, 0, 142, 0, 0, 61,
+	0, 65, -2, 0, 60, 72, 73, 0, 0, 0,
+	0, 0, 0, 0, 0, 129, 130, 0, 95, 0,
+	133, 134, 0, 102, 104, 105, 106, 107, 109, 0,
+	234, 0, 145, 0, 157, 0, 135, 138, 139, 0,
+	246, 197, 62, 0, 0, 74, -2, 0, 60, 68,
+	70, 31, 0, 0, 0, 0, 0, 0, 88, 0,
+	93, 0, 0, 100, 101, 108, 0, 0, 113, 0,
+	0, 158, 0, 196, 63, 0, 0, 64, 0, 60,
+	67, 69, 85, 0, -2, 86, 0, -2, 87, 0,
+	-2, 92, 94, 96, 0, 0, 114, 115, 0, 75,
+	-2, 76, -2, 77, 80, 89, 0, 90, 0, 91,
+	0, 0, 0, 0, 0, 60, 0, 60, 97, 98,
+	99, 110, 0, -2, 0, 78, 81, 79, 82, 111,
+	0, 0, 112, 194, -2, 0, 199, 201, 202, 204,
+	195, 198, 203,
 }
 var protoTok1 = [...]int{
 
 	1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 78, 3, 76, 75, 74, 72, 3,
-	67, 68, 71, 65, 62, 66, 61, 59, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 55, 54,
-	64, 53, 63, 60, 77, 3, 3, 3, 3, 3,
+	3, 3, 3, 76, 3, 74, 73, 72, 70, 3,
+	65, 66, 69, 63, 60, 64, 59, 57, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 53, 52,
+	62, 51, 61, 58, 75, 3, 3, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 69, 58, 70, 73, 3, 80, 3, 3, 3,
+	3, 67, 56, 68, 71, 3, 78, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 56, 3, 57, 79,
+	3, 3, 3, 54, 3, 55, 77,
 }
 var protoTok2 = [...]int{
 
@@ -632,8 +761,7 @@
 	12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
 	22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52,
+	42, 43, 44, 45, 46, 47, 48, 49, 50,
 }
 var protoTok3 = [...]int{
 	0,
@@ -978,7 +1106,7 @@
 
 	case 1:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:114
+//line proto.y:119
 		{
 			protoVAL.file = &fileNode{syntax: protoDollar[1].syn}
 			protoVAL.file.setRange(protoDollar[1].syn, protoDollar[1].syn)
@@ -986,7 +1114,7 @@
 		}
 	case 2:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:119
+//line proto.y:124
 		{
 			protoVAL.file = &fileNode{decls: protoDollar[1].fileDecls}
 			if len(protoDollar[1].fileDecls) > 0 {
@@ -996,7 +1124,7 @@
 		}
 	case 3:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:126
+//line proto.y:131
 		{
 			protoVAL.file = &fileNode{syntax: protoDollar[1].syn, decls: protoDollar[2].fileDecls}
 			var end node
@@ -1010,66 +1138,76 @@
 		}
 	case 4:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:137
+//line proto.y:142
 		{
 		}
 	case 5:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:140
+//line proto.y:145
 		{
 			protoVAL.fileDecls = append(protoDollar[1].fileDecls, protoDollar[2].fileDecls...)
 		}
 	case 7:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:145
+//line proto.y:150
 		{
 			protoVAL.fileDecls = []*fileElement{{imp: protoDollar[1].imprt}}
 		}
 	case 8:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:148
+//line proto.y:153
 		{
 			protoVAL.fileDecls = []*fileElement{{pkg: protoDollar[1].pkg}}
 		}
 	case 9:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:151
+//line proto.y:156
 		{
 			protoVAL.fileDecls = []*fileElement{{option: protoDollar[1].opts[0]}}
 		}
 	case 10:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:154
+//line proto.y:159
 		{
 			protoVAL.fileDecls = []*fileElement{{message: protoDollar[1].msg}}
 		}
 	case 11:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:157
+//line proto.y:162
 		{
 			protoVAL.fileDecls = []*fileElement{{enum: protoDollar[1].en}}
 		}
 	case 12:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:160
+//line proto.y:165
 		{
 			protoVAL.fileDecls = []*fileElement{{extend: protoDollar[1].extend}}
 		}
 	case 13:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:163
+//line proto.y:168
 		{
 			protoVAL.fileDecls = []*fileElement{{service: protoDollar[1].svc}}
 		}
 	case 14:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:166
+//line proto.y:171
 		{
 			protoVAL.fileDecls = []*fileElement{{empty: protoDollar[1].b}}
 		}
 	case 15:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:174
+		{
+		}
+	case 16:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:176
+		{
+		}
+	case 17:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:170
+//line proto.y:179
 		{
 			if protoDollar[3].str.val != "proto2" && protoDollar[3].str.val != "proto3" {
 				lexError(protolex, protoDollar[3].str.start(), "syntax value must be 'proto2' or 'proto3'")
@@ -1077,37 +1215,51 @@
 			protoVAL.syn = &syntaxNode{syntax: protoDollar[3].str}
 			protoVAL.syn.setRange(protoDollar[1].id, protoDollar[4].b)
 		}
-	case 16:
+	case 18:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:178
+//line proto.y:187
 		{
 			protoVAL.imprt = &importNode{name: protoDollar[2].str}
 			protoVAL.imprt.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
-	case 17:
+	case 19:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:182
+//line proto.y:191
 		{
 			protoVAL.imprt = &importNode{name: protoDollar[3].str, weak: true}
 			protoVAL.imprt.setRange(protoDollar[1].id, protoDollar[4].b)
 		}
-	case 18:
+	case 20:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:186
+//line proto.y:195
 		{
 			protoVAL.imprt = &importNode{name: protoDollar[3].str, public: true}
 			protoVAL.imprt.setRange(protoDollar[1].id, protoDollar[4].b)
 		}
-	case 19:
+	case 21:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:191
+//line proto.y:200
 		{
-			protoVAL.pkg = &packageNode{name: protoDollar[2].id}
+			protoVAL.pkg = &packageNode{name: protoDollar[2].cid}
 			protoVAL.pkg.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
 	case 22:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:205
+		{
+			protoVAL.cid = &compoundIdentNode{val: protoDollar[1].id.val}
+			protoVAL.cid.setRange(protoDollar[1].id, protoDollar[1].id)
+		}
+	case 23:
+		protoDollar = protoS[protopt-3 : protopt+1]
+//line proto.y:209
+		{
+			protoVAL.cid = &compoundIdentNode{val: protoDollar[1].cid.val + "." + protoDollar[3].id.val}
+			protoVAL.cid.setRange(protoDollar[1].cid, protoDollar[3].id)
+		}
+	case 24:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:199
+//line proto.y:214
 		{
 			n := &optionNameNode{parts: protoDollar[2].optNm}
 			n.setRange(protoDollar[2].optNm[0], protoDollar[2].optNm[len(protoDollar[2].optNm)-1])
@@ -1115,188 +1267,229 @@
 			o.setRange(protoDollar[1].id, protoDollar[5].b)
 			protoVAL.opts = []*optionNode{o}
 		}
-	case 23:
+	case 25:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:207
+//line proto.y:222
 		{
-			protoVAL.optNm = toNameParts(protoDollar[1].id, 0)
+			protoVAL.optNm = toNameParts(protoDollar[1].cid, 0)
 		}
-	case 24:
+	case 26:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:210
+//line proto.y:225
 		{
-			p := &optionNamePartNode{text: protoDollar[2].id, isExtension: true}
+			p := &optionNamePartNode{text: protoDollar[2].cid, isExtension: true}
 			p.setRange(protoDollar[1].b, protoDollar[3].b)
 			protoVAL.optNm = []*optionNamePartNode{p}
 		}
-	case 25:
+	case 27:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:215
+//line proto.y:230
 		{
-			p := &optionNamePartNode{text: protoDollar[2].id, isExtension: true}
+			p := &optionNamePartNode{text: protoDollar[2].cid, isExtension: true}
 			p.setRange(protoDollar[1].b, protoDollar[3].b)
 			ps := make([]*optionNamePartNode, 1, len(protoDollar[4].optNm)+1)
 			ps[0] = p
 			protoVAL.optNm = append(ps, protoDollar[4].optNm...)
 		}
-	case 27:
+	case 29:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:224
+//line proto.y:239
 		{
 			protoVAL.optNm = append(protoDollar[1].optNm, protoDollar[2].optNm...)
 		}
-	case 28:
-		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:228
-		{
-			protoVAL.optNm = toNameParts(protoDollar[1].id, 1 /* exclude leading dot */)
-		}
-	case 29:
-		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:231
-		{
-			p := &optionNamePartNode{text: protoDollar[3].id, isExtension: true}
-			p.setRange(protoDollar[2].b, protoDollar[4].b)
-			protoVAL.optNm = []*optionNamePartNode{p}
-		}
-	case 32:
-		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:240
-		{
-			protoVAL.v = protoDollar[1].str
-		}
-	case 33:
+	case 30:
 		protoDollar = protoS[protopt-1 : protopt+1]
 //line proto.y:243
 		{
-			protoVAL.v = protoDollar[1].ui
+			protoVAL.optNm = toNameParts(protoDollar[1].cid, 1 /* exclude leading dot */)
+		}
+	case 31:
+		protoDollar = protoS[protopt-4 : protopt+1]
+//line proto.y:246
+		{
+			p := &optionNamePartNode{text: protoDollar[3].cid, isExtension: true}
+			p.setRange(protoDollar[2].b, protoDollar[4].b)
+			protoVAL.optNm = []*optionNamePartNode{p}
 		}
 	case 34:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:246
+//line proto.y:255
 		{
-			protoVAL.v = protoDollar[1].i
-		}
-	case 35:
-		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:249
-		{
-			protoVAL.v = protoDollar[1].f
+			protoVAL.v = protoDollar[1].str
 		}
 	case 36:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:252
+//line proto.y:259
+		{
+			protoVAL.v = protoDollar[1].il
+		}
+	case 38:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:263
 		{
 			if protoDollar[1].id.val == "true" {
-				protoVAL.v = &boolLiteralNode{basicNode: protoDollar[1].id.basicNode, val: true}
+				protoVAL.v = &boolLiteralNode{identNode: protoDollar[1].id, val: true}
 			} else if protoDollar[1].id.val == "false" {
-				protoVAL.v = &boolLiteralNode{basicNode: protoDollar[1].id.basicNode, val: false}
+				protoVAL.v = &boolLiteralNode{identNode: protoDollar[1].id, val: false}
 			} else if protoDollar[1].id.val == "inf" {
-				f := &floatLiteralNode{val: math.Inf(1)}
+				f := &compoundFloatNode{val: math.Inf(1)}
 				f.setRange(protoDollar[1].id, protoDollar[1].id)
 				protoVAL.v = f
 			} else if protoDollar[1].id.val == "nan" {
-				f := &floatLiteralNode{val: math.NaN()}
+				f := &compoundFloatNode{val: math.NaN()}
 				f.setRange(protoDollar[1].id, protoDollar[1].id)
 				protoVAL.v = f
 			} else {
 				protoVAL.v = protoDollar[1].id
 			}
 		}
-	case 38:
-		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:271
-		{
-			protoVAL.ui = protoDollar[2].ui
-		}
 	case 39:
-		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:275
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:281
 		{
-			if protoDollar[2].ui.val > math.MaxInt64+1 {
-				lexError(protolex, protoDollar[2].ui.start(), fmt.Sprintf("numeric constant %d would underflow (allowed range is %d to %d)", protoDollar[2].ui.val, int64(math.MinInt64), int64(math.MaxInt64)))
-			}
-			protoVAL.i = &negativeIntLiteralNode{val: -int64(protoDollar[2].ui.val)}
-			protoVAL.i.setRange(protoDollar[1].b, protoDollar[2].ui)
+			i := &compoundUintNode{val: protoDollar[1].i.val}
+			i.setRange(protoDollar[1].i, protoDollar[1].i)
+			protoVAL.v = i
+		}
+	case 40:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:286
+		{
+			i := &compoundUintNode{val: protoDollar[2].i.val}
+			i.setRange(protoDollar[1].b, protoDollar[2].i)
+			protoVAL.v = i
 		}
 	case 41:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:284
-		{
-			protoVAL.f = &floatLiteralNode{val: -protoDollar[2].f.val}
-			protoVAL.f.setRange(protoDollar[1].b, protoDollar[2].f)
-		}
-	case 42:
-		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:288
-		{
-			protoVAL.f = &floatLiteralNode{val: protoDollar[2].f.val}
-			protoVAL.f.setRange(protoDollar[1].b, protoDollar[2].f)
-		}
-	case 43:
-		protoDollar = protoS[protopt-2 : protopt+1]
 //line proto.y:292
 		{
-			protoVAL.f = &floatLiteralNode{val: math.Inf(1)}
-			protoVAL.f.setRange(protoDollar[1].b, protoDollar[2].id)
+			if protoDollar[2].i.val > math.MaxInt64+1 {
+				lexError(protolex, protoDollar[2].i.start(), fmt.Sprintf("numeric constant %d would underflow (allowed range is %d to %d)", protoDollar[2].i.val, int64(math.MinInt64), int64(math.MaxInt64)))
+			}
+			i := &compoundIntNode{val: -int64(protoDollar[2].i.val)}
+			i.setRange(protoDollar[1].b, protoDollar[2].i)
+			protoVAL.il = i
+		}
+	case 43:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:302
+		{
+			// we don't allow uintLit because this is for enum numeric vals, which don't allow '+'
+			checkUint64InInt32Range(protolex, protoDollar[1].i.start(), protoDollar[1].i.val)
+			i := &compoundIntNode{val: int64(protoDollar[1].i.val)}
+			i.setRange(protoDollar[1].i, protoDollar[1].i)
+			protoVAL.il = i
 		}
 	case 44:
-		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:296
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:310
 		{
-			protoVAL.f = &floatLiteralNode{val: math.Inf(-1)}
-			protoVAL.f.setRange(protoDollar[1].b, protoDollar[2].id)
+			protoVAL.v = protoDollar[1].f
+		}
+	case 45:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:313
+		{
+			f := &compoundFloatNode{val: -protoDollar[2].f.val}
+			f.setRange(protoDollar[1].b, protoDollar[2].f)
+			protoVAL.v = f
 		}
 	case 46:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:302
+//line proto.y:318
 		{
-			protoVAL.str = &stringLiteralNode{val: protoDollar[1].str.val + protoDollar[2].str.val}
-			protoVAL.str.setRange(protoDollar[1].str, protoDollar[2].str)
+			f := &compoundFloatNode{val: protoDollar[2].f.val}
+			f.setRange(protoDollar[1].b, protoDollar[2].f)
+			protoVAL.v = f
 		}
 	case 47:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:323
+		{
+			f := &compoundFloatNode{val: math.Inf(1)}
+			f.setRange(protoDollar[1].b, protoDollar[2].id)
+			protoVAL.v = f
+		}
+	case 48:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:328
+		{
+			f := &compoundFloatNode{val: math.Inf(-1)}
+			f.setRange(protoDollar[1].b, protoDollar[2].id)
+			protoVAL.v = f
+		}
+	case 49:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:334
+		{
+			protoVAL.str = &compoundStringNode{val: protoDollar[1].s.val}
+			protoVAL.str.setRange(protoDollar[1].s, protoDollar[1].s)
+		}
+	case 50:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:338
+		{
+			protoVAL.str = &compoundStringNode{val: protoDollar[1].str.val + protoDollar[2].s.val}
+			protoVAL.str.setRange(protoDollar[1].str, protoDollar[2].s)
+		}
+	case 51:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:307
+//line proto.y:343
 		{
 			a := &aggregateLiteralNode{elements: protoDollar[2].agg}
 			a.setRange(protoDollar[1].b, protoDollar[3].b)
 			protoVAL.v = a
 		}
-	case 49:
+	case 53:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:314
+//line proto.y:350
 		{
 			protoVAL.agg = append(protoDollar[1].agg, protoDollar[2].agg...)
 		}
-	case 50:
+	case 54:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:317
+//line proto.y:353
 		{
 			protoVAL.agg = nil
 		}
-	case 52:
+	case 56:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:322
+//line proto.y:358
 		{
 			protoVAL.agg = protoDollar[1].agg
 		}
-	case 53:
+	case 57:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:325
+//line proto.y:361
 		{
 			protoVAL.agg = protoDollar[1].agg
 		}
-	case 54:
+	case 58:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:364
+		{
+		}
+	case 59:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:366
+		{
+		}
+	case 60:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:368
+		{
+		}
+	case 61:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:329
+//line proto.y:371
 		{
 			a := &aggregateEntryNode{name: protoDollar[1].aggName, val: protoDollar[3].v}
 			a.setRange(protoDollar[1].aggName, protoDollar[3].v)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 55:
+	case 62:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:334
+//line proto.y:376
 		{
 			s := &sliceLiteralNode{}
 			s.setRange(protoDollar[3].b, protoDollar[4].b)
@@ -1304,9 +1497,9 @@
 			a.setRange(protoDollar[1].aggName, protoDollar[4].b)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 56:
+	case 63:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:341
+//line proto.y:383
 		{
 			s := &sliceLiteralNode{elements: protoDollar[4].sl}
 			s.setRange(protoDollar[3].b, protoDollar[5].b)
@@ -1314,25 +1507,30 @@
 			a.setRange(protoDollar[1].aggName, protoDollar[5].b)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 57:
+	case 64:
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:390
+		{
+		}
+	case 65:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:348
+//line proto.y:392
 		{
 			a := &aggregateEntryNode{name: protoDollar[1].aggName, val: protoDollar[3].v}
 			a.setRange(protoDollar[1].aggName, protoDollar[3].v)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 58:
+	case 66:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:353
+//line proto.y:397
 		{
 			a := &aggregateEntryNode{name: protoDollar[1].aggName, val: protoDollar[2].v}
 			a.setRange(protoDollar[1].aggName, protoDollar[2].v)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 59:
+	case 67:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:358
+//line proto.y:402
 		{
 			s := &aggregateLiteralNode{elements: protoDollar[4].agg}
 			s.setRange(protoDollar[3].b, protoDollar[5].b)
@@ -1340,9 +1538,9 @@
 			a.setRange(protoDollar[1].aggName, protoDollar[5].b)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 60:
+	case 68:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:365
+//line proto.y:409
 		{
 			s := &aggregateLiteralNode{elements: protoDollar[3].agg}
 			s.setRange(protoDollar[2].b, protoDollar[4].b)
@@ -1350,141 +1548,187 @@
 			a.setRange(protoDollar[1].aggName, protoDollar[4].b)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 61:
-		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:373
+	case 69:
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:416
 		{
-			protoVAL.aggName = &aggregateNameNode{name: protoDollar[1].id}
+		}
+	case 70:
+		protoDollar = protoS[protopt-4 : protopt+1]
+//line proto.y:418
+		{
+		}
+	case 71:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:421
+		{
+			n := &compoundIdentNode{val: protoDollar[1].id.val}
+			n.setRange(protoDollar[1].id, protoDollar[1].id)
+			protoVAL.aggName = &aggregateNameNode{name: n}
 			protoVAL.aggName.setRange(protoDollar[1].id, protoDollar[1].id)
 		}
-	case 62:
+	case 72:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:377
+//line proto.y:427
 		{
-			protoVAL.aggName = &aggregateNameNode{name: protoDollar[2].id, isExtension: true}
+			protoVAL.aggName = &aggregateNameNode{name: protoDollar[2].cid, isExtension: true}
 			protoVAL.aggName.setRange(protoDollar[1].b, protoDollar[3].b)
 		}
-	case 63:
+	case 73:
+		protoDollar = protoS[protopt-3 : protopt+1]
+//line proto.y:431
+		{
+		}
+	case 74:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:382
+//line proto.y:434
 		{
 			protoVAL.sl = []valueNode{protoDollar[1].v}
 		}
-	case 64:
+	case 75:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:385
+//line proto.y:437
 		{
 			protoVAL.sl = append(protoDollar[1].sl, protoDollar[3].v)
 		}
-	case 65:
+	case 76:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:388
+//line proto.y:440
 		{
 			protoVAL.sl = append(protoDollar[1].sl, protoDollar[3].v)
 		}
-	case 66:
+	case 77:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:391
+//line proto.y:443
 		{
 			s := &aggregateLiteralNode{elements: protoDollar[2].agg}
 			s.setRange(protoDollar[1].b, protoDollar[3].b)
 			protoVAL.sl = []valueNode{s}
 		}
-	case 67:
-		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:396
-		{
-			s := &aggregateLiteralNode{elements: protoDollar[4].agg}
-			s.setRange(protoDollar[3].b, protoDollar[5].b)
-			protoVAL.sl = append(protoDollar[1].sl, s)
-		}
-	case 68:
-		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:401
-		{
-			s := &aggregateLiteralNode{elements: protoDollar[4].agg}
-			s.setRange(protoDollar[3].b, protoDollar[5].b)
-			protoVAL.sl = append(protoDollar[1].sl, s)
-		}
-	case 71:
-		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:410
-		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{basicNode: protoDollar[1].id.basicNode, required: true}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
-		}
-	case 72:
-		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:416
-		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{basicNode: protoDollar[1].id.basicNode}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
-		}
-	case 73:
-		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:422
-		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{basicNode: protoDollar[1].id.basicNode, repeated: true}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
-		}
-	case 74:
-		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:428
-		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
-			protoVAL.fld = &fieldNode{fldType: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].ui}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[5].b)
-		}
-	case 75:
-		protoDollar = protoS[protopt-9 : protopt+1]
-//line proto.y:433
-		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{basicNode: protoDollar[1].id.basicNode, required: true}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui, options: protoDollar[7].opts}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[9].b)
-		}
-	case 76:
-		protoDollar = protoS[protopt-9 : protopt+1]
-//line proto.y:439
-		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{basicNode: protoDollar[1].id.basicNode}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui, options: protoDollar[7].opts}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[9].b)
-		}
-	case 77:
-		protoDollar = protoS[protopt-9 : protopt+1]
-//line proto.y:445
-		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{basicNode: protoDollar[1].id.basicNode, repeated: true}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui, options: protoDollar[7].opts}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[9].b)
-		}
 	case 78:
-		protoDollar = protoS[protopt-8 : protopt+1]
-//line proto.y:451
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:448
 		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
-			protoVAL.fld = &fieldNode{fldType: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].ui, options: protoDollar[6].opts}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[8].b)
+			s := &aggregateLiteralNode{elements: protoDollar[4].agg}
+			s.setRange(protoDollar[3].b, protoDollar[5].b)
+			protoVAL.sl = append(protoDollar[1].sl, s)
 		}
 	case 79:
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:453
+		{
+			s := &aggregateLiteralNode{elements: protoDollar[4].agg}
+			s.setRange(protoDollar[3].b, protoDollar[5].b)
+			protoVAL.sl = append(protoDollar[1].sl, s)
+		}
+	case 80:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:457
+//line proto.y:458
+		{
+		}
+	case 81:
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:460
+		{
+		}
+	case 82:
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:462
+		{
+		}
+	case 84:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:466
+		{
+			protoVAL.cid = &compoundIdentNode{val: "." + protoDollar[2].cid.val}
+			protoVAL.cid.setRange(protoDollar[1].b, protoDollar[2].cid)
+		}
+	case 85:
+		protoDollar = protoS[protopt-6 : protopt+1]
+//line proto.y:471
+		{
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id, required: true}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i}
+			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
+		}
+	case 86:
+		protoDollar = protoS[protopt-6 : protopt+1]
+//line proto.y:477
+		{
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i}
+			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
+		}
+	case 87:
+		protoDollar = protoS[protopt-6 : protopt+1]
+//line proto.y:483
+		{
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id, repeated: true}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i}
+			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
+		}
+	case 88:
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:489
+		{
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.fld = &fieldNode{fldType: protoDollar[1].cid, name: protoDollar[2].id, tag: protoDollar[4].i}
+			protoVAL.fld.setRange(protoDollar[1].cid, protoDollar[5].b)
+		}
+	case 89:
+		protoDollar = protoS[protopt-7 : protopt+1]
+//line proto.y:494
+		{
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id, required: true}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i, options: protoDollar[6].cmpctOpts}
+			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[7].b)
+		}
+	case 90:
+		protoDollar = protoS[protopt-7 : protopt+1]
+//line proto.y:500
+		{
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i, options: protoDollar[6].cmpctOpts}
+			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[7].b)
+		}
+	case 91:
+		protoDollar = protoS[protopt-7 : protopt+1]
+//line proto.y:506
+		{
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id, repeated: true}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i, options: protoDollar[6].cmpctOpts}
+			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[7].b)
+		}
+	case 92:
+		protoDollar = protoS[protopt-6 : protopt+1]
+//line proto.y:512
+		{
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.fld = &fieldNode{fldType: protoDollar[1].cid, name: protoDollar[2].id, tag: protoDollar[4].i, options: protoDollar[5].cmpctOpts}
+			protoVAL.fld.setRange(protoDollar[1].cid, protoDollar[6].b)
+		}
+	case 93:
+		protoDollar = protoS[protopt-3 : protopt+1]
+//line proto.y:518
+		{
+			protoVAL.cmpctOpts = &compactOptionsNode{decls: protoDollar[2].opts}
+			protoVAL.cmpctOpts.setRange(protoDollar[1].b, protoDollar[3].b)
+		}
+	case 94:
+		protoDollar = protoS[protopt-3 : protopt+1]
+//line proto.y:523
 		{
 			protoVAL.opts = append(protoDollar[1].opts, protoDollar[3].opts...)
 		}
-	case 81:
+	case 96:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:462
+//line proto.y:528
 		{
 			n := &optionNameNode{parts: protoDollar[1].optNm}
 			n.setRange(protoDollar[1].optNm[0], protoDollar[1].optNm[len(protoDollar[1].optNm)-1])
@@ -1492,45 +1736,45 @@
 			o.setRange(protoDollar[1].optNm[0], protoDollar[3].v)
 			protoVAL.opts = []*optionNode{o}
 		}
-	case 82:
+	case 97:
 		protoDollar = protoS[protopt-8 : protopt+1]
-//line proto.y:470
+//line proto.y:536
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
 			if !unicode.IsUpper(rune(protoDollar[3].id.val[0])) {
 				lexError(protolex, protoDollar[3].id.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", protoDollar[3].id.val))
 			}
-			lbl := &labelNode{basicNode: protoDollar[1].id.basicNode, required: true}
-			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].ui, decls: protoDollar[7].msgDecls}
+			lbl := fieldLabel{identNode: protoDollar[1].id, required: true}
+			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].i, decls: protoDollar[7].msgDecls}
 			protoVAL.grp.setRange(protoDollar[1].id, protoDollar[8].b)
 		}
-	case 83:
+	case 98:
 		protoDollar = protoS[protopt-8 : protopt+1]
-//line proto.y:479
+//line proto.y:545
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
 			if !unicode.IsUpper(rune(protoDollar[3].id.val[0])) {
 				lexError(protolex, protoDollar[3].id.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", protoDollar[3].id.val))
 			}
-			lbl := &labelNode{basicNode: protoDollar[1].id.basicNode}
-			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].ui, decls: protoDollar[7].msgDecls}
+			lbl := fieldLabel{identNode: protoDollar[1].id}
+			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].i, decls: protoDollar[7].msgDecls}
 			protoVAL.grp.setRange(protoDollar[1].id, protoDollar[8].b)
 		}
-	case 84:
+	case 99:
 		protoDollar = protoS[protopt-8 : protopt+1]
-//line proto.y:488
+//line proto.y:554
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
 			if !unicode.IsUpper(rune(protoDollar[3].id.val[0])) {
 				lexError(protolex, protoDollar[3].id.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", protoDollar[3].id.val))
 			}
-			lbl := &labelNode{basicNode: protoDollar[1].id.basicNode, repeated: true}
-			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].ui, decls: protoDollar[7].msgDecls}
+			lbl := fieldLabel{identNode: protoDollar[1].id, repeated: true}
+			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].i, decls: protoDollar[7].msgDecls}
 			protoVAL.grp.setRange(protoDollar[1].id, protoDollar[8].b)
 		}
-	case 85:
+	case 100:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:498
+//line proto.y:564
 		{
 			c := 0
 			for _, el := range protoDollar[4].ooDecls {
@@ -1544,170 +1788,143 @@
 			protoVAL.oo = &oneOfNode{name: protoDollar[2].id, decls: protoDollar[4].ooDecls}
 			protoVAL.oo.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 86:
+	case 101:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:512
+//line proto.y:578
 		{
 			protoVAL.ooDecls = append(protoDollar[1].ooDecls, protoDollar[2].ooDecls...)
 		}
-	case 88:
+	case 103:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:516
+//line proto.y:582
 		{
 			protoVAL.ooDecls = nil
 		}
-	case 89:
+	case 104:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:520
+//line proto.y:586
 		{
 			protoVAL.ooDecls = []*oneOfElement{{option: protoDollar[1].opts[0]}}
 		}
-	case 90:
+	case 105:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:523
+//line proto.y:589
 		{
 			protoVAL.ooDecls = []*oneOfElement{{field: protoDollar[1].fld}}
 		}
-	case 91:
+	case 106:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:526
+//line proto.y:592
+		{
+			protoVAL.ooDecls = []*oneOfElement{{group: protoDollar[1].grp}}
+		}
+	case 107:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:595
 		{
 			protoVAL.ooDecls = []*oneOfElement{{empty: protoDollar[1].b}}
 		}
-	case 92:
-		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:530
-		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
-			protoVAL.fld = &fieldNode{fldType: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].ui}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[5].b)
-		}
-	case 93:
-		protoDollar = protoS[protopt-8 : protopt+1]
-//line proto.y:535
-		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
-			protoVAL.fld = &fieldNode{fldType: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].ui, options: protoDollar[6].opts}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[8].b)
-		}
-	case 94:
-		protoDollar = protoS[protopt-10 : protopt+1]
-//line proto.y:541
-		{
-			checkTag(protolex, protoDollar[9].ui.start(), protoDollar[9].ui.val)
-			protoVAL.mapFld = &mapFieldNode{mapKeyword: protoDollar[1].id, keyType: protoDollar[3].id, valueType: protoDollar[5].id, name: protoDollar[7].id, tag: protoDollar[9].ui}
-			protoVAL.mapFld.setRange(protoDollar[1].id, protoDollar[10].b)
-		}
-	case 95:
-		protoDollar = protoS[protopt-13 : protopt+1]
-//line proto.y:546
-		{
-			checkTag(protolex, protoDollar[9].ui.start(), protoDollar[9].ui.val)
-			protoVAL.mapFld = &mapFieldNode{mapKeyword: protoDollar[1].id, keyType: protoDollar[3].id, valueType: protoDollar[5].id, name: protoDollar[7].id, tag: protoDollar[9].ui, options: protoDollar[11].opts}
-			protoVAL.mapFld.setRange(protoDollar[1].id, protoDollar[13].b)
-		}
 	case 108:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:598
+		{
+		}
+	case 109:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:600
+		{
+		}
+	case 110:
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:603
+		{
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.fld = &fieldNode{fldType: protoDollar[1].cid, name: protoDollar[2].id, tag: protoDollar[4].i}
+			protoVAL.fld.setRange(protoDollar[1].cid, protoDollar[5].b)
+		}
+	case 111:
+		protoDollar = protoS[protopt-6 : protopt+1]
+//line proto.y:608
+		{
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.fld = &fieldNode{fldType: protoDollar[1].cid, name: protoDollar[2].id, tag: protoDollar[4].i, options: protoDollar[5].cmpctOpts}
+			protoVAL.fld.setRange(protoDollar[1].cid, protoDollar[6].b)
+		}
+	case 112:
+		protoDollar = protoS[protopt-7 : protopt+1]
+//line proto.y:614
+		{
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			if !unicode.IsUpper(rune(protoDollar[2].id.val[0])) {
+				lexError(protolex, protoDollar[2].id.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", protoDollar[2].id.val))
+			}
+			protoVAL.grp = &groupNode{groupKeyword: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].i, decls: protoDollar[6].msgDecls}
+			protoVAL.grp.setRange(protoDollar[1].id, protoDollar[7].b)
+		}
+	case 113:
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:623
+		{
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.mapFld = &mapFieldNode{mapType: protoDollar[1].mapType, name: protoDollar[2].id, tag: protoDollar[4].i}
+			protoVAL.mapFld.setRange(protoDollar[1].mapType, protoDollar[5].b)
+		}
+	case 114:
+		protoDollar = protoS[protopt-6 : protopt+1]
+//line proto.y:628
+		{
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.mapFld = &mapFieldNode{mapType: protoDollar[1].mapType, name: protoDollar[2].id, tag: protoDollar[4].i, options: protoDollar[5].cmpctOpts}
+			protoVAL.mapFld.setRange(protoDollar[1].mapType, protoDollar[6].b)
+		}
+	case 115:
+		protoDollar = protoS[protopt-6 : protopt+1]
+//line proto.y:634
+		{
+			protoVAL.mapType = &mapTypeNode{mapKeyword: protoDollar[1].id, keyType: protoDollar[3].id, valueType: protoDollar[5].cid}
+			protoVAL.mapType.setRange(protoDollar[1].id, protoDollar[6].b)
+		}
+	case 128:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:565
+//line proto.y:652
 		{
 			protoVAL.ext = &extensionRangeNode{ranges: protoDollar[2].rngs}
 			protoVAL.ext.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
-	case 109:
-		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:569
+	case 129:
+		protoDollar = protoS[protopt-4 : protopt+1]
+//line proto.y:656
 		{
-			protoVAL.ext = &extensionRangeNode{ranges: protoDollar[2].rngs, options: protoDollar[4].opts}
-			protoVAL.ext.setRange(protoDollar[1].id, protoDollar[6].b)
+			protoVAL.ext = &extensionRangeNode{ranges: protoDollar[2].rngs, options: protoDollar[3].cmpctOpts}
+			protoVAL.ext.setRange(protoDollar[1].id, protoDollar[4].b)
 		}
-	case 110:
+	case 130:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:574
+//line proto.y:661
 		{
 			protoVAL.rngs = append(protoDollar[1].rngs, protoDollar[3].rngs...)
 		}
-	case 112:
+	case 132:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:579
+//line proto.y:666
 		{
-			if protoDollar[1].ui.val > internal.MaxTag {
-				lexError(protolex, protoDollar[1].ui.start(), fmt.Sprintf("range includes out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].ui.val, internal.MaxTag))
+			if protoDollar[1].i.val > internal.MaxTag {
+				lexError(protolex, protoDollar[1].i.start(), fmt.Sprintf("range includes out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].i.val, internal.MaxTag))
 			}
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[1].ui, st: int32(protoDollar[1].ui.val), en: int32(protoDollar[1].ui.val)}
-			r.setRange(protoDollar[1].ui, protoDollar[1].ui)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 113:
-		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:587
-		{
-			if protoDollar[1].ui.val > internal.MaxTag {
-				lexError(protolex, protoDollar[1].ui.start(), fmt.Sprintf("range start is out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].ui.val, internal.MaxTag))
-			}
-			if protoDollar[3].ui.val > internal.MaxTag {
-				lexError(protolex, protoDollar[3].ui.start(), fmt.Sprintf("range end is out-of-range tag: %d (should be between 0 and %d)", protoDollar[3].ui.val, internal.MaxTag))
-			}
-			if protoDollar[1].ui.val > protoDollar[3].ui.val {
-				lexError(protolex, protoDollar[1].ui.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", protoDollar[1].ui.val, protoDollar[3].ui.val))
-			}
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[3].ui, st: int32(protoDollar[1].ui.val), en: int32(protoDollar[3].ui.val)}
-			r.setRange(protoDollar[1].ui, protoDollar[3].ui)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 114:
-		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:601
-		{
-			if protoDollar[1].ui.val > internal.MaxTag {
-				lexError(protolex, protoDollar[1].ui.start(), fmt.Sprintf("range start is out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].ui.val, internal.MaxTag))
-			}
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[3].id, st: int32(protoDollar[1].ui.val), en: internal.MaxTag}
-			r.setRange(protoDollar[1].ui, protoDollar[3].id)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 115:
-		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:610
-		{
-			protoVAL.rngs = append(protoDollar[1].rngs, protoDollar[3].rngs...)
-		}
-	case 117:
-		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:615
-		{
-			checkUint64InInt32Range(protolex, protoDollar[1].ui.start(), protoDollar[1].ui.val)
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[1].ui, st: int32(protoDollar[1].ui.val), en: int32(protoDollar[1].ui.val)}
-			r.setRange(protoDollar[1].ui, protoDollar[1].ui)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 118:
-		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:621
-		{
-			checkInt64InInt32Range(protolex, protoDollar[1].i.start(), protoDollar[1].i.val)
 			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[1].i, st: int32(protoDollar[1].i.val), en: int32(protoDollar[1].i.val)}
 			r.setRange(protoDollar[1].i, protoDollar[1].i)
 			protoVAL.rngs = []*rangeNode{r}
 		}
-	case 119:
+	case 133:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:627
+//line proto.y:674
 		{
-			checkUint64InInt32Range(protolex, protoDollar[1].ui.start(), protoDollar[1].ui.val)
-			checkUint64InInt32Range(protolex, protoDollar[3].ui.start(), protoDollar[3].ui.val)
-			if protoDollar[1].ui.val > protoDollar[3].ui.val {
-				lexError(protolex, protoDollar[1].ui.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", protoDollar[1].ui.val, protoDollar[3].ui.val))
+			if protoDollar[1].i.val > internal.MaxTag {
+				lexError(protolex, protoDollar[1].i.start(), fmt.Sprintf("range start is out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].i.val, internal.MaxTag))
 			}
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[3].ui, st: int32(protoDollar[1].ui.val), en: int32(protoDollar[3].ui.val)}
-			r.setRange(protoDollar[1].ui, protoDollar[3].ui)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 120:
-		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:637
-		{
-			checkInt64InInt32Range(protolex, protoDollar[1].i.start(), protoDollar[1].i.val)
-			checkInt64InInt32Range(protolex, protoDollar[3].i.start(), protoDollar[3].i.val)
+			if protoDollar[3].i.val > internal.MaxTag {
+				lexError(protolex, protoDollar[3].i.start(), fmt.Sprintf("range end is out-of-range tag: %d (should be between 0 and %d)", protoDollar[3].i.val, internal.MaxTag))
+			}
 			if protoDollar[1].i.val > protoDollar[3].i.val {
 				lexError(protolex, protoDollar[1].i.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", protoDollar[1].i.val, protoDollar[3].i.val))
 			}
@@ -1715,51 +1932,71 @@
 			r.setRange(protoDollar[1].i, protoDollar[3].i)
 			protoVAL.rngs = []*rangeNode{r}
 		}
-	case 121:
+	case 134:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:647
+//line proto.y:688
 		{
-			checkInt64InInt32Range(protolex, protoDollar[1].i.start(), protoDollar[1].i.val)
-			checkUint64InInt32Range(protolex, protoDollar[3].ui.start(), protoDollar[3].ui.val)
-			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[3].ui, st: int32(protoDollar[1].i.val), en: int32(protoDollar[3].ui.val)}
-			r.setRange(protoDollar[1].i, protoDollar[3].ui)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 122:
-		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:654
-		{
-			checkUint64InInt32Range(protolex, protoDollar[1].ui.start(), protoDollar[1].ui.val)
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[3].id, st: int32(protoDollar[1].ui.val), en: math.MaxInt32}
-			r.setRange(protoDollar[1].ui, protoDollar[3].id)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 123:
-		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:660
-		{
-			checkInt64InInt32Range(protolex, protoDollar[1].i.start(), protoDollar[1].i.val)
-			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[3].id, st: int32(protoDollar[1].i.val), en: math.MaxInt32}
+			if protoDollar[1].i.val > internal.MaxTag {
+				lexError(protolex, protoDollar[1].i.start(), fmt.Sprintf("range start is out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].i.val, internal.MaxTag))
+			}
+			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[3].id, st: int32(protoDollar[1].i.val), en: internal.MaxTag}
 			r.setRange(protoDollar[1].i, protoDollar[3].id)
 			protoVAL.rngs = []*rangeNode{r}
 		}
-	case 124:
+	case 135:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:667
+//line proto.y:697
+		{
+			protoVAL.rngs = append(protoDollar[1].rngs, protoDollar[3].rngs...)
+		}
+	case 137:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:702
+		{
+			checkInt64InInt32Range(protolex, protoDollar[1].il.start(), protoDollar[1].il.val)
+			r := &rangeNode{stNode: protoDollar[1].il, enNode: protoDollar[1].il, st: int32(protoDollar[1].il.val), en: int32(protoDollar[1].il.val)}
+			r.setRange(protoDollar[1].il, protoDollar[1].il)
+			protoVAL.rngs = []*rangeNode{r}
+		}
+	case 138:
+		protoDollar = protoS[protopt-3 : protopt+1]
+//line proto.y:708
+		{
+			checkInt64InInt32Range(protolex, protoDollar[1].il.start(), protoDollar[1].il.val)
+			checkInt64InInt32Range(protolex, protoDollar[3].il.start(), protoDollar[3].il.val)
+			if protoDollar[1].il.val > protoDollar[3].il.val {
+				lexError(protolex, protoDollar[1].il.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", protoDollar[1].il.val, protoDollar[3].il.val))
+			}
+			r := &rangeNode{stNode: protoDollar[1].il, enNode: protoDollar[3].il, st: int32(protoDollar[1].il.val), en: int32(protoDollar[3].il.val)}
+			r.setRange(protoDollar[1].il, protoDollar[3].il)
+			protoVAL.rngs = []*rangeNode{r}
+		}
+	case 139:
+		protoDollar = protoS[protopt-3 : protopt+1]
+//line proto.y:718
+		{
+			checkInt64InInt32Range(protolex, protoDollar[1].il.start(), protoDollar[1].il.val)
+			r := &rangeNode{stNode: protoDollar[1].il, enNode: protoDollar[3].id, st: int32(protoDollar[1].il.val), en: math.MaxInt32}
+			r.setRange(protoDollar[1].il, protoDollar[3].id)
+			protoVAL.rngs = []*rangeNode{r}
+		}
+	case 140:
+		protoDollar = protoS[protopt-3 : protopt+1]
+//line proto.y:725
 		{
 			protoVAL.resvd = &reservedNode{ranges: protoDollar[2].rngs}
 			protoVAL.resvd.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
-	case 126:
+	case 142:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:673
+//line proto.y:731
 		{
 			protoVAL.resvd = &reservedNode{ranges: protoDollar[2].rngs}
 			protoVAL.resvd.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
-	case 128:
+	case 144:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:679
+//line proto.y:737
 		{
 			rsvd := map[string]struct{}{}
 			for _, n := range protoDollar[2].names {
@@ -1772,21 +2009,21 @@
 			protoVAL.resvd = &reservedNode{names: protoDollar[2].names}
 			protoVAL.resvd.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
-	case 129:
+	case 145:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:692
+//line proto.y:750
 		{
 			protoVAL.names = append(protoDollar[1].names, protoDollar[3].str)
 		}
-	case 130:
+	case 146:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:695
+//line proto.y:753
 		{
-			protoVAL.names = []*stringLiteralNode{protoDollar[1].str}
+			protoVAL.names = []*compoundStringNode{protoDollar[1].str}
 		}
-	case 131:
+	case 147:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:699
+//line proto.y:757
 		{
 			c := 0
 			for _, el := range protoDollar[4].enDecls {
@@ -1800,162 +2037,166 @@
 			protoVAL.en = &enumNode{name: protoDollar[2].id, decls: protoDollar[4].enDecls}
 			protoVAL.en.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 132:
+	case 148:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:713
+//line proto.y:771
 		{
 			protoVAL.enDecls = append(protoDollar[1].enDecls, protoDollar[2].enDecls...)
 		}
-	case 134:
+	case 150:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:717
+//line proto.y:775
 		{
 			protoVAL.enDecls = nil
 		}
-	case 135:
+	case 151:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:721
+//line proto.y:779
 		{
 			protoVAL.enDecls = []*enumElement{{option: protoDollar[1].opts[0]}}
 		}
-	case 136:
+	case 152:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:724
+//line proto.y:782
 		{
 			protoVAL.enDecls = []*enumElement{{value: protoDollar[1].env}}
 		}
-	case 137:
+	case 153:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:727
+//line proto.y:785
 		{
 			protoVAL.enDecls = []*enumElement{{reserved: protoDollar[1].resvd}}
 		}
-	case 138:
+	case 154:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:730
+//line proto.y:788
 		{
 			protoVAL.enDecls = []*enumElement{{empty: protoDollar[1].b}}
 		}
-	case 139:
-		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:734
+	case 155:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:791
 		{
-			checkUint64InInt32Range(protolex, protoDollar[3].ui.start(), protoDollar[3].ui.val)
-			protoVAL.env = &enumValueNode{name: protoDollar[1].id, numberP: protoDollar[3].ui}
+		}
+	case 156:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:793
+		{
+		}
+	case 157:
+		protoDollar = protoS[protopt-4 : protopt+1]
+//line proto.y:796
+		{
+			checkInt64InInt32Range(protolex, protoDollar[3].il.start(), protoDollar[3].il.val)
+			protoVAL.env = &enumValueNode{name: protoDollar[1].id, number: protoDollar[3].il}
 			protoVAL.env.setRange(protoDollar[1].id, protoDollar[4].b)
 		}
-	case 140:
-		protoDollar = protoS[protopt-7 : protopt+1]
-//line proto.y:739
-		{
-			checkUint64InInt32Range(protolex, protoDollar[3].ui.start(), protoDollar[3].ui.val)
-			protoVAL.env = &enumValueNode{name: protoDollar[1].id, numberP: protoDollar[3].ui, options: protoDollar[5].opts}
-			protoVAL.env.setRange(protoDollar[1].id, protoDollar[7].b)
-		}
-	case 141:
-		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:744
-		{
-			checkInt64InInt32Range(protolex, protoDollar[3].i.start(), protoDollar[3].i.val)
-			protoVAL.env = &enumValueNode{name: protoDollar[1].id, numberN: protoDollar[3].i}
-			protoVAL.env.setRange(protoDollar[1].id, protoDollar[4].b)
-		}
-	case 142:
-		protoDollar = protoS[protopt-7 : protopt+1]
-//line proto.y:749
-		{
-			checkInt64InInt32Range(protolex, protoDollar[3].i.start(), protoDollar[3].i.val)
-			protoVAL.env = &enumValueNode{name: protoDollar[1].id, numberN: protoDollar[3].i, options: protoDollar[5].opts}
-			protoVAL.env.setRange(protoDollar[1].id, protoDollar[7].b)
-		}
-	case 143:
+	case 158:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:755
+//line proto.y:801
+		{
+			checkInt64InInt32Range(protolex, protoDollar[3].il.start(), protoDollar[3].il.val)
+			protoVAL.env = &enumValueNode{name: protoDollar[1].id, number: protoDollar[3].il, options: protoDollar[4].cmpctOpts}
+			protoVAL.env.setRange(protoDollar[1].id, protoDollar[5].b)
+		}
+	case 159:
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:807
 		{
 			protoVAL.msg = &messageNode{name: protoDollar[2].id, decls: protoDollar[4].msgDecls}
 			protoVAL.msg.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 144:
+	case 160:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:760
+//line proto.y:812
 		{
 			protoVAL.msgDecls = append(protoDollar[1].msgDecls, protoDollar[2].msgDecls...)
 		}
-	case 146:
+	case 162:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:764
+//line proto.y:816
 		{
 			protoVAL.msgDecls = nil
 		}
-	case 147:
+	case 163:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:768
+//line proto.y:820
 		{
 			protoVAL.msgDecls = []*messageElement{{field: protoDollar[1].fld}}
 		}
-	case 148:
+	case 164:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:771
+//line proto.y:823
 		{
 			protoVAL.msgDecls = []*messageElement{{enum: protoDollar[1].en}}
 		}
-	case 149:
+	case 165:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:774
+//line proto.y:826
 		{
 			protoVAL.msgDecls = []*messageElement{{nested: protoDollar[1].msg}}
 		}
-	case 150:
+	case 166:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:777
+//line proto.y:829
 		{
 			protoVAL.msgDecls = []*messageElement{{extend: protoDollar[1].extend}}
 		}
-	case 151:
+	case 167:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:780
+//line proto.y:832
 		{
 			protoVAL.msgDecls = []*messageElement{{extensionRange: protoDollar[1].ext}}
 		}
-	case 152:
+	case 168:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:783
+//line proto.y:835
 		{
 			protoVAL.msgDecls = []*messageElement{{group: protoDollar[1].grp}}
 		}
-	case 153:
+	case 169:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:786
+//line proto.y:838
 		{
 			protoVAL.msgDecls = []*messageElement{{option: protoDollar[1].opts[0]}}
 		}
-	case 154:
+	case 170:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:789
+//line proto.y:841
 		{
 			protoVAL.msgDecls = []*messageElement{{oneOf: protoDollar[1].oo}}
 		}
-	case 155:
+	case 171:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:792
+//line proto.y:844
 		{
 			protoVAL.msgDecls = []*messageElement{{mapField: protoDollar[1].mapFld}}
 		}
-	case 156:
+	case 172:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:795
+//line proto.y:847
 		{
 			protoVAL.msgDecls = []*messageElement{{reserved: protoDollar[1].resvd}}
 		}
-	case 157:
+	case 173:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:798
+//line proto.y:850
 		{
 			protoVAL.msgDecls = []*messageElement{{empty: protoDollar[1].b}}
 		}
-	case 158:
+	case 174:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:853
+		{
+		}
+	case 175:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:855
+		{
+		}
+	case 176:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:802
+//line proto.y:858
 		{
 			c := 0
 			for _, el := range protoDollar[4].extDecls {
@@ -1966,128 +2207,158 @@
 			if c == 0 {
 				lexError(protolex, protoDollar[1].id.start(), "extend sections must define at least one extension")
 			}
-			protoVAL.extend = &extendNode{extendee: protoDollar[2].id, decls: protoDollar[4].extDecls}
+			protoVAL.extend = &extendNode{extendee: protoDollar[2].cid, decls: protoDollar[4].extDecls}
 			protoVAL.extend.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 159:
+	case 177:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:816
+//line proto.y:872
 		{
 			protoVAL.extDecls = append(protoDollar[1].extDecls, protoDollar[2].extDecls...)
 		}
-	case 161:
+	case 179:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:820
+//line proto.y:876
 		{
 			protoVAL.extDecls = nil
 		}
-	case 162:
+	case 180:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:824
+//line proto.y:880
 		{
 			protoVAL.extDecls = []*extendElement{{field: protoDollar[1].fld}}
 		}
-	case 163:
+	case 181:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:827
+//line proto.y:883
 		{
 			protoVAL.extDecls = []*extendElement{{group: protoDollar[1].grp}}
 		}
-	case 164:
+	case 182:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:830
+//line proto.y:886
 		{
 			protoVAL.extDecls = []*extendElement{{empty: protoDollar[1].b}}
 		}
-	case 165:
+	case 183:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:889
+		{
+		}
+	case 184:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:891
+		{
+		}
+	case 185:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:834
+//line proto.y:894
 		{
 			protoVAL.svc = &serviceNode{name: protoDollar[2].id, decls: protoDollar[4].svcDecls}
 			protoVAL.svc.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 166:
+	case 186:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:839
+//line proto.y:899
 		{
 			protoVAL.svcDecls = append(protoDollar[1].svcDecls, protoDollar[2].svcDecls...)
 		}
-	case 168:
+	case 188:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:843
+//line proto.y:903
 		{
 			protoVAL.svcDecls = nil
 		}
-	case 169:
+	case 189:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:850
+//line proto.y:910
 		{
 			protoVAL.svcDecls = []*serviceElement{{option: protoDollar[1].opts[0]}}
 		}
-	case 170:
+	case 190:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:853
+//line proto.y:913
 		{
 			protoVAL.svcDecls = []*serviceElement{{rpc: protoDollar[1].mtd}}
 		}
-	case 171:
+	case 191:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:856
+//line proto.y:916
 		{
 			protoVAL.svcDecls = []*serviceElement{{empty: protoDollar[1].b}}
 		}
-	case 172:
+	case 192:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:919
+		{
+		}
+	case 193:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:921
+		{
+		}
+	case 194:
 		protoDollar = protoS[protopt-10 : protopt+1]
-//line proto.y:860
+//line proto.y:924
 		{
 			protoVAL.mtd = &methodNode{name: protoDollar[2].id, input: protoDollar[4].rpcType, output: protoDollar[8].rpcType}
 			protoVAL.mtd.setRange(protoDollar[1].id, protoDollar[10].b)
 		}
-	case 173:
+	case 195:
 		protoDollar = protoS[protopt-12 : protopt+1]
-//line proto.y:864
+//line proto.y:928
 		{
 			protoVAL.mtd = &methodNode{name: protoDollar[2].id, input: protoDollar[4].rpcType, output: protoDollar[8].rpcType, options: protoDollar[11].opts}
 			protoVAL.mtd.setRange(protoDollar[1].id, protoDollar[12].b)
 		}
-	case 174:
+	case 196:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:869
+//line proto.y:933
 		{
-			protoVAL.rpcType = &rpcTypeNode{msgType: protoDollar[2].id, streamKeyword: protoDollar[1].id}
-			protoVAL.rpcType.setRange(protoDollar[1].id, protoDollar[2].id)
+			protoVAL.rpcType = &rpcTypeNode{msgType: protoDollar[2].cid, streamKeyword: protoDollar[1].id}
+			protoVAL.rpcType.setRange(protoDollar[1].id, protoDollar[2].cid)
 		}
-	case 175:
+	case 197:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:873
+//line proto.y:937
 		{
-			protoVAL.rpcType = &rpcTypeNode{msgType: protoDollar[1].id}
-			protoVAL.rpcType.setRange(protoDollar[1].id, protoDollar[1].id)
+			protoVAL.rpcType = &rpcTypeNode{msgType: protoDollar[1].cid}
+			protoVAL.rpcType.setRange(protoDollar[1].cid, protoDollar[1].cid)
 		}
-	case 176:
+	case 198:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:878
+//line proto.y:942
 		{
 			protoVAL.opts = append(protoDollar[1].opts, protoDollar[2].opts...)
 		}
-	case 178:
+	case 200:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:882
+//line proto.y:946
 		{
 			protoVAL.opts = []*optionNode{}
 		}
-	case 179:
+	case 201:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:886
+//line proto.y:950
 		{
 			protoVAL.opts = protoDollar[1].opts
 		}
-	case 180:
+	case 202:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:889
+//line proto.y:953
 		{
 			protoVAL.opts = []*optionNode{}
 		}
+	case 203:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:956
+		{
+		}
+	case 204:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:958
+		{
+		}
 	}
 	goto protostack /* stack new state and value */
 }
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/resolve_files.go b/vendor/github.com/jhump/protoreflect/desc/protoparse/resolve_files.go
new file mode 100644
index 0000000..2561e56
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/resolve_files.go
@@ -0,0 +1,170 @@
+package protoparse
+
+import (
+	"errors"
+	"fmt"
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+var errNoImportPathsForAbsoluteFilePath = errors.New("must specify at least one import path if any absolute file paths are given")
+
+// ResolveFilenames tries to resolve fileNames into paths that are relative to
+// directories in the given importPaths. The returned slice has the results in
+// the same order as they are supplied in fileNames.
+//
+// The resulting names should be suitable for passing to Parser.ParseFiles.
+//
+// If no import paths are given and any file name is absolute, this returns an
+// error.  If no import paths are given and all file names are relative, this
+// returns the original file names. If a file name is already relative to one
+// of the given import paths, it will be unchanged in the returned slice. If a
+// file name given is relative to the current working directory, it will be made
+// relative to one of the given import paths; but if it cannot be made relative
+// (due to no matching import path), an error will be returned.
+func ResolveFilenames(importPaths []string, fileNames ...string) ([]string, error) {
+	if len(importPaths) == 0 {
+		if containsAbsFilePath(fileNames) {
+			// We have to do this as otherwise parseProtoFiles can result in duplicate symbols.
+			// For example, assume we import "foo/bar/bar.proto" in a file "/home/alice/dev/foo/bar/baz.proto"
+			// as we call ParseFiles("/home/alice/dev/foo/bar/bar.proto","/home/alice/dev/foo/bar/baz.proto")
+			// with "/home/alice/dev" as our current directory. Due to the recursive nature of parseProtoFiles,
+			// it will discover the import "foo/bar/bar.proto" in the input file, and call parse on this,
+			// adding "foo/bar/bar.proto" to the parsed results, as well as "/home/alice/dev/foo/bar/bar.proto"
+			// from the input file list. This will result in a
+			// 'duplicate symbol SYMBOL: already defined as field in "/home/alice/dev/foo/bar/bar.proto'
+			// error being returned from ParseFiles.
+			return nil, errNoImportPathsForAbsoluteFilePath
+		}
+		return fileNames, nil
+	}
+	absImportPaths, err := absoluteFilePaths(importPaths)
+	if err != nil {
+		return nil, err
+	}
+	resolvedFileNames := make([]string, 0, len(fileNames))
+	for _, fileName := range fileNames {
+		resolvedFileName, err := resolveFilename(absImportPaths, fileName)
+		if err != nil {
+			return nil, err
+		}
+		resolvedFileNames = append(resolvedFileNames, resolvedFileName)
+	}
+	return resolvedFileNames, nil
+}
+
+func containsAbsFilePath(filePaths []string) bool {
+	for _, filePath := range filePaths {
+		if filepath.IsAbs(filePath) {
+			return true
+		}
+	}
+	return false
+}
+
+func absoluteFilePaths(filePaths []string) ([]string, error) {
+	absFilePaths := make([]string, 0, len(filePaths))
+	for _, filePath := range filePaths {
+		absFilePath, err := canonicalize(filePath)
+		if err != nil {
+			return nil, err
+		}
+		absFilePaths = append(absFilePaths, absFilePath)
+	}
+	return absFilePaths, nil
+}
+
+func canonicalize(filePath string) (string, error) {
+	absPath, err := filepath.Abs(filePath)
+	if err != nil {
+		return "", err
+	}
+	// this is kind of gross, but it lets us construct a resolved path even if some
+	// path elements do not exist (a single call to filepath.EvalSymlinks would just
+	// return an error, ENOENT, in that case).
+	head := absPath
+	tail := ""
+	for {
+		noLinks, err := filepath.EvalSymlinks(head)
+		if err == nil {
+			if tail != "" {
+				return filepath.Join(noLinks, tail), nil
+			}
+			return noLinks, nil
+		}
+
+		if tail == "" {
+			tail = filepath.Base(head)
+		} else {
+			tail = filepath.Join(filepath.Base(head), tail)
+		}
+		head = filepath.Dir(head)
+		if head == "." {
+			// ran out of path elements to try to resolve
+			return absPath, nil
+		}
+	}
+}
+
+const dotPrefix = "." + string(filepath.Separator)
+const dotDotPrefix = ".." + string(filepath.Separator)
+
+func resolveFilename(absImportPaths []string, fileName string) (string, error) {
+	if filepath.IsAbs(fileName) {
+		return resolveAbsFilename(absImportPaths, fileName)
+	}
+
+	if !strings.HasPrefix(fileName, dotPrefix) && !strings.HasPrefix(fileName, dotDotPrefix) {
+		// Use of . and .. are assumed to be relative to current working
+		// directory. So if those aren't present, check to see if the file is
+		// relative to an import path.
+		for _, absImportPath := range absImportPaths {
+			absFileName := filepath.Join(absImportPath, fileName)
+			_, err := os.Stat(absFileName)
+			if err != nil {
+				continue
+			}
+			// found it! it was relative to this import path
+			return fileName, nil
+		}
+	}
+
+	// must be relative to current working dir
+	return resolveAbsFilename(absImportPaths, fileName)
+}
+
+func resolveAbsFilename(absImportPaths []string, fileName string) (string, error) {
+	absFileName, err := canonicalize(fileName)
+	if err != nil {
+		return "", err
+	}
+	for _, absImportPath := range absImportPaths {
+		if isDescendant(absImportPath, absFileName) {
+			resolvedPath, err := filepath.Rel(absImportPath, absFileName)
+			if err != nil {
+				return "", err
+			}
+			return resolvedPath, nil
+		}
+	}
+	return "", fmt.Errorf("%s does not reside in any import path", fileName)
+}
+
+// isDescendant returns true if file is a descendant of dir. Both dir and file must
+// be cleaned, absolute paths.
+func isDescendant(dir, file string) bool {
+	dir = filepath.Clean(dir)
+	cur := file
+	for {
+		d := filepath.Dir(cur)
+		if d == dir {
+			return true
+		}
+		if d == "." || d == cur {
+			// we've run out of path elements
+			return false
+		}
+		cur = d
+	}
+}
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/source_code_info.go b/vendor/github.com/jhump/protoreflect/desc/protoparse/source_code_info.go
index d0a61c2..ff37733 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoparse/source_code_info.go
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/source_code_info.go
@@ -2,8 +2,6 @@
 
 import (
 	"bytes"
-	"reflect"
-	"sort"
 	"strings"
 
 	"github.com/golang/protobuf/proto"
@@ -23,287 +21,267 @@
 	path := make([]int32, 0, 10)
 
 	fn := r.getFileNode(r.fd).(*fileNode)
+	sci.newLocWithoutComments(fn, nil)
+
 	if fn.syntax != nil {
 		sci.newLoc(fn.syntax, append(path, internal.File_syntaxTag))
 	}
-	if fn.pkg != nil {
-		sci.newLoc(fn.pkg, append(path, internal.File_packageTag))
-	}
-	for i, imp := range fn.imports {
-		sci.newLoc(imp, append(path, internal.File_dependencyTag, int32(i)))
-	}
 
-	// file options
-	r.generateSourceCodeInfoForOptions(&sci, fn.decls, func(n interface{}) *optionNode {
-		return n.(*fileElement).option
-	}, r.fd.Options.GetUninterpretedOption(), append(path, internal.File_optionsTag))
+	var depIndex, optIndex, msgIndex, enumIndex, extendIndex, svcIndex int32
 
-	// message types
-	for i, msg := range r.fd.GetMessageType() {
-		r.generateSourceCodeInfoForMessage(&sci, msg, append(path, internal.File_messagesTag, int32(i)))
-	}
-
-	// enum types
-	for i, enum := range r.fd.GetEnumType() {
-		r.generateSourceCodeInfoForEnum(&sci, enum, append(path, internal.File_enumsTag, int32(i)))
-	}
-
-	// extension fields
-	for i, ext := range r.fd.GetExtension() {
-		r.generateSourceCodeInfoForField(&sci, ext, append(path, internal.File_extensionsTag, int32(i)))
-	}
-
-	// services and methods
-	for i, svc := range r.fd.GetService() {
-		n := r.getServiceNode(svc).(*serviceNode)
-		svcPath := append(path, internal.File_servicesTag, int32(i))
-		sci.newLoc(n, svcPath)
-		sci.newLoc(n.name, append(svcPath, internal.Service_nameTag))
-
-		// service options
-		r.generateSourceCodeInfoForOptions(&sci, n.decls, func(n interface{}) *optionNode {
-			return n.(*serviceElement).option
-		}, svc.Options.GetUninterpretedOption(), append(svcPath, internal.Service_optionsTag))
-
-		// methods
-		for j, mtd := range svc.GetMethod() {
-			mn := r.getMethodNode(mtd).(*methodNode)
-			mtdPath := append(svcPath, internal.Service_methodsTag, int32(j))
-			sci.newLoc(mn, mtdPath)
-			sci.newLoc(mn.name, append(mtdPath, internal.Method_nameTag))
-
-			sci.newLoc(mn.input.msgType, append(mtdPath, internal.Method_inputTag))
-			if mn.input.streamKeyword != nil {
-				sci.newLoc(mn.input.streamKeyword, append(mtdPath, internal.Method_inputStreamTag))
-			}
-			sci.newLoc(mn.output.msgType, append(mtdPath, internal.Method_outputTag))
-			if mn.output.streamKeyword != nil {
-				sci.newLoc(mn.output.streamKeyword, append(mtdPath, internal.Method_outputStreamTag))
-			}
-
-			// method options
-			r.generateSourceCodeInfoForOptions(&sci, mn.options, func(n interface{}) *optionNode {
-				return n.(*optionNode)
-			}, mtd.Options.GetUninterpretedOption(), append(mtdPath, internal.Method_optionsTag))
-		}
-	}
-	return &dpb.SourceCodeInfo{Location: sci.generateLocs()}
-}
-
-func (r *parseResult) generateSourceCodeInfoForOptions(sci *sourceCodeInfo, elements interface{}, extractor func(interface{}) *optionNode, uninterp []*dpb.UninterpretedOption, path []int32) {
-	// Known options are option node elements that have a corresponding
-	// path in r.interpretedOptions. We'll do those first.
-	rv := reflect.ValueOf(elements)
-	for i := 0; i < rv.Len(); i++ {
-		on := extractor(rv.Index(i).Interface())
-		if on == nil {
-			continue
-		}
-		optPath := r.interpretedOptions[on]
-		if len(optPath) > 0 {
-			p := path
-			if optPath[0] == -1 {
-				// used by "default" and "json_name" field pseudo-options
-				// to attribute path to parent element (since those are
-				// stored directly on the descriptor, not its options)
-				p = make([]int32, len(path)-1)
-				copy(p, path)
-				optPath = optPath[1:]
-			}
-			sci.newLoc(on, append(p, optPath...))
-		}
-	}
-
-	// Now uninterpreted options
-	for i, uo := range uninterp {
-		optPath := append(path, internal.UninterpretedOptionsTag, int32(i))
-		on := r.getOptionNode(uo).(*optionNode)
-		sci.newLoc(on, optPath)
-
-		var valTag int32
+	for _, child := range fn.decls {
 		switch {
-		case uo.IdentifierValue != nil:
-			valTag = internal.Uninterpreted_identTag
-		case uo.PositiveIntValue != nil:
-			valTag = internal.Uninterpreted_posIntTag
-		case uo.NegativeIntValue != nil:
-			valTag = internal.Uninterpreted_negIntTag
-		case uo.DoubleValue != nil:
-			valTag = internal.Uninterpreted_doubleTag
-		case uo.StringValue != nil:
-			valTag = internal.Uninterpreted_stringTag
-		case uo.AggregateValue != nil:
-			valTag = internal.Uninterpreted_aggregateTag
+		case child.imp != nil:
+			sci.newLoc(child.imp, append(path, internal.File_dependencyTag, int32(depIndex)))
+			depIndex++
+		case child.pkg != nil:
+			sci.newLoc(child.pkg, append(path, internal.File_packageTag))
+		case child.option != nil:
+			r.generateSourceCodeInfoForOption(&sci, child.option, false, &optIndex, append(path, internal.File_optionsTag))
+		case child.message != nil:
+			r.generateSourceCodeInfoForMessage(&sci, child.message, nil, append(path, internal.File_messagesTag, msgIndex))
+			msgIndex++
+		case child.enum != nil:
+			r.generateSourceCodeInfoForEnum(&sci, child.enum, append(path, internal.File_enumsTag, enumIndex))
+			enumIndex++
+		case child.extend != nil:
+			r.generateSourceCodeInfoForExtensions(&sci, child.extend, &extendIndex, &msgIndex, append(path, internal.File_extensionsTag), append(dup(path), internal.File_messagesTag))
+		case child.service != nil:
+			r.generateSourceCodeInfoForService(&sci, child.service, append(path, internal.File_servicesTag, svcIndex))
+			svcIndex++
 		}
-		if valTag != 0 {
-			sci.newLoc(on.val, append(optPath, valTag))
-		}
+	}
 
-		for j, n := range uo.Name {
-			optNmPath := append(optPath, internal.Uninterpreted_nameTag, int32(j))
-			nn := r.getOptionNamePartNode(n).(*optionNamePartNode)
-			sci.newLoc(nn, optNmPath)
-			sci.newLoc(nn.text, append(optNmPath, internal.UninterpretedName_nameTag))
+	return &dpb.SourceCodeInfo{Location: sci.locs}
+}
+
+func (r *parseResult) generateSourceCodeInfoForOption(sci *sourceCodeInfo, n *optionNode, compact bool, uninterpIndex *int32, path []int32) {
+	if !compact {
+		sci.newLocWithoutComments(n, path)
+	}
+	subPath := r.interpretedOptions[n]
+	if len(subPath) > 0 {
+		p := path
+		if subPath[0] == -1 {
+			// used by "default" and "json_name" field pseudo-options
+			// to attribute path to parent element (since those are
+			// stored directly on the descriptor, not its options)
+			p = make([]int32, len(path)-1)
+			copy(p, path)
+			subPath = subPath[1:]
 		}
+		sci.newLoc(n, append(p, subPath...))
+		return
+	}
+
+	// it's an uninterpreted option
+	optPath := append(path, internal.UninterpretedOptionsTag, *uninterpIndex)
+	*uninterpIndex++
+	sci.newLoc(n, optPath)
+	var valTag int32
+	switch n.val.(type) {
+	case *compoundIdentNode:
+		valTag = internal.Uninterpreted_identTag
+	case *intLiteralNode:
+		valTag = internal.Uninterpreted_posIntTag
+	case *compoundIntNode:
+		valTag = internal.Uninterpreted_negIntTag
+	case *compoundFloatNode:
+		valTag = internal.Uninterpreted_doubleTag
+	case *compoundStringNode:
+		valTag = internal.Uninterpreted_stringTag
+	case *aggregateLiteralNode:
+		valTag = internal.Uninterpreted_aggregateTag
+	}
+	if valTag != 0 {
+		sci.newLoc(n.val, append(optPath, valTag))
+	}
+	for j, nn := range n.name.parts {
+		optNmPath := append(optPath, internal.Uninterpreted_nameTag, int32(j))
+		sci.newLoc(nn, optNmPath)
+		sci.newLoc(nn.text, append(optNmPath, internal.UninterpretedName_nameTag))
 	}
 }
 
-func (r *parseResult) generateSourceCodeInfoForMessage(sci *sourceCodeInfo, msg *dpb.DescriptorProto, path []int32) {
-	n := r.getMessageNode(msg)
+func (r *parseResult) generateSourceCodeInfoForMessage(sci *sourceCodeInfo, n msgDecl, fieldPath []int32, path []int32) {
 	sci.newLoc(n, path)
 
 	var decls []*messageElement
-	var resvdNames []*stringLiteralNode
 	switch n := n.(type) {
 	case *messageNode:
 		decls = n.decls
-		resvdNames = n.reserved
 	case *groupNode:
 		decls = n.decls
-		resvdNames = n.reserved
-	}
-	if decls == nil {
+	case *mapFieldNode:
 		// map entry so nothing else to do
 		return
 	}
 
 	sci.newLoc(n.messageName(), append(path, internal.Message_nameTag))
-
-	// message options
-	r.generateSourceCodeInfoForOptions(sci, decls, func(n interface{}) *optionNode {
-		return n.(*messageElement).option
-	}, msg.Options.GetUninterpretedOption(), append(path, internal.Message_optionsTag))
-
-	// fields
-	for i, fld := range msg.GetField() {
-		r.generateSourceCodeInfoForField(sci, fld, append(path, internal.Message_fieldsTag, int32(i)))
+	// matching protoc, which emits the corresponding field type name (for group fields)
+	// right after the source location for the group message name
+	if fieldPath != nil {
+		sci.newLoc(n.messageName(), append(fieldPath, internal.Field_typeNameTag))
 	}
 
-	// one-ofs
-	for i, ood := range msg.GetOneofDecl() {
-		oon := r.getOneOfNode(ood).(*oneOfNode)
-		ooPath := append(path, internal.Message_oneOfsTag, int32(i))
-		sci.newLoc(oon, ooPath)
-		sci.newLoc(oon.name, append(ooPath, internal.OneOf_nameTag))
-
-		// one-of options
-		r.generateSourceCodeInfoForOptions(sci, oon.decls, func(n interface{}) *optionNode {
-			return n.(*oneOfElement).option
-		}, ood.Options.GetUninterpretedOption(), append(ooPath, internal.OneOf_optionsTag))
-	}
-
-	// nested messages
-	for i, nm := range msg.GetNestedType() {
-		r.generateSourceCodeInfoForMessage(sci, nm, append(path, internal.Message_nestedMessagesTag, int32(i)))
-	}
-
-	// nested enums
-	for i, enum := range msg.GetEnumType() {
-		r.generateSourceCodeInfoForEnum(sci, enum, append(path, internal.Message_enumsTag, int32(i)))
-	}
-
-	// nested extensions
-	for i, ext := range msg.GetExtension() {
-		r.generateSourceCodeInfoForField(sci, ext, append(path, internal.Message_extensionsTag, int32(i)))
-	}
-
-	// extension ranges
-	for i, er := range msg.ExtensionRange {
-		rangePath := append(path, internal.Message_extensionRangeTag, int32(i))
-		rn := r.getExtensionRangeNode(er).(*rangeNode)
-		sci.newLoc(rn, rangePath)
-		sci.newLoc(rn.stNode, append(rangePath, internal.ExtensionRange_startTag))
-		if rn.stNode != rn.enNode {
-			sci.newLoc(rn.enNode, append(rangePath, internal.ExtensionRange_endTag))
-		}
-		// now we have to find the extension decl and options that correspond to this range :(
-		for _, d := range decls {
-			found := false
-			if d.extensionRange != nil {
-				for _, r := range d.extensionRange.ranges {
-					if rn == r {
-						found = true
-						break
-					}
+	var optIndex, fieldIndex, oneOfIndex, extendIndex, nestedMsgIndex int32
+	var nestedEnumIndex, extRangeIndex, reservedRangeIndex, reservedNameIndex int32
+	for _, child := range decls {
+		switch {
+		case child.option != nil:
+			r.generateSourceCodeInfoForOption(sci, child.option, false, &optIndex, append(path, internal.Message_optionsTag))
+		case child.field != nil:
+			r.generateSourceCodeInfoForField(sci, child.field, append(path, internal.Message_fieldsTag, fieldIndex))
+			fieldIndex++
+		case child.group != nil:
+			fldPath := append(path, internal.Message_fieldsTag, fieldIndex)
+			r.generateSourceCodeInfoForField(sci, child.group, fldPath)
+			fieldIndex++
+			r.generateSourceCodeInfoForMessage(sci, child.group, fldPath, append(dup(path), internal.Message_nestedMessagesTag, nestedMsgIndex))
+			nestedMsgIndex++
+		case child.mapField != nil:
+			r.generateSourceCodeInfoForField(sci, child.mapField, append(path, internal.Message_fieldsTag, fieldIndex))
+			fieldIndex++
+		case child.oneOf != nil:
+			r.generateSourceCodeInfoForOneOf(sci, child.oneOf, &fieldIndex, &nestedMsgIndex, append(path, internal.Message_fieldsTag), append(dup(path), internal.Message_nestedMessagesTag), append(dup(path), internal.Message_oneOfsTag, oneOfIndex))
+			oneOfIndex++
+		case child.nested != nil:
+			r.generateSourceCodeInfoForMessage(sci, child.nested, nil, append(path, internal.Message_nestedMessagesTag, nestedMsgIndex))
+			nestedMsgIndex++
+		case child.enum != nil:
+			r.generateSourceCodeInfoForEnum(sci, child.enum, append(path, internal.Message_enumsTag, nestedEnumIndex))
+			nestedEnumIndex++
+		case child.extend != nil:
+			r.generateSourceCodeInfoForExtensions(sci, child.extend, &extendIndex, &nestedMsgIndex, append(path, internal.Message_extensionsTag), append(dup(path), internal.Message_nestedMessagesTag))
+		case child.extensionRange != nil:
+			r.generateSourceCodeInfoForExtensionRanges(sci, child.extensionRange, &extRangeIndex, append(path, internal.Message_extensionRangeTag))
+		case child.reserved != nil:
+			if len(child.reserved.names) > 0 {
+				resPath := append(path, internal.Message_reservedNameTag)
+				sci.newLoc(child.reserved, resPath)
+				for _, rn := range child.reserved.names {
+					sci.newLoc(rn, append(resPath, reservedNameIndex))
+					reservedNameIndex++
 				}
 			}
-			if found {
-				r.generateSourceCodeInfoForOptions(sci, d.extensionRange.options, func(n interface{}) *optionNode {
-					return n.(*optionNode)
-				}, er.Options.GetUninterpretedOption(), append(rangePath, internal.ExtensionRange_optionsTag))
-				break
+			if len(child.reserved.ranges) > 0 {
+				resPath := append(path, internal.Message_reservedRangeTag)
+				sci.newLoc(child.reserved, resPath)
+				for _, rr := range child.reserved.ranges {
+					r.generateSourceCodeInfoForReservedRange(sci, rr, append(resPath, reservedRangeIndex))
+					reservedRangeIndex++
+				}
 			}
 		}
 	}
-
-	// reserved ranges
-	for i, rr := range msg.ReservedRange {
-		rangePath := append(path, internal.Message_reservedRangeTag, int32(i))
-		rn := r.getMessageReservedRangeNode(rr).(*rangeNode)
-		sci.newLoc(rn, rangePath)
-		sci.newLoc(rn.stNode, append(rangePath, internal.ReservedRange_startTag))
-		if rn.stNode != rn.enNode {
-			sci.newLoc(rn.enNode, append(rangePath, internal.ReservedRange_endTag))
-		}
-	}
-
-	// reserved names
-	for i, n := range resvdNames {
-		sci.newLoc(n, append(path, internal.Message_reservedNameTag, int32(i)))
-	}
 }
 
-func (r *parseResult) generateSourceCodeInfoForEnum(sci *sourceCodeInfo, enum *dpb.EnumDescriptorProto, path []int32) {
-	n := r.getEnumNode(enum).(*enumNode)
+func (r *parseResult) generateSourceCodeInfoForEnum(sci *sourceCodeInfo, n *enumNode, path []int32) {
 	sci.newLoc(n, path)
 	sci.newLoc(n.name, append(path, internal.Enum_nameTag))
 
-	// enum options
-	r.generateSourceCodeInfoForOptions(sci, n.decls, func(n interface{}) *optionNode {
-		return n.(*enumElement).option
-	}, enum.Options.GetUninterpretedOption(), append(path, internal.Enum_optionsTag))
-
-	// enum values
-	for j, ev := range enum.GetValue() {
-		evn := r.getEnumValueNode(ev).(*enumValueNode)
-		evPath := append(path, internal.Enum_valuesTag, int32(j))
-		sci.newLoc(evn, evPath)
-		sci.newLoc(evn.name, append(evPath, internal.EnumVal_nameTag))
-		sci.newLoc(evn.getNumber(), append(evPath, internal.EnumVal_numberTag))
-
-		// enum value options
-		r.generateSourceCodeInfoForOptions(sci, evn.options, func(n interface{}) *optionNode {
-			return n.(*optionNode)
-		}, ev.Options.GetUninterpretedOption(), append(evPath, internal.EnumVal_optionsTag))
-	}
-
-	// reserved ranges
-	for i, rr := range enum.GetReservedRange() {
-		rangePath := append(path, internal.Enum_reservedRangeTag, int32(i))
-		rn := r.getEnumReservedRangeNode(rr).(*rangeNode)
-		sci.newLoc(rn, rangePath)
-		sci.newLoc(rn.stNode, append(rangePath, internal.ReservedRange_startTag))
-		if rn.stNode != rn.enNode {
-			sci.newLoc(rn.enNode, append(rangePath, internal.ReservedRange_endTag))
+	var optIndex, valIndex, reservedNameIndex, reservedRangeIndex int32
+	for _, child := range n.decls {
+		switch {
+		case child.option != nil:
+			r.generateSourceCodeInfoForOption(sci, child.option, false, &optIndex, append(path, internal.Enum_optionsTag))
+		case child.value != nil:
+			r.generateSourceCodeInfoForEnumValue(sci, child.value, append(path, internal.Enum_valuesTag, valIndex))
+			valIndex++
+		case child.reserved != nil:
+			if len(child.reserved.names) > 0 {
+				resPath := append(path, internal.Enum_reservedNameTag)
+				sci.newLoc(child.reserved, resPath)
+				for _, rn := range child.reserved.names {
+					sci.newLoc(rn, append(resPath, reservedNameIndex))
+					reservedNameIndex++
+				}
+			}
+			if len(child.reserved.ranges) > 0 {
+				resPath := append(path, internal.Enum_reservedRangeTag)
+				sci.newLoc(child.reserved, resPath)
+				for _, rr := range child.reserved.ranges {
+					r.generateSourceCodeInfoForReservedRange(sci, rr, append(resPath, reservedRangeIndex))
+					reservedRangeIndex++
+				}
+			}
 		}
 	}
-
-	// reserved names
-	for i, rn := range n.reserved {
-		sci.newLoc(rn, append(path, internal.Enum_reservedNameTag, int32(i)))
-	}
 }
 
-func (r *parseResult) generateSourceCodeInfoForField(sci *sourceCodeInfo, fld *dpb.FieldDescriptorProto, path []int32) {
-	n := r.getFieldNode(fld)
+func (r *parseResult) generateSourceCodeInfoForEnumValue(sci *sourceCodeInfo, n *enumValueNode, path []int32) {
+	sci.newLoc(n, path)
+	sci.newLoc(n.name, append(path, internal.EnumVal_nameTag))
+	sci.newLoc(n.getNumber(), append(path, internal.EnumVal_numberTag))
 
+	// enum value options
+	if n.options != nil {
+		optsPath := append(path, internal.EnumVal_optionsTag)
+		sci.newLoc(n.options, optsPath)
+		var optIndex int32
+		for _, opt := range n.options.decls {
+			r.generateSourceCodeInfoForOption(sci, opt, true, &optIndex, optsPath)
+		}
+	}
+}
+
+func (r *parseResult) generateSourceCodeInfoForReservedRange(sci *sourceCodeInfo, n *rangeNode, path []int32) {
+	sci.newLoc(n, path)
+	sci.newLoc(n.stNode, append(path, internal.ReservedRange_startTag))
+	if n.stNode != n.enNode {
+		sci.newLoc(n.enNode, append(path, internal.ReservedRange_endTag))
+	}
+}
+
+func (r *parseResult) generateSourceCodeInfoForExtensions(sci *sourceCodeInfo, n *extendNode, extendIndex, msgIndex *int32, extendPath, msgPath []int32) {
+	sci.newLoc(n, extendPath)
+	for _, decl := range n.decls {
+		switch {
+		case decl.field != nil:
+			r.generateSourceCodeInfoForField(sci, decl.field, append(extendPath, *extendIndex))
+			*extendIndex++
+		case decl.group != nil:
+			fldPath := append(extendPath, *extendIndex)
+			r.generateSourceCodeInfoForField(sci, decl.group, fldPath)
+			*extendIndex++
+			r.generateSourceCodeInfoForMessage(sci, decl.group, fldPath, append(msgPath, *msgIndex))
+			*msgIndex++
+		}
+	}
+}
+
+func (r *parseResult) generateSourceCodeInfoForOneOf(sci *sourceCodeInfo, n *oneOfNode, fieldIndex, nestedMsgIndex *int32, fieldPath, nestedMsgPath, oneOfPath []int32) {
+	sci.newLoc(n, oneOfPath)
+	sci.newLoc(n.name, append(oneOfPath, internal.OneOf_nameTag))
+
+	var optIndex int32
+	for _, child := range n.decls {
+		switch {
+		case child.option != nil:
+			r.generateSourceCodeInfoForOption(sci, child.option, false, &optIndex, append(oneOfPath, internal.OneOf_optionsTag))
+		case child.field != nil:
+			r.generateSourceCodeInfoForField(sci, child.field, append(fieldPath, *fieldIndex))
+			*fieldIndex++
+		case child.group != nil:
+			fldPath := append(fieldPath, *fieldIndex)
+			r.generateSourceCodeInfoForField(sci, child.group, fldPath)
+			*fieldIndex++
+			r.generateSourceCodeInfoForMessage(sci, child.group, fldPath, append(nestedMsgPath, *nestedMsgIndex))
+			*nestedMsgIndex++
+		}
+	}
+}
+
+func (r *parseResult) generateSourceCodeInfoForField(sci *sourceCodeInfo, n fieldDecl, path []int32) {
 	isGroup := false
-	var opts []*optionNode
+	var opts *compactOptionsNode
 	var extendee *extendNode
+	var fieldType string
 	switch n := n.(type) {
 	case *fieldNode:
 		opts = n.options
 		extendee = n.extendee
+		fieldType = n.fldType.val
 	case *mapFieldNode:
 		opts = n.options
 	case *groupNode:
@@ -315,22 +293,105 @@
 		return
 	}
 
-	sci.newLoc(n, path)
-	if !isGroup {
-		sci.newLoc(n.fieldName(), append(path, internal.Field_nameTag))
+	if isGroup {
+		// comments will appear on group message
+		sci.newLocWithoutComments(n, path)
+		if extendee != nil {
+			sci.newLoc(extendee.extendee, append(path, internal.Field_extendeeTag))
+		}
+		if n.fieldLabel() != nil {
+			// no comments here either (label is first token for group, so we want
+			// to leave the comments to be associated with the group message instead)
+			sci.newLocWithoutComments(n.fieldLabel(), append(path, internal.Field_labelTag))
+		}
 		sci.newLoc(n.fieldType(), append(path, internal.Field_typeTag))
-	}
-	if n.fieldLabel() != nil {
-		sci.newLoc(n.fieldLabel(), append(path, internal.Field_labelTag))
+		// let the name comments be attributed to the group name
+		sci.newLocWithoutComments(n.fieldName(), append(path, internal.Field_nameTag))
+	} else {
+		sci.newLoc(n, path)
+		if extendee != nil {
+			sci.newLoc(extendee.extendee, append(path, internal.Field_extendeeTag))
+		}
+		if n.fieldLabel() != nil {
+			sci.newLoc(n.fieldLabel(), append(path, internal.Field_labelTag))
+		}
+		n.fieldType()
+		var tag int32
+		if _, isScalar := fieldTypes[fieldType]; isScalar {
+			tag = internal.Field_typeTag
+		} else {
+			// this is a message or an enum, so attribute type location
+			// to the type name field
+			tag = internal.Field_typeNameTag
+		}
+		sci.newLoc(n.fieldType(), append(path, tag))
+		sci.newLoc(n.fieldName(), append(path, internal.Field_nameTag))
 	}
 	sci.newLoc(n.fieldTag(), append(path, internal.Field_numberTag))
-	if extendee != nil {
-		sci.newLoc(extendee.extendee, append(path, internal.Field_extendeeTag))
-	}
 
-	r.generateSourceCodeInfoForOptions(sci, opts, func(n interface{}) *optionNode {
-		return n.(*optionNode)
-	}, fld.Options.GetUninterpretedOption(), append(path, internal.Field_optionsTag))
+	if opts != nil {
+		optsPath := append(path, internal.Field_optionsTag)
+		sci.newLoc(opts, optsPath)
+		var optIndex int32
+		for _, opt := range opts.decls {
+			r.generateSourceCodeInfoForOption(sci, opt, true, &optIndex, optsPath)
+		}
+	}
+}
+
+func (r *parseResult) generateSourceCodeInfoForExtensionRanges(sci *sourceCodeInfo, n *extensionRangeNode, extRangeIndex *int32, path []int32) {
+	sci.newLoc(n, path)
+	for _, child := range n.ranges {
+		path := append(path, *extRangeIndex)
+		*extRangeIndex++
+		sci.newLoc(child, path)
+		sci.newLoc(child.stNode, append(path, internal.ExtensionRange_startTag))
+		if child.stNode != child.enNode {
+			sci.newLoc(child.enNode, append(path, internal.ExtensionRange_endTag))
+		}
+		if n.options != nil {
+			optsPath := append(path, internal.ExtensionRange_optionsTag)
+			sci.newLoc(n.options, optsPath)
+			var optIndex int32
+			for _, opt := range n.options.decls {
+				r.generateSourceCodeInfoForOption(sci, opt, true, &optIndex, optsPath)
+			}
+		}
+	}
+}
+
+func (r *parseResult) generateSourceCodeInfoForService(sci *sourceCodeInfo, n *serviceNode, path []int32) {
+	sci.newLoc(n, path)
+	sci.newLoc(n.name, append(path, internal.Service_nameTag))
+	var optIndex, rpcIndex int32
+	for _, child := range n.decls {
+		switch {
+		case child.option != nil:
+			r.generateSourceCodeInfoForOption(sci, child.option, false, &optIndex, append(path, internal.Service_optionsTag))
+		case child.rpc != nil:
+			r.generateSourceCodeInfoForMethod(sci, child.rpc, append(path, internal.Service_methodsTag, rpcIndex))
+			rpcIndex++
+		}
+	}
+}
+
+func (r *parseResult) generateSourceCodeInfoForMethod(sci *sourceCodeInfo, n *methodNode, path []int32) {
+	sci.newLoc(n, path)
+	sci.newLoc(n.name, append(path, internal.Method_nameTag))
+	if n.input.streamKeyword != nil {
+		sci.newLoc(n.input.streamKeyword, append(path, internal.Method_inputStreamTag))
+	}
+	sci.newLoc(n.input.msgType, append(path, internal.Method_inputTag))
+	if n.output.streamKeyword != nil {
+		sci.newLoc(n.output.streamKeyword, append(path, internal.Method_outputStreamTag))
+	}
+	sci.newLoc(n.output.msgType, append(path, internal.Method_outputTag))
+
+	optsPath := append(path, internal.Method_optionsTag)
+	var optIndex int32
+	for _, opt := range n.options {
+		r.generateSourceCodeInfoForOption(sci, opt, false, &optIndex, optsPath)
+	}
 }
 
 type sourceCodeInfo struct {
@@ -338,6 +399,15 @@
 	commentsUsed map[*comment]struct{}
 }
 
+func (sci *sourceCodeInfo) newLocWithoutComments(n node, path []int32) {
+	dup := make([]int32, len(path))
+	copy(dup, path)
+	sci.locs = append(sci.locs, &dpb.SourceCodeInfo_Location{
+		Path: dup,
+		Span: makeSpan(n.start(), n.end()),
+	})
+}
+
 func (sci *sourceCodeInfo) newLoc(n node, path []int32) {
 	leadingComments := n.leadingComments()
 	trailingComments := n.trailingComments()
@@ -348,7 +418,10 @@
 		trailingComments = nil
 	}
 	detached := groupComments(leadingComments)
-	trail := combineComments(trailingComments)
+	var trail *string
+	if str, ok := combineComments(trailingComments); ok {
+		trail = proto.String(str)
+	}
 	var lead *string
 	if len(leadingComments) > 0 && leadingComments[len(leadingComments)-1].end.Line >= n.start().Line-1 {
 		lead = proto.String(detached[len(detached)-1])
@@ -356,34 +429,35 @@
 	}
 	dup := make([]int32, len(path))
 	copy(dup, path)
-	var span []int32
-	if n.start().Line == n.end().Line {
-		span = []int32{int32(n.start().Line) - 1, int32(n.start().Col) - 1, int32(n.end().Col) - 1}
-	} else {
-		span = []int32{int32(n.start().Line) - 1, int32(n.start().Col) - 1, int32(n.end().Line) - 1, int32(n.end().Col) - 1}
-	}
 	sci.locs = append(sci.locs, &dpb.SourceCodeInfo_Location{
 		LeadingDetachedComments: detached,
 		LeadingComments:         lead,
 		TrailingComments:        trail,
 		Path:                    dup,
-		Span:                    span,
+		Span:                    makeSpan(n.start(), n.end()),
 	})
 }
 
-func (sci *sourceCodeInfo) commentUsed(c []*comment) bool {
+func makeSpan(start, end *SourcePos) []int32 {
+	if start.Line == end.Line {
+		return []int32{int32(start.Line) - 1, int32(start.Col) - 1, int32(end.Col) - 1}
+	}
+	return []int32{int32(start.Line) - 1, int32(start.Col) - 1, int32(end.Line) - 1, int32(end.Col) - 1}
+}
+
+func (sci *sourceCodeInfo) commentUsed(c []comment) bool {
 	if len(c) == 0 {
 		return false
 	}
-	if _, ok := sci.commentsUsed[c[0]]; ok {
+	if _, ok := sci.commentsUsed[&c[0]]; ok {
 		return true
 	}
 
-	sci.commentsUsed[c[0]] = struct{}{}
+	sci.commentsUsed[&c[0]] = struct{}{}
 	return false
 }
 
-func groupComments(comments []*comment) []string {
+func groupComments(comments []comment) []string {
 	if len(comments) == 0 {
 		return nil
 	}
@@ -398,29 +472,26 @@
 		singleLineStyle = strings.HasPrefix(comments[i].text, "//")
 		if !singleLineStyle || prevSingleLine != singleLineStyle || c.start.Line > line+1 {
 			// new group!
-			groups = append(groups, *combineComments(comments[start:i]))
+			if str, ok := combineComments(comments[start:i]); ok {
+				groups = append(groups, str)
+			}
 			start = i
 		}
 		line = c.end.Line
 	}
 	// don't forget last group
-	groups = append(groups, *combineComments(comments[start:]))
-
+	if str, ok := combineComments(comments[start:]); ok {
+		groups = append(groups, str)
+	}
 	return groups
 }
 
-func combineComments(comments []*comment) *string {
+func combineComments(comments []comment) (string, bool) {
 	if len(comments) == 0 {
-		return nil
+		return "", false
 	}
-	first := true
 	var buf bytes.Buffer
 	for _, c := range comments {
-		if first {
-			first = false
-		} else {
-			buf.WriteByte('\n')
-		}
 		if c.text[:2] == "//" {
 			buf.WriteString(c.text[2:])
 		} else {
@@ -453,160 +524,9 @@
 			}
 		}
 	}
-	return proto.String(buf.String())
+	return buf.String(), true
 }
 
-func (sci *sourceCodeInfo) generateLocs() []*dpb.SourceCodeInfo_Location {
-	// generate intermediate locations: paths between root (inclusive) and the
-	// leaf locations already created, these will not have comments but will
-	// have aggregate span, than runs from min(start pos) to max(end pos) for
-	// all descendent paths.
-
-	if len(sci.locs) == 0 {
-		// nothing to generate
-		return nil
-	}
-
-	var root locTrie
-	for _, loc := range sci.locs {
-		root.add(loc.Path, loc)
-	}
-	root.fillIn()
-	locs := make([]*dpb.SourceCodeInfo_Location, 0, root.countLocs())
-	root.aggregate(&locs)
-	// finally, sort the resulting slice by location
-	sort.Slice(locs, func(i, j int) bool {
-		startI, endI := getSpanPositions(locs[i].Span)
-		startJ, endJ := getSpanPositions(locs[j].Span)
-		cmp := compareSlice(startI, startJ)
-		if cmp == 0 {
-			// if start position is the same, sort by end position _decreasing_
-			// (so enclosing locations will appear before leaves)
-			cmp = -compareSlice(endI, endJ)
-			if cmp == 0 {
-				// start and end position are the same? so break ties using path
-				cmp = compareSlice(locs[i].Path, locs[j].Path)
-			}
-		}
-		return cmp < 0
-	})
-	return locs
-}
-
-type locTrie struct {
-	children map[int32]*locTrie
-	loc      *dpb.SourceCodeInfo_Location
-}
-
-func (t *locTrie) add(path []int32, loc *dpb.SourceCodeInfo_Location) {
-	if len(path) == 0 {
-		t.loc = loc
-		return
-	}
-	child := t.children[path[0]]
-	if child == nil {
-		if t.children == nil {
-			t.children = map[int32]*locTrie{}
-		}
-		child = &locTrie{}
-		t.children[path[0]] = child
-	}
-	child.add(path[1:], loc)
-}
-
-func (t *locTrie) fillIn() {
-	var path []int32
-	var start, end []int32
-	for _, child := range t.children {
-		// recurse
-		child.fillIn()
-		if t.loc == nil {
-			// maintain min(start) and max(end) so we can
-			// populate t.loc below
-			childStart, childEnd := getSpanPositions(child.loc.Span)
-
-			if start == nil {
-				if path == nil {
-					path = child.loc.Path[:len(child.loc.Path)-1]
-				}
-				start = childStart
-				end = childEnd
-			} else {
-				if compareSlice(childStart, start) < 0 {
-					start = childStart
-				}
-				if compareSlice(childEnd, end) > 0 {
-					end = childEnd
-				}
-			}
-		}
-	}
-
-	if t.loc == nil {
-		var span []int32
-		// we don't use append below because we want a new slice
-		// that doesn't share underlying buffer with spans from
-		// any other location
-		if start[0] == end[0] {
-			span = []int32{start[0], start[1], end[1]}
-		} else {
-			span = []int32{start[0], start[1], end[0], end[1]}
-		}
-		t.loc = &dpb.SourceCodeInfo_Location{
-			Path: path,
-			Span: span,
-		}
-	}
-}
-
-func (t *locTrie) countLocs() int {
-	count := 0
-	if t.loc != nil {
-		count = 1
-	}
-	for _, ch := range t.children {
-		count += ch.countLocs()
-	}
-	return count
-}
-
-func (t *locTrie) aggregate(dest *[]*dpb.SourceCodeInfo_Location) {
-	if t.loc != nil {
-		*dest = append(*dest, t.loc)
-	}
-	for _, child := range t.children {
-		child.aggregate(dest)
-	}
-}
-
-func getSpanPositions(span []int32) (start, end []int32) {
-	start = span[:2]
-	if len(span) == 3 {
-		end = []int32{span[0], span[2]}
-	} else {
-		end = span[2:]
-	}
-	return
-}
-
-func compareSlice(a, b []int32) int {
-	end := len(a)
-	if len(b) < end {
-		end = len(b)
-	}
-	for i := 0; i < end; i++ {
-		if a[i] < b[i] {
-			return -1
-		}
-		if a[i] > b[i] {
-			return 1
-		}
-	}
-	if len(a) < len(b) {
-		return -1
-	}
-	if len(a) > len(b) {
-		return 1
-	}
-	return 0
+func dup(p []int32) []int32 {
+	return append(([]int32)(nil), p...)
 }
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/std_imports.go b/vendor/github.com/jhump/protoreflect/desc/protoparse/std_imports.go
index 59bcdd3..8fbc1fc 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoparse/std_imports.go
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/std_imports.go
@@ -42,8 +42,9 @@
 	standardImports = map[string]*dpb.FileDescriptorProto{}
 	for _, fn := range standardFilenames {
 		fd, err := internal.LoadFileDescriptor(fn)
-		if err == nil {
-			standardImports[fn] = fd
+		if err != nil {
+			panic(err.Error())
 		}
+		standardImports[fn] = fd
 	}
 }
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoparse/test-source-info.txt b/vendor/github.com/jhump/protoreflect/desc/protoparse/test-source-info.txt
index c03fd64..324fb19 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoparse/test-source-info.txt
+++ b/vendor/github.com/jhump/protoreflect/desc/protoparse/test-source-info.txt
@@ -3,7 +3,7 @@
 
 :
 desc_test_comments.proto:8:1
-desc_test_comments.proto:119:2
+desc_test_comments.proto:141:2
 
 
  > syntax:
@@ -11,18 +11,22 @@
 desc_test_comments.proto:8:19
     Leading detached comment [0]:
  This is the first detached comment for the syntax.
+
     Leading detached comment [1]:
 
  This is a second detached comment.
 
     Leading detached comment [2]:
  This is a third.
+
     Leading comments:
  Syntax comment...
+
     Trailing comments:
  Syntax trailer.
 
 
+
  > package:
 desc_test_comments.proto:12:1
 desc_test_comments.proto:12:17
@@ -30,6 +34,7 @@
  And now the package declaration
 
 
+
  > options:
 desc_test_comments.proto:15:1
 desc_test_comments.proto:15:75
@@ -42,10 +47,6 @@
  option comments FTW!!!
 
 
- > dependency:
-desc_test_comments.proto:17:1
-desc_test_comments.proto:18:34
-
 
  > dependency[0]:
 desc_test_comments.proto:17:1
@@ -57,23 +58,21 @@
 desc_test_comments.proto:18:34
 
 
- > message_type:
-desc_test_comments.proto:25:1
-desc_test_comments.proto:89:2
-
-
  > message_type[0]:
 desc_test_comments.proto:25:1
-desc_test_comments.proto:89:2
+desc_test_comments.proto:105:2
     Leading detached comment [0]:
  Multiple white space lines (like above) cannot
  be preserved...
+
     Leading comments:
  We need a request for our RPC service below.
+
     Trailing comments:
  And next we'll need some extensions...
 
 
+
  > message_type[0] > name:
 desc_test_comments.proto:25:68
 desc_test_comments.proto:25:75
@@ -85,48 +84,49 @@
  trailer
 
 
+
  > message_type[0] > options:
-desc_test_comments.proto:26:3
-desc_test_comments.proto:35:54
+desc_test_comments.proto:26:9
+desc_test_comments.proto:26:34
 
 
  > message_type[0] > options > deprecated:
-desc_test_comments.proto:26:3
-desc_test_comments.proto:26:28
+desc_test_comments.proto:26:9
+desc_test_comments.proto:26:34
+    Trailing comments:
+ deprecated!
 
 
- > message_type[0] > field:
-desc_test_comments.proto:29:2
-desc_test_comments.proto:66:3
-
 
  > message_type[0] > field[0]:
-desc_test_comments.proto:29:2
-desc_test_comments.proto:32:92
+desc_test_comments.proto:29:9
+desc_test_comments.proto:32:132
     Leading comments:
  A field comment
+
     Trailing comments:
  field trailer #1...
 
 
+
  > message_type[0] > field[0] > label:
-desc_test_comments.proto:29:2
-desc_test_comments.proto:29:10
+desc_test_comments.proto:29:9
+desc_test_comments.proto:29:17
 
 
  > message_type[0] > field[0] > type:
-desc_test_comments.proto:29:11
-desc_test_comments.proto:29:16
+desc_test_comments.proto:29:18
+desc_test_comments.proto:29:23
 
 
  > message_type[0] > field[0] > name:
-desc_test_comments.proto:29:17
-desc_test_comments.proto:29:20
+desc_test_comments.proto:29:24
+desc_test_comments.proto:29:27
 
 
  > message_type[0] > field[0] > number:
-desc_test_comments.proto:29:63
-desc_test_comments.proto:29:64
+desc_test_comments.proto:29:70
+desc_test_comments.proto:29:71
     Leading detached comment [0]:
  detached tag 
     Leading comments:
@@ -138,84 +138,97 @@
 
 
  > message_type[0] > field[0] > options:
-desc_test_comments.proto:32:5
-desc_test_comments.proto:32:90
+desc_test_comments.proto:32:11
+desc_test_comments.proto:32:131
 
 
  > message_type[0] > field[0] > options > packed:
-desc_test_comments.proto:32:5
-desc_test_comments.proto:32:16
+desc_test_comments.proto:32:12
+desc_test_comments.proto:32:23
+    Trailing comments:
+ packed! 
 
 
  > message_type[0] > field[0] > json_name:
-desc_test_comments.proto:32:18
-desc_test_comments.proto:32:35
-
-
- > message_type[0] > field[0] > options > ffubar:
-desc_test_comments.proto:32:37
-desc_test_comments.proto:32:62
+desc_test_comments.proto:32:39
+desc_test_comments.proto:32:56
+    Trailing comments:
+ custom JSON! 
 
 
  > message_type[0] > field[0] > options > ffubar[0]:
-desc_test_comments.proto:32:37
-desc_test_comments.proto:32:62
+desc_test_comments.proto:32:77
+desc_test_comments.proto:32:102
 
 
  > message_type[0] > field[0] > options > ffubarb:
-desc_test_comments.proto:32:64
-desc_test_comments.proto:32:90
+desc_test_comments.proto:32:104
+desc_test_comments.proto:32:130
+
+
+ > message_type[0] > options:
+desc_test_comments.proto:35:27
+desc_test_comments.proto:35:61
 
 
  > message_type[0] > options > mfubar:
-desc_test_comments.proto:35:20
-desc_test_comments.proto:35:54
+desc_test_comments.proto:35:27
+desc_test_comments.proto:35:61
     Leading comments:
  lead mfubar 
     Trailing comments:
  trailing mfubar
 
 
+
  > message_type[0] > field[1]:
-desc_test_comments.proto:42:22
-desc_test_comments.proto:43:63
+desc_test_comments.proto:42:29
+desc_test_comments.proto:43:77
     Leading detached comment [0]:
  some detached comments
+
     Leading detached comment [1]:
  some detached comments
+
     Leading detached comment [2]:
  Another field comment
+
     Leading comments:
  label comment 
 
 
  > message_type[0] > field[1] > label:
-desc_test_comments.proto:42:22
-desc_test_comments.proto:42:30
+desc_test_comments.proto:42:29
+desc_test_comments.proto:42:37
 
 
  > message_type[0] > field[1] > type:
-desc_test_comments.proto:42:50
-desc_test_comments.proto:42:56
+desc_test_comments.proto:42:57
+desc_test_comments.proto:42:63
     Leading comments:
  type comment 
 
 
  > message_type[0] > field[1] > name:
-desc_test_comments.proto:42:76
-desc_test_comments.proto:42:80
+desc_test_comments.proto:42:83
+desc_test_comments.proto:42:87
     Leading comments:
  name comment 
 
 
  > message_type[0] > field[1] > number:
-desc_test_comments.proto:42:83
-desc_test_comments.proto:42:84
+desc_test_comments.proto:42:90
+desc_test_comments.proto:42:91
+
+
+ > message_type[0] > field[1] > options:
+desc_test_comments.proto:43:17
+desc_test_comments.proto:43:76
 
 
  > message_type[0] > field[1] > default_value:
-desc_test_comments.proto:43:23
-desc_test_comments.proto:43:40
+desc_test_comments.proto:43:37
+desc_test_comments.proto:43:54
     Leading comments:
  default lead 
     Trailing comments:
@@ -223,627 +236,826 @@
 
 
  > message_type[0] > extension_range:
-desc_test_comments.proto:46:13
-desc_test_comments.proto:47:23
+desc_test_comments.proto:46:9
+desc_test_comments.proto:46:31
+    Leading comments:
+ extension range comments are (sadly) not preserved
+
 
 
  > message_type[0] > extension_range[0]:
-desc_test_comments.proto:46:13
-desc_test_comments.proto:46:23
+desc_test_comments.proto:46:20
+desc_test_comments.proto:46:30
 
 
  > message_type[0] > extension_range[0] > start:
-desc_test_comments.proto:46:13
-desc_test_comments.proto:46:16
-
-
- > message_type[0] > extension_range[0] > end:
 desc_test_comments.proto:46:20
 desc_test_comments.proto:46:23
 
 
+ > message_type[0] > extension_range[0] > end:
+desc_test_comments.proto:46:27
+desc_test_comments.proto:46:30
+
+
+ > message_type[0] > extension_range:
+desc_test_comments.proto:47:9
+desc_test_comments.proto:47:109
+
+
  > message_type[0] > extension_range[1]:
-desc_test_comments.proto:47:13
-desc_test_comments.proto:47:23
+desc_test_comments.proto:47:20
+desc_test_comments.proto:47:30
 
 
  > message_type[0] > extension_range[1] > start:
-desc_test_comments.proto:47:13
-desc_test_comments.proto:47:16
-
-
- > message_type[0] > extension_range[1] > end:
 desc_test_comments.proto:47:20
 desc_test_comments.proto:47:23
 
 
+ > message_type[0] > extension_range[1] > end:
+desc_test_comments.proto:47:27
+desc_test_comments.proto:47:30
+
+
  > message_type[0] > extension_range[1] > options:
-desc_test_comments.proto:47:25
-desc_test_comments.proto:47:100
+desc_test_comments.proto:47:31
+desc_test_comments.proto:47:108
 
 
  > message_type[0] > extension_range[1] > options > exfubarb:
-desc_test_comments.proto:47:25
-desc_test_comments.proto:47:67
-
-
- > message_type[0] > extension_range[1] > options > exfubar:
-desc_test_comments.proto:47:69
-desc_test_comments.proto:47:100
+desc_test_comments.proto:47:32
+desc_test_comments.proto:47:74
 
 
  > message_type[0] > extension_range[1] > options > exfubar[0]:
-desc_test_comments.proto:47:69
-desc_test_comments.proto:47:100
+desc_test_comments.proto:47:76
+desc_test_comments.proto:47:107
 
 
  > message_type[0] > reserved_range:
-desc_test_comments.proto:51:50
-desc_test_comments.proto:51:68
+desc_test_comments.proto:51:48
+desc_test_comments.proto:51:77
+    Leading detached comment [0]:
+ another detached comment
+
+    Leading comments:
+ same for reserved range comments 
 
 
  > message_type[0] > reserved_range[0]:
-desc_test_comments.proto:51:50
-desc_test_comments.proto:51:58
+desc_test_comments.proto:51:57
+desc_test_comments.proto:51:65
 
 
  > message_type[0] > reserved_range[0] > start:
-desc_test_comments.proto:51:50
-desc_test_comments.proto:51:52
+desc_test_comments.proto:51:57
+desc_test_comments.proto:51:59
 
 
  > message_type[0] > reserved_range[0] > end:
-desc_test_comments.proto:51:56
-desc_test_comments.proto:51:58
+desc_test_comments.proto:51:63
+desc_test_comments.proto:51:65
 
 
  > message_type[0] > reserved_range[1]:
-desc_test_comments.proto:51:60
-desc_test_comments.proto:51:68
+desc_test_comments.proto:51:67
+desc_test_comments.proto:51:75
 
 
  > message_type[0] > reserved_range[1] > start:
-desc_test_comments.proto:51:60
-desc_test_comments.proto:51:62
+desc_test_comments.proto:51:67
+desc_test_comments.proto:51:69
 
 
  > message_type[0] > reserved_range[1] > end:
-desc_test_comments.proto:51:66
-desc_test_comments.proto:51:68
+desc_test_comments.proto:51:73
+desc_test_comments.proto:51:75
 
 
  > message_type[0] > reserved_name:
-desc_test_comments.proto:52:11
-desc_test_comments.proto:52:30
+desc_test_comments.proto:52:9
+desc_test_comments.proto:52:38
+    Trailing comments:
+ reserved trailers 
 
 
  > message_type[0] > reserved_name[0]:
-desc_test_comments.proto:52:11
-desc_test_comments.proto:52:16
-
-
- > message_type[0] > reserved_name[1]:
 desc_test_comments.proto:52:18
 desc_test_comments.proto:52:23
 
 
- > message_type[0] > reserved_name[2]:
+ > message_type[0] > reserved_name[1]:
 desc_test_comments.proto:52:25
 desc_test_comments.proto:52:30
 
 
+ > message_type[0] > reserved_name[2]:
+desc_test_comments.proto:52:32
+desc_test_comments.proto:52:37
+
+
  > message_type[0] > field[2]:
-desc_test_comments.proto:55:2
-desc_test_comments.proto:66:3
+desc_test_comments.proto:55:9
+desc_test_comments.proto:67:10
+
+
+ > message_type[0] > field[2] > label:
+desc_test_comments.proto:55:9
+desc_test_comments.proto:55:17
+
+
+ > message_type[0] > field[2] > type:
+desc_test_comments.proto:55:18
+desc_test_comments.proto:55:23
+
+
+ > message_type[0] > field[2] > name:
+desc_test_comments.proto:55:41
+desc_test_comments.proto:55:47
+
+
+ > message_type[0] > field[2] > number:
+desc_test_comments.proto:55:50
+desc_test_comments.proto:55:51
+
+
+ > message_type[0] > nested_type[0]:
+desc_test_comments.proto:55:9
+desc_test_comments.proto:67:10
     Leading comments:
  Group comment
 
 
- > message_type[0] > nested_type:
-desc_test_comments.proto:55:2
-desc_test_comments.proto:66:3
-
-
- > message_type[0] > nested_type[0]:
-desc_test_comments.proto:55:2
-desc_test_comments.proto:66:3
-
-
- > message_type[0] > field[2] > label:
-desc_test_comments.proto:55:2
-desc_test_comments.proto:55:10
-
 
  > message_type[0] > nested_type[0] > name:
-desc_test_comments.proto:55:34
-desc_test_comments.proto:55:40
+desc_test_comments.proto:55:41
+desc_test_comments.proto:55:47
     Leading comments:
  group name 
 
 
- > message_type[0] > field[2] > number:
-desc_test_comments.proto:55:43
-desc_test_comments.proto:55:44
+ > message_type[0] > field[2] > type_name:
+desc_test_comments.proto:55:41
+desc_test_comments.proto:55:47
 
 
  > message_type[0] > nested_type[0] > options:
-desc_test_comments.proto:56:3
-desc_test_comments.proto:61:50
+desc_test_comments.proto:57:17
+desc_test_comments.proto:57:52
 
 
  > message_type[0] > nested_type[0] > options > mfubar:
-desc_test_comments.proto:56:3
-desc_test_comments.proto:56:38
+desc_test_comments.proto:57:17
+desc_test_comments.proto:57:52
+    Leading comments:
+ this is a custom option
 
 
- > message_type[0] > nested_type[0] > field:
-desc_test_comments.proto:58:3
-desc_test_comments.proto:64:27
-
 
  > message_type[0] > nested_type[0] > field[0]:
-desc_test_comments.proto:58:3
-desc_test_comments.proto:58:27
+desc_test_comments.proto:59:17
+desc_test_comments.proto:59:41
 
 
  > message_type[0] > nested_type[0] > field[0] > label:
-desc_test_comments.proto:58:3
-desc_test_comments.proto:58:11
-
-
- > message_type[0] > nested_type[0] > field[0] > type:
-desc_test_comments.proto:58:12
-desc_test_comments.proto:58:18
-
-
- > message_type[0] > nested_type[0] > field[0] > name:
-desc_test_comments.proto:58:19
-desc_test_comments.proto:58:22
-
-
- > message_type[0] > nested_type[0] > field[0] > number:
-desc_test_comments.proto:58:25
-desc_test_comments.proto:58:26
-
-
- > message_type[0] > nested_type[0] > field[1]:
-desc_test_comments.proto:59:3
-desc_test_comments.proto:59:26
-
-
- > message_type[0] > nested_type[0] > field[1] > label:
-desc_test_comments.proto:59:3
-desc_test_comments.proto:59:11
-
-
- > message_type[0] > nested_type[0] > field[1] > type:
-desc_test_comments.proto:59:12
 desc_test_comments.proto:59:17
-
-
- > message_type[0] > nested_type[0] > field[1] > name:
-desc_test_comments.proto:59:18
-desc_test_comments.proto:59:21
-
-
- > message_type[0] > nested_type[0] > field[1] > number:
-desc_test_comments.proto:59:24
 desc_test_comments.proto:59:25
 
 
+ > message_type[0] > nested_type[0] > field[0] > type:
+desc_test_comments.proto:59:26
+desc_test_comments.proto:59:32
+
+
+ > message_type[0] > nested_type[0] > field[0] > name:
+desc_test_comments.proto:59:33
+desc_test_comments.proto:59:36
+
+
+ > message_type[0] > nested_type[0] > field[0] > number:
+desc_test_comments.proto:59:39
+desc_test_comments.proto:59:40
+
+
+ > message_type[0] > nested_type[0] > field[1]:
+desc_test_comments.proto:60:17
+desc_test_comments.proto:60:40
+
+
+ > message_type[0] > nested_type[0] > field[1] > label:
+desc_test_comments.proto:60:17
+desc_test_comments.proto:60:25
+
+
+ > message_type[0] > nested_type[0] > field[1] > type:
+desc_test_comments.proto:60:26
+desc_test_comments.proto:60:31
+
+
+ > message_type[0] > nested_type[0] > field[1] > name:
+desc_test_comments.proto:60:32
+desc_test_comments.proto:60:35
+
+
+ > message_type[0] > nested_type[0] > field[1] > number:
+desc_test_comments.proto:60:38
+desc_test_comments.proto:60:39
+
+
+ > message_type[0] > nested_type[0] > options:
+desc_test_comments.proto:62:17
+desc_test_comments.proto:62:64
+
+
  > message_type[0] > nested_type[0] > options > no_standard_descriptor_accessor:
-desc_test_comments.proto:61:3
-desc_test_comments.proto:61:50
+desc_test_comments.proto:62:17
+desc_test_comments.proto:62:64
 
 
  > message_type[0] > nested_type[0] > field[2]:
-desc_test_comments.proto:64:3
-desc_test_comments.proto:64:27
+desc_test_comments.proto:65:17
+desc_test_comments.proto:65:41
     Leading comments:
  Leading comment...
+
     Trailing comments:
  Trailing comment...
 
 
+
  > message_type[0] > nested_type[0] > field[2] > label:
-desc_test_comments.proto:64:3
-desc_test_comments.proto:64:11
+desc_test_comments.proto:65:17
+desc_test_comments.proto:65:25
 
 
  > message_type[0] > nested_type[0] > field[2] > type:
-desc_test_comments.proto:64:12
-desc_test_comments.proto:64:18
+desc_test_comments.proto:65:26
+desc_test_comments.proto:65:32
 
 
  > message_type[0] > nested_type[0] > field[2] > name:
-desc_test_comments.proto:64:19
-desc_test_comments.proto:64:22
+desc_test_comments.proto:65:33
+desc_test_comments.proto:65:36
 
 
  > message_type[0] > nested_type[0] > field[2] > number:
-desc_test_comments.proto:64:25
-desc_test_comments.proto:64:26
-
-
- > message_type[0] > enum_type:
-desc_test_comments.proto:68:2
-desc_test_comments.proto:88:3
+desc_test_comments.proto:65:39
+desc_test_comments.proto:65:40
 
 
  > message_type[0] > enum_type[0]:
-desc_test_comments.proto:68:2
-desc_test_comments.proto:88:3
+desc_test_comments.proto:69:9
+desc_test_comments.proto:90:10
 
 
  > message_type[0] > enum_type[0] > name:
-desc_test_comments.proto:68:7
-desc_test_comments.proto:68:22
+desc_test_comments.proto:69:14
+desc_test_comments.proto:69:29
     Trailing comments:
  "super"!
 
 
- > message_type[0] > enum_type[0] > value:
-desc_test_comments.proto:72:3
-desc_test_comments.proto:85:17
+
+ > message_type[0] > enum_type[0] > options:
+desc_test_comments.proto:72:17
+desc_test_comments.proto:72:43
+
+
+ > message_type[0] > enum_type[0] > options > allow_alias:
+desc_test_comments.proto:72:17
+desc_test_comments.proto:72:43
+    Leading comments:
+ allow_alias comments!
+
 
 
  > message_type[0] > enum_type[0] > value[0]:
-desc_test_comments.proto:72:3
-desc_test_comments.proto:72:72
+desc_test_comments.proto:74:17
+desc_test_comments.proto:74:86
 
 
  > message_type[0] > enum_type[0] > value[0] > name:
-desc_test_comments.proto:72:3
-desc_test_comments.proto:72:8
+desc_test_comments.proto:74:17
+desc_test_comments.proto:74:22
 
 
  > message_type[0] > enum_type[0] > value[0] > number:
-desc_test_comments.proto:72:11
-desc_test_comments.proto:72:12
+desc_test_comments.proto:74:25
+desc_test_comments.proto:74:26
 
 
  > message_type[0] > enum_type[0] > value[0] > options:
-desc_test_comments.proto:72:14
-desc_test_comments.proto:72:70
+desc_test_comments.proto:74:27
+desc_test_comments.proto:74:85
 
 
  > message_type[0] > enum_type[0] > value[0] > options > evfubars:
-desc_test_comments.proto:72:14
-desc_test_comments.proto:72:42
+desc_test_comments.proto:74:28
+desc_test_comments.proto:74:56
 
 
  > message_type[0] > enum_type[0] > value[0] > options > evfubar:
-desc_test_comments.proto:72:44
-desc_test_comments.proto:72:70
+desc_test_comments.proto:74:58
+desc_test_comments.proto:74:84
 
 
  > message_type[0] > enum_type[0] > value[1]:
-desc_test_comments.proto:73:3
-desc_test_comments.proto:73:86
+desc_test_comments.proto:75:17
+desc_test_comments.proto:75:100
 
 
  > message_type[0] > enum_type[0] > value[1] > name:
-desc_test_comments.proto:73:3
-desc_test_comments.proto:73:8
+desc_test_comments.proto:75:17
+desc_test_comments.proto:75:22
 
 
  > message_type[0] > enum_type[0] > value[1] > number:
-desc_test_comments.proto:73:11
-desc_test_comments.proto:73:12
+desc_test_comments.proto:75:25
+desc_test_comments.proto:75:26
 
 
  > message_type[0] > enum_type[0] > value[1] > options:
-desc_test_comments.proto:73:15
-desc_test_comments.proto:73:84
+desc_test_comments.proto:75:27
+desc_test_comments.proto:75:99
 
 
  > message_type[0] > enum_type[0] > value[1] > options > evfubaruf:
-desc_test_comments.proto:73:15
-desc_test_comments.proto:73:43
+desc_test_comments.proto:75:29
+desc_test_comments.proto:75:57
 
 
  > message_type[0] > enum_type[0] > value[1] > options > evfubaru:
-desc_test_comments.proto:73:59
-desc_test_comments.proto:73:84
+desc_test_comments.proto:75:73
+desc_test_comments.proto:75:98
 
 
  > message_type[0] > enum_type[0] > value[2]:
-desc_test_comments.proto:74:3
-desc_test_comments.proto:74:13
+desc_test_comments.proto:76:17
+desc_test_comments.proto:76:27
 
 
  > message_type[0] > enum_type[0] > value[2] > name:
-desc_test_comments.proto:74:3
-desc_test_comments.proto:74:8
+desc_test_comments.proto:76:17
+desc_test_comments.proto:76:22
 
 
  > message_type[0] > enum_type[0] > value[2] > number:
-desc_test_comments.proto:74:11
-desc_test_comments.proto:74:12
+desc_test_comments.proto:76:25
+desc_test_comments.proto:76:26
 
 
  > message_type[0] > enum_type[0] > value[3]:
-desc_test_comments.proto:75:3
-desc_test_comments.proto:75:14
+desc_test_comments.proto:77:17
+desc_test_comments.proto:77:28
 
 
  > message_type[0] > enum_type[0] > value[3] > name:
-desc_test_comments.proto:75:3
-desc_test_comments.proto:75:9
+desc_test_comments.proto:77:17
+desc_test_comments.proto:77:23
 
 
  > message_type[0] > enum_type[0] > value[3] > number:
-desc_test_comments.proto:75:12
-desc_test_comments.proto:75:13
+desc_test_comments.proto:77:26
+desc_test_comments.proto:77:27
 
 
  > message_type[0] > enum_type[0] > options:
-desc_test_comments.proto:77:3
-desc_test_comments.proto:87:36
+desc_test_comments.proto:79:17
+desc_test_comments.proto:79:52
 
 
  > message_type[0] > enum_type[0] > options > efubars:
-desc_test_comments.proto:77:3
-desc_test_comments.proto:77:38
+desc_test_comments.proto:79:17
+desc_test_comments.proto:79:52
 
 
  > message_type[0] > enum_type[0] > value[4]:
-desc_test_comments.proto:79:3
-desc_test_comments.proto:79:13
+desc_test_comments.proto:81:17
+desc_test_comments.proto:81:27
 
 
  > message_type[0] > enum_type[0] > value[4] > name:
-desc_test_comments.proto:79:3
-desc_test_comments.proto:79:8
+desc_test_comments.proto:81:17
+desc_test_comments.proto:81:22
 
 
  > message_type[0] > enum_type[0] > value[4] > number:
-desc_test_comments.proto:79:11
-desc_test_comments.proto:79:12
+desc_test_comments.proto:81:25
+desc_test_comments.proto:81:26
 
 
  > message_type[0] > enum_type[0] > value[5]:
-desc_test_comments.proto:80:3
-desc_test_comments.proto:80:15
+desc_test_comments.proto:82:17
+desc_test_comments.proto:82:29
 
 
  > message_type[0] > enum_type[0] > value[5] > name:
-desc_test_comments.proto:80:3
-desc_test_comments.proto:80:10
+desc_test_comments.proto:82:17
+desc_test_comments.proto:82:24
 
 
  > message_type[0] > enum_type[0] > value[5] > number:
-desc_test_comments.proto:80:13
-desc_test_comments.proto:80:14
+desc_test_comments.proto:82:27
+desc_test_comments.proto:82:28
 
 
  > message_type[0] > enum_type[0] > value[6]:
-desc_test_comments.proto:81:3
-desc_test_comments.proto:81:46
+desc_test_comments.proto:83:17
+desc_test_comments.proto:83:60
 
 
  > message_type[0] > enum_type[0] > value[6] > name:
-desc_test_comments.proto:81:3
-desc_test_comments.proto:81:10
+desc_test_comments.proto:83:17
+desc_test_comments.proto:83:24
 
 
  > message_type[0] > enum_type[0] > value[6] > number:
-desc_test_comments.proto:81:13
-desc_test_comments.proto:81:14
+desc_test_comments.proto:83:27
+desc_test_comments.proto:83:28
 
 
  > message_type[0] > enum_type[0] > value[6] > options:
-desc_test_comments.proto:81:16
-desc_test_comments.proto:81:44
+desc_test_comments.proto:83:29
+desc_test_comments.proto:83:59
 
 
  > message_type[0] > enum_type[0] > value[6] > options > evfubarsf:
-desc_test_comments.proto:81:16
-desc_test_comments.proto:81:44
+desc_test_comments.proto:83:30
+desc_test_comments.proto:83:58
 
 
  > message_type[0] > enum_type[0] > value[7]:
-desc_test_comments.proto:82:3
-desc_test_comments.proto:82:14
+desc_test_comments.proto:84:17
+desc_test_comments.proto:84:28
 
 
  > message_type[0] > enum_type[0] > value[7] > name:
-desc_test_comments.proto:82:3
-desc_test_comments.proto:82:9
+desc_test_comments.proto:84:17
+desc_test_comments.proto:84:23
 
 
  > message_type[0] > enum_type[0] > value[7] > number:
-desc_test_comments.proto:82:12
-desc_test_comments.proto:82:13
+desc_test_comments.proto:84:26
+desc_test_comments.proto:84:27
 
 
  > message_type[0] > enum_type[0] > value[8]:
-desc_test_comments.proto:83:3
-desc_test_comments.proto:83:17
+desc_test_comments.proto:85:17
+desc_test_comments.proto:85:31
 
 
  > message_type[0] > enum_type[0] > value[8] > name:
-desc_test_comments.proto:83:3
-desc_test_comments.proto:83:12
+desc_test_comments.proto:85:17
+desc_test_comments.proto:85:26
 
 
  > message_type[0] > enum_type[0] > value[8] > number:
-desc_test_comments.proto:83:15
-desc_test_comments.proto:83:16
+desc_test_comments.proto:85:29
+desc_test_comments.proto:85:30
 
 
  > message_type[0] > enum_type[0] > value[9]:
-desc_test_comments.proto:84:3
-desc_test_comments.proto:84:13
+desc_test_comments.proto:86:17
+desc_test_comments.proto:86:27
 
 
  > message_type[0] > enum_type[0] > value[9] > name:
-desc_test_comments.proto:84:3
-desc_test_comments.proto:84:8
+desc_test_comments.proto:86:17
+desc_test_comments.proto:86:22
 
 
  > message_type[0] > enum_type[0] > value[9] > number:
-desc_test_comments.proto:84:11
-desc_test_comments.proto:84:12
+desc_test_comments.proto:86:25
+desc_test_comments.proto:86:26
 
 
  > message_type[0] > enum_type[0] > value[10]:
-desc_test_comments.proto:85:3
-desc_test_comments.proto:85:17
+desc_test_comments.proto:87:17
+desc_test_comments.proto:87:31
 
 
  > message_type[0] > enum_type[0] > value[10] > name:
-desc_test_comments.proto:85:3
-desc_test_comments.proto:85:9
+desc_test_comments.proto:87:17
+desc_test_comments.proto:87:23
 
 
  > message_type[0] > enum_type[0] > value[10] > number:
-desc_test_comments.proto:85:12
-desc_test_comments.proto:85:16
+desc_test_comments.proto:87:26
+desc_test_comments.proto:87:30
+
+
+ > message_type[0] > enum_type[0] > options:
+desc_test_comments.proto:89:17
+desc_test_comments.proto:89:50
 
 
  > message_type[0] > enum_type[0] > options > efubar:
-desc_test_comments.proto:87:3
-desc_test_comments.proto:87:36
+desc_test_comments.proto:89:17
+desc_test_comments.proto:89:50
 
 
- > extension[0] > extendee:
-desc_test_comments.proto:94:1
-desc_test_comments.proto:94:8
+ > message_type[0] > oneof_decl[0]:
+desc_test_comments.proto:93:9
+desc_test_comments.proto:96:10
     Leading comments:
- extendee comment
+ can be this or that
 
 
- > extension[1] > extendee:
-desc_test_comments.proto:94:1
-desc_test_comments.proto:94:8
+
+ > message_type[0] > oneof_decl[0] > name:
+desc_test_comments.proto:93:15
+desc_test_comments.proto:93:18
+
+
+ > message_type[0] > field[3]:
+desc_test_comments.proto:94:17
+desc_test_comments.proto:94:33
+
+
+ > message_type[0] > field[3] > type:
+desc_test_comments.proto:94:17
+desc_test_comments.proto:94:23
+
+
+ > message_type[0] > field[3] > name:
+desc_test_comments.proto:94:24
+desc_test_comments.proto:94:28
+
+
+ > message_type[0] > field[3] > number:
+desc_test_comments.proto:94:31
+desc_test_comments.proto:94:32
+
+
+ > message_type[0] > field[4]:
+desc_test_comments.proto:95:17
+desc_test_comments.proto:95:32
+
+
+ > message_type[0] > field[4] > type:
+desc_test_comments.proto:95:17
+desc_test_comments.proto:95:22
+
+
+ > message_type[0] > field[4] > name:
+desc_test_comments.proto:95:23
+desc_test_comments.proto:95:27
+
+
+ > message_type[0] > field[4] > number:
+desc_test_comments.proto:95:30
+desc_test_comments.proto:95:31
+
+
+ > message_type[0] > oneof_decl[1]:
+desc_test_comments.proto:98:9
+desc_test_comments.proto:101:10
+    Leading comments:
+ can be these or those
+
+
+
+ > message_type[0] > oneof_decl[1] > name:
+desc_test_comments.proto:98:15
+desc_test_comments.proto:98:18
+
+
+ > message_type[0] > field[5]:
+desc_test_comments.proto:99:17
+desc_test_comments.proto:99:34
+
+
+ > message_type[0] > field[5] > type:
+desc_test_comments.proto:99:17
+desc_test_comments.proto:99:23
+
+
+ > message_type[0] > field[5] > name:
+desc_test_comments.proto:99:24
+desc_test_comments.proto:99:29
+
+
+ > message_type[0] > field[5] > number:
+desc_test_comments.proto:99:32
+desc_test_comments.proto:99:33
+
+
+ > message_type[0] > field[6]:
+desc_test_comments.proto:100:17
+desc_test_comments.proto:100:33
+
+
+ > message_type[0] > field[6] > type:
+desc_test_comments.proto:100:17
+desc_test_comments.proto:100:22
+
+
+ > message_type[0] > field[6] > name:
+desc_test_comments.proto:100:23
+desc_test_comments.proto:100:28
+
+
+ > message_type[0] > field[6] > number:
+desc_test_comments.proto:100:31
+desc_test_comments.proto:100:32
+
+
+ > message_type[0] > field[7]:
+desc_test_comments.proto:104:9
+desc_test_comments.proto:104:40
+    Leading comments:
+ map field
+
+
+
+ > message_type[0] > field[7] > type_name:
+desc_test_comments.proto:104:9
+desc_test_comments.proto:104:28
+
+
+ > message_type[0] > field[7] > name:
+desc_test_comments.proto:104:29
+desc_test_comments.proto:104:35
+
+
+ > message_type[0] > field[7] > number:
+desc_test_comments.proto:104:38
+desc_test_comments.proto:104:39
 
 
  > extension:
-desc_test_comments.proto:96:2
-desc_test_comments.proto:98:30
+desc_test_comments.proto:108:1
+desc_test_comments.proto:117:2
+    Trailing comments:
+ extend trailer...
+
 
 
  > extension[0]:
-desc_test_comments.proto:96:2
-desc_test_comments.proto:96:30
+desc_test_comments.proto:114:9
+desc_test_comments.proto:114:37
     Leading comments:
  comment for guid1
 
 
+
+ > extension[0] > extendee:
+desc_test_comments.proto:110:1
+desc_test_comments.proto:110:8
+    Leading comments:
+ extendee comment
+
+    Trailing comments:
+ extendee trailer
+
+
+
  > extension[0] > label:
-desc_test_comments.proto:96:2
-desc_test_comments.proto:96:10
+desc_test_comments.proto:114:9
+desc_test_comments.proto:114:17
 
 
  > extension[0] > type:
-desc_test_comments.proto:96:11
-desc_test_comments.proto:96:17
+desc_test_comments.proto:114:18
+desc_test_comments.proto:114:24
 
 
  > extension[0] > name:
-desc_test_comments.proto:96:18
-desc_test_comments.proto:96:23
+desc_test_comments.proto:114:25
+desc_test_comments.proto:114:30
 
 
  > extension[0] > number:
-desc_test_comments.proto:96:26
-desc_test_comments.proto:96:29
+desc_test_comments.proto:114:33
+desc_test_comments.proto:114:36
 
 
  > extension[1]:
-desc_test_comments.proto:98:2
-desc_test_comments.proto:98:30
+desc_test_comments.proto:116:9
+desc_test_comments.proto:116:37
     Leading comments:
  ... and a comment for guid2
 
 
+
+ > extension[1] > extendee:
+desc_test_comments.proto:110:1
+desc_test_comments.proto:110:8
+
+
  > extension[1] > label:
-desc_test_comments.proto:98:2
-desc_test_comments.proto:98:10
+desc_test_comments.proto:116:9
+desc_test_comments.proto:116:17
 
 
  > extension[1] > type:
-desc_test_comments.proto:98:11
-desc_test_comments.proto:98:17
+desc_test_comments.proto:116:18
+desc_test_comments.proto:116:24
 
 
  > extension[1] > name:
-desc_test_comments.proto:98:18
-desc_test_comments.proto:98:23
+desc_test_comments.proto:116:25
+desc_test_comments.proto:116:30
 
 
  > extension[1] > number:
-desc_test_comments.proto:98:26
-desc_test_comments.proto:98:29
+desc_test_comments.proto:116:33
+desc_test_comments.proto:116:36
 
 
- > service:
-desc_test_comments.proto:103:1
-desc_test_comments.proto:119:2
+ > message_type[1]:
+desc_test_comments.proto:120:1
+desc_test_comments.proto:120:81
+
+
+ > message_type[1] > name:
+desc_test_comments.proto:120:36
+desc_test_comments.proto:120:50
+    Leading comments:
+ name leading comment 
+    Trailing comments:
+ name trailing comment 
 
 
  > service[0]:
-desc_test_comments.proto:103:1
-desc_test_comments.proto:119:2
+desc_test_comments.proto:123:1
+desc_test_comments.proto:141:2
     Leading comments:
  Service comment
+
     Trailing comments:
  service trailer
 
 
+
  > service[0] > name:
-desc_test_comments.proto:103:28
-desc_test_comments.proto:103:38
+desc_test_comments.proto:123:28
+desc_test_comments.proto:123:38
     Leading comments:
  service name 
 
 
  > service[0] > options:
-desc_test_comments.proto:104:2
-desc_test_comments.proto:108:38
-
-
- > service[0] > options > sfubar:
-desc_test_comments.proto:104:2
-desc_test_comments.proto:105:40
+desc_test_comments.proto:125:9
+desc_test_comments.proto:125:43
 
 
  > service[0] > options > sfubar > id:
-desc_test_comments.proto:104:2
-desc_test_comments.proto:104:36
+desc_test_comments.proto:125:9
+desc_test_comments.proto:125:43
+    Leading comments:
+ option that sets field
+
+
+
+ > service[0] > options:
+desc_test_comments.proto:127:9
+desc_test_comments.proto:127:47
 
 
  > service[0] > options > sfubar > name:
-desc_test_comments.proto:105:2
-desc_test_comments.proto:105:40
+desc_test_comments.proto:127:9
+desc_test_comments.proto:127:47
+    Leading comments:
+ another option that sets field
+
+
+
+ > service[0] > options:
+desc_test_comments.proto:128:9
+desc_test_comments.proto:128:35
 
 
  > service[0] > options > deprecated:
-desc_test_comments.proto:106:2
-desc_test_comments.proto:106:28
+desc_test_comments.proto:128:9
+desc_test_comments.proto:128:35
+    Trailing comments:
+ DEPRECATED!
+
+
+
+ > service[0] > options:
+desc_test_comments.proto:130:9
+desc_test_comments.proto:130:45
 
 
  > service[0] > options > sfubare:
-desc_test_comments.proto:108:2
-desc_test_comments.proto:108:38
-
-
- > service[0] > method:
-desc_test_comments.proto:111:2
-desc_test_comments.proto:118:3
+desc_test_comments.proto:130:9
+desc_test_comments.proto:130:45
 
 
  > service[0] > method[0]:
-desc_test_comments.proto:111:2
-desc_test_comments.proto:112:70
+desc_test_comments.proto:133:9
+desc_test_comments.proto:134:84
     Leading comments:
  Method comment
 
 
+
  > service[0] > method[0] > name:
-desc_test_comments.proto:111:21
-desc_test_comments.proto:111:33
+desc_test_comments.proto:133:28
+desc_test_comments.proto:133:40
     Leading comments:
  rpc name 
     Trailing comments:
@@ -851,75 +1063,4304 @@
 
 
  > service[0] > method[0] > client_streaming:
-desc_test_comments.proto:111:66
-desc_test_comments.proto:111:72
+desc_test_comments.proto:133:73
+desc_test_comments.proto:133:79
     Leading comments:
  comment B 
 
 
  > service[0] > method[0] > input_type:
-desc_test_comments.proto:111:89
-desc_test_comments.proto:111:96
+desc_test_comments.proto:133:96
+desc_test_comments.proto:133:103
     Leading comments:
  comment C 
 
 
  > service[0] > method[0] > output_type:
-desc_test_comments.proto:112:43
-desc_test_comments.proto:112:50
+desc_test_comments.proto:134:57
+desc_test_comments.proto:134:64
     Leading comments:
 comment E 
 
 
  > service[0] > method[1]:
-desc_test_comments.proto:114:2
-desc_test_comments.proto:118:3
+desc_test_comments.proto:136:9
+desc_test_comments.proto:140:10
 
 
  > service[0] > method[1] > name:
-desc_test_comments.proto:114:6
-desc_test_comments.proto:114:14
+desc_test_comments.proto:136:13
+desc_test_comments.proto:136:21
 
 
  > service[0] > method[1] > input_type:
-desc_test_comments.proto:114:16
-desc_test_comments.proto:114:23
+desc_test_comments.proto:136:23
+desc_test_comments.proto:136:30
 
 
  > service[0] > method[1] > output_type:
-desc_test_comments.proto:114:34
-desc_test_comments.proto:114:55
+desc_test_comments.proto:136:41
+desc_test_comments.proto:136:62
 
 
  > service[0] > method[1] > options:
-desc_test_comments.proto:115:3
-desc_test_comments.proto:117:42
+desc_test_comments.proto:137:17
+desc_test_comments.proto:137:42
 
 
  > service[0] > method[1] > options > deprecated:
-desc_test_comments.proto:115:3
-desc_test_comments.proto:115:28
+desc_test_comments.proto:137:17
+desc_test_comments.proto:137:42
 
 
- > service[0] > method[1] > options > mtfubar:
-desc_test_comments.proto:116:3
-desc_test_comments.proto:116:39
+ > service[0] > method[1] > options:
+desc_test_comments.proto:138:17
+desc_test_comments.proto:138:53
 
 
  > service[0] > method[1] > options > mtfubar[0]:
-desc_test_comments.proto:116:3
-desc_test_comments.proto:116:39
+desc_test_comments.proto:138:17
+desc_test_comments.proto:138:53
+
+
+ > service[0] > method[1] > options:
+desc_test_comments.proto:139:17
+desc_test_comments.proto:139:56
 
 
  > service[0] > method[1] > options > mtfubard:
-desc_test_comments.proto:117:3
-desc_test_comments.proto:117:42
+desc_test_comments.proto:139:17
+desc_test_comments.proto:139:56
+---- desc_test_complex.proto ----
+
+
+:
+desc_test_complex.proto:1:1
+desc_test_complex.proto:286:2
+
+
+ > syntax:
+desc_test_complex.proto:1:1
+desc_test_complex.proto:1:19
+
+
+ > package:
+desc_test_complex.proto:3:1
+desc_test_complex.proto:3:17
+
+
+ > options:
+desc_test_complex.proto:5:1
+desc_test_complex.proto:5:73
+
+
+ > options > go_package:
+desc_test_complex.proto:5:1
+desc_test_complex.proto:5:73
+
+
+ > dependency[0]:
+desc_test_complex.proto:7:1
+desc_test_complex.proto:7:43
+
+
+ > message_type[0]:
+desc_test_complex.proto:9:1
+desc_test_complex.proto:12:2
+
+
+ > message_type[0] > name:
+desc_test_complex.proto:9:9
+desc_test_complex.proto:9:15
+
+
+ > message_type[0] > field[0]:
+desc_test_complex.proto:10:9
+desc_test_complex.proto:10:34
+
+
+ > message_type[0] > field[0] > label:
+desc_test_complex.proto:10:9
+desc_test_complex.proto:10:17
+
+
+ > message_type[0] > field[0] > type:
+desc_test_complex.proto:10:18
+desc_test_complex.proto:10:24
+
+
+ > message_type[0] > field[0] > name:
+desc_test_complex.proto:10:25
+desc_test_complex.proto:10:29
+
+
+ > message_type[0] > field[0] > number:
+desc_test_complex.proto:10:32
+desc_test_complex.proto:10:33
+
+
+ > message_type[0] > field[1]:
+desc_test_complex.proto:11:9
+desc_test_complex.proto:11:32
+
+
+ > message_type[0] > field[1] > label:
+desc_test_complex.proto:11:9
+desc_test_complex.proto:11:17
+
+
+ > message_type[0] > field[1] > type:
+desc_test_complex.proto:11:18
+desc_test_complex.proto:11:24
+
+
+ > message_type[0] > field[1] > name:
+desc_test_complex.proto:11:25
+desc_test_complex.proto:11:27
+
+
+ > message_type[0] > field[1] > number:
+desc_test_complex.proto:11:30
+desc_test_complex.proto:11:31
+
+
+ > extension:
+desc_test_complex.proto:14:1
+desc_test_complex.proto:18:2
+
+
+ > extension[0]:
+desc_test_complex.proto:17:9
+desc_test_complex.proto:17:39
+
+
+ > extension[0] > extendee:
+desc_test_complex.proto:14:8
+desc_test_complex.proto:16:25
+
+
+ > extension[0] > label:
+desc_test_complex.proto:17:9
+desc_test_complex.proto:17:17
+
+
+ > extension[0] > type:
+desc_test_complex.proto:17:18
+desc_test_complex.proto:17:24
+
+
+ > extension[0] > name:
+desc_test_complex.proto:17:25
+desc_test_complex.proto:17:30
+
+
+ > extension[0] > number:
+desc_test_complex.proto:17:33
+desc_test_complex.proto:17:38
+
+
+ > message_type[1]:
+desc_test_complex.proto:20:1
+desc_test_complex.proto:59:2
+
+
+ > message_type[1] > name:
+desc_test_complex.proto:20:9
+desc_test_complex.proto:20:13
+
+
+ > message_type[1] > field[0]:
+desc_test_complex.proto:21:9
+desc_test_complex.proto:21:55
+
+
+ > message_type[1] > field[0] > label:
+desc_test_complex.proto:21:9
+desc_test_complex.proto:21:17
+
+
+ > message_type[1] > field[0] > type:
+desc_test_complex.proto:21:18
+desc_test_complex.proto:21:24
+
+
+ > message_type[1] > field[0] > name:
+desc_test_complex.proto:21:25
+desc_test_complex.proto:21:28
+
+
+ > message_type[1] > field[0] > number:
+desc_test_complex.proto:21:31
+desc_test_complex.proto:21:32
+
+
+ > message_type[1] > field[0] > options:
+desc_test_complex.proto:21:33
+desc_test_complex.proto:21:54
+
+
+ > message_type[1] > field[0] > json_name:
+desc_test_complex.proto:21:34
+desc_test_complex.proto:21:53
+
+
+ > message_type[1] > field[1]:
+desc_test_complex.proto:22:9
+desc_test_complex.proto:22:34
+
+
+ > message_type[1] > field[1] > label:
+desc_test_complex.proto:22:9
+desc_test_complex.proto:22:17
+
+
+ > message_type[1] > field[1] > type:
+desc_test_complex.proto:22:18
+desc_test_complex.proto:22:23
+
+
+ > message_type[1] > field[1] > name:
+desc_test_complex.proto:22:24
+desc_test_complex.proto:22:29
+
+
+ > message_type[1] > field[1] > number:
+desc_test_complex.proto:22:32
+desc_test_complex.proto:22:33
+
+
+ > message_type[1] > field[2]:
+desc_test_complex.proto:23:9
+desc_test_complex.proto:23:31
+
+
+ > message_type[1] > field[2] > label:
+desc_test_complex.proto:23:9
+desc_test_complex.proto:23:17
+
+
+ > message_type[1] > field[2] > type_name:
+desc_test_complex.proto:23:18
+desc_test_complex.proto:23:24
+
+
+ > message_type[1] > field[2] > name:
+desc_test_complex.proto:23:25
+desc_test_complex.proto:23:26
+
+
+ > message_type[1] > field[2] > number:
+desc_test_complex.proto:23:29
+desc_test_complex.proto:23:30
+
+
+ > message_type[1] > field[3]:
+desc_test_complex.proto:24:9
+desc_test_complex.proto:24:31
+
+
+ > message_type[1] > field[3] > label:
+desc_test_complex.proto:24:9
+desc_test_complex.proto:24:17
+
+
+ > message_type[1] > field[3] > type_name:
+desc_test_complex.proto:24:18
+desc_test_complex.proto:24:24
+
+
+ > message_type[1] > field[3] > name:
+desc_test_complex.proto:24:25
+desc_test_complex.proto:24:26
+
+
+ > message_type[1] > field[3] > number:
+desc_test_complex.proto:24:29
+desc_test_complex.proto:24:30
+
+
+ > message_type[1] > field[4]:
+desc_test_complex.proto:25:9
+desc_test_complex.proto:25:34
+
+
+ > message_type[1] > field[4] > type_name:
+desc_test_complex.proto:25:9
+desc_test_complex.proto:25:27
+
+
+ > message_type[1] > field[4] > name:
+desc_test_complex.proto:25:28
+desc_test_complex.proto:25:29
+
+
+ > message_type[1] > field[4] > number:
+desc_test_complex.proto:25:32
+desc_test_complex.proto:25:33
+
+
+ > message_type[1] > field[5]:
+desc_test_complex.proto:27:9
+desc_test_complex.proto:27:67
+
+
+ > message_type[1] > field[5] > label:
+desc_test_complex.proto:27:9
+desc_test_complex.proto:27:17
+
+
+ > message_type[1] > field[5] > type:
+desc_test_complex.proto:27:18
+desc_test_complex.proto:27:23
+
+
+ > message_type[1] > field[5] > name:
+desc_test_complex.proto:27:24
+desc_test_complex.proto:27:25
+
+
+ > message_type[1] > field[5] > number:
+desc_test_complex.proto:27:28
+desc_test_complex.proto:27:29
+
+
+ > message_type[1] > field[5] > options:
+desc_test_complex.proto:27:30
+desc_test_complex.proto:27:66
+
+
+ > message_type[1] > field[5] > default_value:
+desc_test_complex.proto:27:31
+desc_test_complex.proto:27:65
+
+
+ > message_type[1] > extension_range:
+desc_test_complex.proto:29:9
+desc_test_complex.proto:29:31
+
+
+ > message_type[1] > extension_range[0]:
+desc_test_complex.proto:29:20
+desc_test_complex.proto:29:30
+
+
+ > message_type[1] > extension_range[0] > start:
+desc_test_complex.proto:29:20
+desc_test_complex.proto:29:23
+
+
+ > message_type[1] > extension_range[0] > end:
+desc_test_complex.proto:29:27
+desc_test_complex.proto:29:30
+
+
+ > message_type[1] > extension_range:
+desc_test_complex.proto:31:9
+desc_test_complex.proto:31:62
+
+
+ > message_type[1] > extension_range[1]:
+desc_test_complex.proto:31:20
+desc_test_complex.proto:31:30
+
+
+ > message_type[1] > extension_range[1] > start:
+desc_test_complex.proto:31:20
+desc_test_complex.proto:31:23
+
+
+ > message_type[1] > extension_range[1] > end:
+desc_test_complex.proto:31:27
+desc_test_complex.proto:31:30
+
+
+ > message_type[1] > extension_range[1] > options:
+desc_test_complex.proto:31:43
+desc_test_complex.proto:31:61
+
+
+ > message_type[1] > extension_range[1] > options > label:
+desc_test_complex.proto:31:44
+desc_test_complex.proto:31:60
+
+
+ > message_type[1] > extension_range[2]:
+desc_test_complex.proto:31:32
+desc_test_complex.proto:31:42
+
+
+ > message_type[1] > extension_range[2] > start:
+desc_test_complex.proto:31:32
+desc_test_complex.proto:31:35
+
+
+ > message_type[1] > extension_range[2] > end:
+desc_test_complex.proto:31:39
+desc_test_complex.proto:31:42
+
+
+ > message_type[1] > extension_range[2] > options:
+desc_test_complex.proto:31:43
+desc_test_complex.proto:31:61
+
+
+ > message_type[1] > extension_range[2] > options > label:
+desc_test_complex.proto:31:44
+desc_test_complex.proto:31:60
+
+
+ > message_type[1] > nested_type[0]:
+desc_test_complex.proto:33:9
+desc_test_complex.proto:58:10
+
+
+ > message_type[1] > nested_type[0] > name:
+desc_test_complex.proto:33:17
+desc_test_complex.proto:33:23
+
+
+ > message_type[1] > nested_type[0] > extension:
+desc_test_complex.proto:34:17
+desc_test_complex.proto:36:18
+
+
+ > message_type[1] > nested_type[0] > extension[0]:
+desc_test_complex.proto:35:25
+desc_test_complex.proto:35:56
+
+
+ > message_type[1] > nested_type[0] > extension[0] !!!  > extendee:
+desc_test_complex.proto:34:24
+desc_test_complex.proto:34:54
+
+
+ > message_type[1] > nested_type[0] > extension[0] !!!  > label:
+desc_test_complex.proto:35:25
+desc_test_complex.proto:35:33
+
+
+ > message_type[1] > nested_type[0] > extension[0] !!!  > type:
+desc_test_complex.proto:35:34
+desc_test_complex.proto:35:39
+
+
+ > message_type[1] > nested_type[0] > extension[0] !!!  > name:
+desc_test_complex.proto:35:40
+desc_test_complex.proto:35:47
+
+
+ > message_type[1] > nested_type[0] > extension[0] !!!  > number:
+desc_test_complex.proto:35:50
+desc_test_complex.proto:35:55
+
+
+ > message_type[1] > nested_type[0] > nested_type[0]:
+desc_test_complex.proto:37:17
+desc_test_complex.proto:57:18
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > name:
+desc_test_complex.proto:37:25
+desc_test_complex.proto:37:38
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0]:
+desc_test_complex.proto:38:25
+desc_test_complex.proto:46:26
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > name:
+desc_test_complex.proto:38:30
+desc_test_complex.proto:38:33
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[0]:
+desc_test_complex.proto:39:33
+desc_test_complex.proto:39:40
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[0] > name:
+desc_test_complex.proto:39:33
+desc_test_complex.proto:39:35
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[0] > number:
+desc_test_complex.proto:39:38
+desc_test_complex.proto:39:39
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[1]:
+desc_test_complex.proto:40:33
+desc_test_complex.proto:40:40
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[1] > name:
+desc_test_complex.proto:40:33
+desc_test_complex.proto:40:35
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[1] > number:
+desc_test_complex.proto:40:38
+desc_test_complex.proto:40:39
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[2]:
+desc_test_complex.proto:41:33
+desc_test_complex.proto:41:40
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[2] > name:
+desc_test_complex.proto:41:33
+desc_test_complex.proto:41:35
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[2] > number:
+desc_test_complex.proto:41:38
+desc_test_complex.proto:41:39
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[3]:
+desc_test_complex.proto:42:33
+desc_test_complex.proto:42:40
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[3] > name:
+desc_test_complex.proto:42:33
+desc_test_complex.proto:42:35
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[3] > number:
+desc_test_complex.proto:42:38
+desc_test_complex.proto:42:39
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[4]:
+desc_test_complex.proto:43:33
+desc_test_complex.proto:43:40
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[4] > name:
+desc_test_complex.proto:43:33
+desc_test_complex.proto:43:35
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[4] > number:
+desc_test_complex.proto:43:38
+desc_test_complex.proto:43:39
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[5]:
+desc_test_complex.proto:44:33
+desc_test_complex.proto:44:40
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[5] > name:
+desc_test_complex.proto:44:33
+desc_test_complex.proto:44:35
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[5] > number:
+desc_test_complex.proto:44:38
+desc_test_complex.proto:44:39
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[6]:
+desc_test_complex.proto:45:33
+desc_test_complex.proto:45:40
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[6] > name:
+desc_test_complex.proto:45:33
+desc_test_complex.proto:45:35
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > enum_type[0] > value[6] > number:
+desc_test_complex.proto:45:38
+desc_test_complex.proto:45:39
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > options:
+desc_test_complex.proto:47:25
+desc_test_complex.proto:47:50
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > options > fooblez:
+desc_test_complex.proto:47:25
+desc_test_complex.proto:47:50
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > extension:
+desc_test_complex.proto:48:25
+desc_test_complex.proto:50:26
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > extension[0]:
+desc_test_complex.proto:49:33
+desc_test_complex.proto:49:64
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > extension[0] > extendee:
+desc_test_complex.proto:48:32
+desc_test_complex.proto:48:36
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > extension[0] > label:
+desc_test_complex.proto:49:33
+desc_test_complex.proto:49:41
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > extension[0] > type:
+desc_test_complex.proto:49:42
+desc_test_complex.proto:49:48
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > extension[0] > name:
+desc_test_complex.proto:49:49
+desc_test_complex.proto:49:57
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > extension[0] > number:
+desc_test_complex.proto:49:60
+desc_test_complex.proto:49:63
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > options:
+desc_test_complex.proto:51:25
+desc_test_complex.proto:51:108
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > options > rept[0]:
+desc_test_complex.proto:51:25
+desc_test_complex.proto:51:108
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > nested_type[0]:
+desc_test_complex.proto:52:25
+desc_test_complex.proto:56:26
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > nested_type[0] > name:
+desc_test_complex.proto:52:33
+desc_test_complex.proto:52:51
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > nested_type[0] > options:
+desc_test_complex.proto:53:33
+desc_test_complex.proto:53:109
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > nested_type[0] > options > rept[0]:
+desc_test_complex.proto:53:33
+desc_test_complex.proto:53:109
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > nested_type[0] > field[0]:
+desc_test_complex.proto:55:33
+desc_test_complex.proto:55:56
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > nested_type[0] > field[0] > label:
+desc_test_complex.proto:55:33
+desc_test_complex.proto:55:41
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > nested_type[0] > field[0] > type_name:
+desc_test_complex.proto:55:42
+desc_test_complex.proto:55:46
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > nested_type[0] > field[0] > name:
+desc_test_complex.proto:55:47
+desc_test_complex.proto:55:51
+
+
+ > message_type[1] > nested_type[0] > nested_type[0] !!!  > nested_type[0] > field[0] > number:
+desc_test_complex.proto:55:54
+desc_test_complex.proto:55:55
+
+
+ > enum_type[0]:
+desc_test_complex.proto:61:1
+desc_test_complex.proto:70:2
+
+
+ > enum_type[0] > name:
+desc_test_complex.proto:61:6
+desc_test_complex.proto:61:26
+
+
+ > enum_type[0] > value[0]:
+desc_test_complex.proto:62:9
+desc_test_complex.proto:62:15
+
+
+ > enum_type[0] > value[0] > name:
+desc_test_complex.proto:62:9
+desc_test_complex.proto:62:10
+
+
+ > enum_type[0] > value[0] > number:
+desc_test_complex.proto:62:13
+desc_test_complex.proto:62:14
+
+
+ > enum_type[0] > value[1]:
+desc_test_complex.proto:63:9
+desc_test_complex.proto:63:15
+
+
+ > enum_type[0] > value[1] > name:
+desc_test_complex.proto:63:9
+desc_test_complex.proto:63:10
+
+
+ > enum_type[0] > value[1] > number:
+desc_test_complex.proto:63:13
+desc_test_complex.proto:63:14
+
+
+ > enum_type[0] > value[2]:
+desc_test_complex.proto:64:9
+desc_test_complex.proto:64:15
+
+
+ > enum_type[0] > value[2] > name:
+desc_test_complex.proto:64:9
+desc_test_complex.proto:64:10
+
+
+ > enum_type[0] > value[2] > number:
+desc_test_complex.proto:64:13
+desc_test_complex.proto:64:14
+
+
+ > enum_type[0] > reserved_range:
+desc_test_complex.proto:65:9
+desc_test_complex.proto:65:30
+
+
+ > enum_type[0] > reserved_range[0]:
+desc_test_complex.proto:65:18
+desc_test_complex.proto:65:29
+
+
+ > enum_type[0] > reserved_range[0] > start:
+desc_test_complex.proto:65:18
+desc_test_complex.proto:65:22
+
+
+ > enum_type[0] > reserved_range[0] > end:
+desc_test_complex.proto:65:26
+desc_test_complex.proto:65:29
+
+
+ > enum_type[0] > reserved_range:
+desc_test_complex.proto:66:9
+desc_test_complex.proto:66:26
+
+
+ > enum_type[0] > reserved_range[1]:
+desc_test_complex.proto:66:18
+desc_test_complex.proto:66:25
+
+
+ > enum_type[0] > reserved_range[1] > start:
+desc_test_complex.proto:66:18
+desc_test_complex.proto:66:20
+
+
+ > enum_type[0] > reserved_range[1] > end:
+desc_test_complex.proto:66:24
+desc_test_complex.proto:66:25
+
+
+ > enum_type[0] > reserved_range:
+desc_test_complex.proto:67:9
+desc_test_complex.proto:67:40
+
+
+ > enum_type[0] > reserved_range[2]:
+desc_test_complex.proto:67:18
+desc_test_complex.proto:67:25
+
+
+ > enum_type[0] > reserved_range[2] > start:
+desc_test_complex.proto:67:18
+desc_test_complex.proto:67:19
+
+
+ > enum_type[0] > reserved_range[2] > end:
+desc_test_complex.proto:67:23
+desc_test_complex.proto:67:25
+
+
+ > enum_type[0] > reserved_range[3]:
+desc_test_complex.proto:67:27
+desc_test_complex.proto:67:35
+
+
+ > enum_type[0] > reserved_range[3] > start:
+desc_test_complex.proto:67:27
+desc_test_complex.proto:67:29
+
+
+ > enum_type[0] > reserved_range[3] > end:
+desc_test_complex.proto:67:33
+desc_test_complex.proto:67:35
+
+
+ > enum_type[0] > reserved_range[4]:
+desc_test_complex.proto:67:37
+desc_test_complex.proto:67:39
+
+
+ > enum_type[0] > reserved_range[4] > start:
+desc_test_complex.proto:67:37
+desc_test_complex.proto:67:39
+
+
+ > enum_type[0] > reserved_range:
+desc_test_complex.proto:68:9
+desc_test_complex.proto:68:27
+
+
+ > enum_type[0] > reserved_range[5]:
+desc_test_complex.proto:68:18
+desc_test_complex.proto:68:26
+
+
+ > enum_type[0] > reserved_range[5] > start:
+desc_test_complex.proto:68:18
+desc_test_complex.proto:68:20
+
+
+ > enum_type[0] > reserved_range[5] > end:
+desc_test_complex.proto:68:24
+desc_test_complex.proto:68:26
+
+
+ > enum_type[0] > reserved_name:
+desc_test_complex.proto:69:9
+desc_test_complex.proto:69:32
+
+
+ > enum_type[0] > reserved_name[0]:
+desc_test_complex.proto:69:18
+desc_test_complex.proto:69:21
+
+
+ > enum_type[0] > reserved_name[1]:
+desc_test_complex.proto:69:23
+desc_test_complex.proto:69:26
+
+
+ > enum_type[0] > reserved_name[2]:
+desc_test_complex.proto:69:28
+desc_test_complex.proto:69:31
+
+
+ > message_type[2]:
+desc_test_complex.proto:72:1
+desc_test_complex.proto:76:2
+
+
+ > message_type[2] > name:
+desc_test_complex.proto:72:9
+desc_test_complex.proto:72:32
+
+
+ > message_type[2] > reserved_range:
+desc_test_complex.proto:73:9
+desc_test_complex.proto:73:40
+
+
+ > message_type[2] > reserved_range[0]:
+desc_test_complex.proto:73:18
+desc_test_complex.proto:73:25
+
+
+ > message_type[2] > reserved_range[0] > start:
+desc_test_complex.proto:73:18
+desc_test_complex.proto:73:19
+
+
+ > message_type[2] > reserved_range[0] > end:
+desc_test_complex.proto:73:23
+desc_test_complex.proto:73:25
+
+
+ > message_type[2] > reserved_range[1]:
+desc_test_complex.proto:73:27
+desc_test_complex.proto:73:35
+
+
+ > message_type[2] > reserved_range[1] > start:
+desc_test_complex.proto:73:27
+desc_test_complex.proto:73:29
+
+
+ > message_type[2] > reserved_range[1] > end:
+desc_test_complex.proto:73:33
+desc_test_complex.proto:73:35
+
+
+ > message_type[2] > reserved_range[2]:
+desc_test_complex.proto:73:37
+desc_test_complex.proto:73:39
+
+
+ > message_type[2] > reserved_range[2] > start:
+desc_test_complex.proto:73:37
+desc_test_complex.proto:73:39
+
+
+ > message_type[2] > reserved_range:
+desc_test_complex.proto:74:9
+desc_test_complex.proto:74:30
+
+
+ > message_type[2] > reserved_range[3]:
+desc_test_complex.proto:74:18
+desc_test_complex.proto:74:29
+
+
+ > message_type[2] > reserved_range[3] > start:
+desc_test_complex.proto:74:18
+desc_test_complex.proto:74:22
+
+
+ > message_type[2] > reserved_range[3] > end:
+desc_test_complex.proto:74:26
+desc_test_complex.proto:74:29
+
+
+ > message_type[2] > reserved_name:
+desc_test_complex.proto:75:9
+desc_test_complex.proto:75:32
+
+
+ > message_type[2] > reserved_name[0]:
+desc_test_complex.proto:75:18
+desc_test_complex.proto:75:21
+
+
+ > message_type[2] > reserved_name[1]:
+desc_test_complex.proto:75:23
+desc_test_complex.proto:75:26
+
+
+ > message_type[2] > reserved_name[2]:
+desc_test_complex.proto:75:28
+desc_test_complex.proto:75:31
+
+
+ > extension:
+desc_test_complex.proto:78:1
+desc_test_complex.proto:82:2
+
+
+ > extension[1]:
+desc_test_complex.proto:79:9
+desc_test_complex.proto:79:36
+
+
+ > extension[1] > extendee:
+desc_test_complex.proto:78:8
+desc_test_complex.proto:78:38
+
+
+ > extension[1] > label:
+desc_test_complex.proto:79:9
+desc_test_complex.proto:79:17
+
+
+ > extension[1] > type_name:
+desc_test_complex.proto:79:18
+desc_test_complex.proto:79:22
+
+
+ > extension[1] > name:
+desc_test_complex.proto:79:23
+desc_test_complex.proto:79:27
+
+
+ > extension[1] > number:
+desc_test_complex.proto:79:30
+desc_test_complex.proto:79:35
+
+
+ > extension[2]:
+desc_test_complex.proto:80:9
+desc_test_complex.proto:80:60
+
+
+ > extension[2] > extendee:
+desc_test_complex.proto:78:8
+desc_test_complex.proto:78:38
+
+
+ > extension[2] > label:
+desc_test_complex.proto:80:9
+desc_test_complex.proto:80:17
+
+
+ > extension[2] > type_name:
+desc_test_complex.proto:80:18
+desc_test_complex.proto:80:47
+
+
+ > extension[2] > name:
+desc_test_complex.proto:80:48
+desc_test_complex.proto:80:51
+
+
+ > extension[2] > number:
+desc_test_complex.proto:80:54
+desc_test_complex.proto:80:59
+
+
+ > extension[3]:
+desc_test_complex.proto:81:9
+desc_test_complex.proto:81:36
+
+
+ > extension[3] > extendee:
+desc_test_complex.proto:78:8
+desc_test_complex.proto:78:38
+
+
+ > extension[3] > label:
+desc_test_complex.proto:81:9
+desc_test_complex.proto:81:17
+
+
+ > extension[3] > type_name:
+desc_test_complex.proto:81:18
+desc_test_complex.proto:81:25
+
+
+ > extension[3] > name:
+desc_test_complex.proto:81:26
+desc_test_complex.proto:81:27
+
+
+ > extension[3] > number:
+desc_test_complex.proto:81:30
+desc_test_complex.proto:81:35
+
+
+ > message_type[3]:
+desc_test_complex.proto:84:1
+desc_test_complex.proto:99:2
+
+
+ > message_type[3] > name:
+desc_test_complex.proto:84:9
+desc_test_complex.proto:84:16
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:85:5
+desc_test_complex.proto:85:130
+
+
+ > message_type[3] > options > rept[0]:
+desc_test_complex.proto:85:5
+desc_test_complex.proto:85:130
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:86:5
+desc_test_complex.proto:86:115
+
+
+ > message_type[3] > options > rept[1]:
+desc_test_complex.proto:86:5
+desc_test_complex.proto:86:115
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:87:5
+desc_test_complex.proto:87:36
+
+
+ > message_type[3] > options > rept[2]:
+desc_test_complex.proto:87:5
+desc_test_complex.proto:87:36
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:88:5
+desc_test_complex.proto:88:23
+
+
+ > message_type[3] > options > eee:
+desc_test_complex.proto:88:5
+desc_test_complex.proto:88:23
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:89:9
+desc_test_complex.proto:89:34
+
+
+ > message_type[3] > options > a:
+desc_test_complex.proto:89:9
+desc_test_complex.proto:89:34
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:90:9
+desc_test_complex.proto:90:86
+
+
+ > message_type[3] > options > a > test:
+desc_test_complex.proto:90:9
+desc_test_complex.proto:90:86
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:91:9
+desc_test_complex.proto:91:37
+
+
+ > message_type[3] > options > a > test > foo:
+desc_test_complex.proto:91:9
+desc_test_complex.proto:91:37
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:92:9
+desc_test_complex.proto:92:41
+
+
+ > message_type[3] > options > a > test > s > name:
+desc_test_complex.proto:92:9
+desc_test_complex.proto:92:41
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:93:5
+desc_test_complex.proto:93:34
+
+
+ > message_type[3] > options > a > test > s > id:
+desc_test_complex.proto:93:5
+desc_test_complex.proto:93:34
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:94:5
+desc_test_complex.proto:94:31
+
+
+ > message_type[3] > options > a > test > array[0]:
+desc_test_complex.proto:94:5
+desc_test_complex.proto:94:31
+
+
+ > message_type[3] > options:
+desc_test_complex.proto:95:5
+desc_test_complex.proto:95:31
+
+
+ > message_type[3] > options > a > test > array[1]:
+desc_test_complex.proto:95:5
+desc_test_complex.proto:95:31
+
+
+ > message_type[3] > field[0]:
+desc_test_complex.proto:97:5
+desc_test_complex.proto:97:28
+
+
+ > message_type[3] > field[0] > label:
+desc_test_complex.proto:97:5
+desc_test_complex.proto:97:13
+
+
+ > message_type[3] > field[0] > type_name:
+desc_test_complex.proto:97:14
+desc_test_complex.proto:97:18
+
+
+ > message_type[3] > field[0] > name:
+desc_test_complex.proto:97:19
+desc_test_complex.proto:97:23
+
+
+ > message_type[3] > field[0] > number:
+desc_test_complex.proto:97:26
+desc_test_complex.proto:97:27
+
+
+ > message_type[3] > field[1]:
+desc_test_complex.proto:98:5
+desc_test_complex.proto:98:67
+
+
+ > message_type[3] > field[1] > label:
+desc_test_complex.proto:98:5
+desc_test_complex.proto:98:13
+
+
+ > message_type[3] > field[1] > type_name:
+desc_test_complex.proto:98:14
+desc_test_complex.proto:98:43
+
+
+ > message_type[3] > field[1] > name:
+desc_test_complex.proto:98:44
+desc_test_complex.proto:98:47
+
+
+ > message_type[3] > field[1] > number:
+desc_test_complex.proto:98:50
+desc_test_complex.proto:98:51
+
+
+ > message_type[3] > field[1] > options:
+desc_test_complex.proto:98:52
+desc_test_complex.proto:98:66
+
+
+ > message_type[3] > field[1] > default_value:
+desc_test_complex.proto:98:53
+desc_test_complex.proto:98:65
+
+
+ > message_type[4]:
+desc_test_complex.proto:101:1
+desc_test_complex.proto:115:2
+
+
+ > message_type[4] > name:
+desc_test_complex.proto:101:9
+desc_test_complex.proto:101:18
+
+
+ > message_type[4] > field[0]:
+desc_test_complex.proto:102:9
+desc_test_complex.proto:102:41
+
+
+ > message_type[4] > field[0] > label:
+desc_test_complex.proto:102:9
+desc_test_complex.proto:102:17
+
+
+ > message_type[4] > field[0] > type:
+desc_test_complex.proto:102:18
+desc_test_complex.proto:102:22
+
+
+ > message_type[4] > field[0] > name:
+desc_test_complex.proto:102:23
+desc_test_complex.proto:102:36
+
+
+ > message_type[4] > field[0] > number:
+desc_test_complex.proto:102:39
+desc_test_complex.proto:102:40
+
+
+ > message_type[4] > enum_type[0]:
+desc_test_complex.proto:104:9
+desc_test_complex.proto:108:10
+
+
+ > message_type[4] > enum_type[0] > name:
+desc_test_complex.proto:104:14
+desc_test_complex.proto:104:20
+
+
+ > message_type[4] > enum_type[0] > value[0]:
+desc_test_complex.proto:105:17
+desc_test_complex.proto:105:27
+
+
+ > message_type[4] > enum_type[0] > value[0] > name:
+desc_test_complex.proto:105:17
+desc_test_complex.proto:105:22
+
+
+ > message_type[4] > enum_type[0] > value[0] > number:
+desc_test_complex.proto:105:25
+desc_test_complex.proto:105:26
+
+
+ > message_type[4] > enum_type[0] > value[1]:
+desc_test_complex.proto:106:17
+desc_test_complex.proto:106:26
+
+
+ > message_type[4] > enum_type[0] > value[1] > name:
+desc_test_complex.proto:106:17
+desc_test_complex.proto:106:21
+
+
+ > message_type[4] > enum_type[0] > value[1] > number:
+desc_test_complex.proto:106:24
+desc_test_complex.proto:106:25
+
+
+ > message_type[4] > enum_type[0] > value[2]:
+desc_test_complex.proto:107:17
+desc_test_complex.proto:107:27
+
+
+ > message_type[4] > enum_type[0] > value[2] > name:
+desc_test_complex.proto:107:17
+desc_test_complex.proto:107:22
+
+
+ > message_type[4] > enum_type[0] > value[2] > number:
+desc_test_complex.proto:107:25
+desc_test_complex.proto:107:26
+
+
+ > message_type[4] > nested_type[0]:
+desc_test_complex.proto:109:9
+desc_test_complex.proto:112:10
+
+
+ > message_type[4] > nested_type[0] > name:
+desc_test_complex.proto:109:17
+desc_test_complex.proto:109:27
+
+
+ > message_type[4] > nested_type[0] > field[0]:
+desc_test_complex.proto:110:17
+desc_test_complex.proto:110:44
+
+
+ > message_type[4] > nested_type[0] > field[0] > label:
+desc_test_complex.proto:110:17
+desc_test_complex.proto:110:25
+
+
+ > message_type[4] > nested_type[0] > field[0] > type_name:
+desc_test_complex.proto:110:26
+desc_test_complex.proto:110:32
+
+
+ > message_type[4] > nested_type[0] > field[0] > name:
+desc_test_complex.proto:110:33
+desc_test_complex.proto:110:39
+
+
+ > message_type[4] > nested_type[0] > field[0] > number:
+desc_test_complex.proto:110:42
+desc_test_complex.proto:110:43
+
+
+ > message_type[4] > nested_type[0] > field[1]:
+desc_test_complex.proto:111:17
+desc_test_complex.proto:111:44
+
+
+ > message_type[4] > nested_type[0] > field[1] > label:
+desc_test_complex.proto:111:17
+desc_test_complex.proto:111:25
+
+
+ > message_type[4] > nested_type[0] > field[1] > type:
+desc_test_complex.proto:111:26
+desc_test_complex.proto:111:32
+
+
+ > message_type[4] > nested_type[0] > field[1] > name:
+desc_test_complex.proto:111:33
+desc_test_complex.proto:111:39
+
+
+ > message_type[4] > nested_type[0] > field[1] > number:
+desc_test_complex.proto:111:42
+desc_test_complex.proto:111:43
+
+
+ > message_type[4] > field[1]:
+desc_test_complex.proto:114:9
+desc_test_complex.proto:114:44
+
+
+ > message_type[4] > field[1] > label:
+desc_test_complex.proto:114:9
+desc_test_complex.proto:114:17
+
+
+ > message_type[4] > field[1] > type_name:
+desc_test_complex.proto:114:18
+desc_test_complex.proto:114:28
+
+
+ > message_type[4] > field[1] > name:
+desc_test_complex.proto:114:29
+desc_test_complex.proto:114:39
+
+
+ > message_type[4] > field[1] > number:
+desc_test_complex.proto:114:42
+desc_test_complex.proto:114:43
+
+
+ > extension:
+desc_test_complex.proto:117:1
+desc_test_complex.proto:119:2
+
+
+ > extension[4]:
+desc_test_complex.proto:118:9
+desc_test_complex.proto:118:46
+
+
+ > extension[4] > extendee:
+desc_test_complex.proto:117:8
+desc_test_complex.proto:117:37
+
+
+ > extension[4] > label:
+desc_test_complex.proto:118:9
+desc_test_complex.proto:118:17
+
+
+ > extension[4] > type_name:
+desc_test_complex.proto:118:18
+desc_test_complex.proto:118:27
+
+
+ > extension[4] > name:
+desc_test_complex.proto:118:28
+desc_test_complex.proto:118:37
+
+
+ > extension[4] > number:
+desc_test_complex.proto:118:40
+desc_test_complex.proto:118:45
+
+
+ > service[0]:
+desc_test_complex.proto:121:1
+desc_test_complex.proto:140:2
+
+
+ > service[0] > name:
+desc_test_complex.proto:121:9
+desc_test_complex.proto:121:24
+
+
+ > service[0] > method[0]:
+desc_test_complex.proto:122:9
+desc_test_complex.proto:130:10
+
+
+ > service[0] > method[0] > name:
+desc_test_complex.proto:122:13
+desc_test_complex.proto:122:21
+
+
+ > service[0] > method[0] > input_type:
+desc_test_complex.proto:122:22
+desc_test_complex.proto:122:26
+
+
+ > service[0] > method[0] > output_type:
+desc_test_complex.proto:122:37
+desc_test_complex.proto:122:41
+
+
+ > service[0] > method[0] > options:
+desc_test_complex.proto:123:17
+desc_test_complex.proto:129:19
+
+
+ > service[0] > method[0] > options > validator:
+desc_test_complex.proto:123:17
+desc_test_complex.proto:129:19
+
+
+ > service[0] > method[1]:
+desc_test_complex.proto:131:9
+desc_test_complex.proto:139:10
+
+
+ > service[0] > method[1] > name:
+desc_test_complex.proto:131:13
+desc_test_complex.proto:131:16
+
+
+ > service[0] > method[1] > input_type:
+desc_test_complex.proto:131:17
+desc_test_complex.proto:131:21
+
+
+ > service[0] > method[1] > output_type:
+desc_test_complex.proto:131:32
+desc_test_complex.proto:131:36
+
+
+ > service[0] > method[1] > options:
+desc_test_complex.proto:132:17
+desc_test_complex.proto:138:19
+
+
+ > service[0] > method[1] > options > validator:
+desc_test_complex.proto:132:17
+desc_test_complex.proto:138:19
+
+
+ > message_type[5]:
+desc_test_complex.proto:142:1
+desc_test_complex.proto:168:2
+
+
+ > message_type[5] > name:
+desc_test_complex.proto:142:9
+desc_test_complex.proto:142:13
+
+
+ > message_type[5] > nested_type[0]:
+desc_test_complex.proto:143:3
+desc_test_complex.proto:148:4
+
+
+ > message_type[5] > nested_type[0] > name:
+desc_test_complex.proto:143:11
+desc_test_complex.proto:143:21
+
+
+ > message_type[5] > nested_type[0] > field[0]:
+desc_test_complex.proto:144:5
+desc_test_complex.proto:144:33
+
+
+ > message_type[5] > nested_type[0] > field[0] > label:
+desc_test_complex.proto:144:5
+desc_test_complex.proto:144:13
+
+
+ > message_type[5] > nested_type[0] > field[0] > type:
+desc_test_complex.proto:144:14
+desc_test_complex.proto:144:20
+
+
+ > message_type[5] > nested_type[0] > field[0] > name:
+desc_test_complex.proto:144:21
+desc_test_complex.proto:144:28
+
+
+ > message_type[5] > nested_type[0] > field[0] > number:
+desc_test_complex.proto:144:31
+desc_test_complex.proto:144:32
+
+
+ > message_type[5] > nested_type[0] > field[1]:
+desc_test_complex.proto:145:5
+desc_test_complex.proto:145:35
+
+
+ > message_type[5] > nested_type[0] > field[1] > label:
+desc_test_complex.proto:145:5
+desc_test_complex.proto:145:13
+
+
+ > message_type[5] > nested_type[0] > field[1] > type:
+desc_test_complex.proto:145:14
+desc_test_complex.proto:145:18
+
+
+ > message_type[5] > nested_type[0] > field[1] > name:
+desc_test_complex.proto:145:19
+desc_test_complex.proto:145:30
+
+
+ > message_type[5] > nested_type[0] > field[1] > number:
+desc_test_complex.proto:145:33
+desc_test_complex.proto:145:34
+
+
+ > message_type[5] > nested_type[0] > field[2]:
+desc_test_complex.proto:146:5
+desc_test_complex.proto:146:32
+
+
+ > message_type[5] > nested_type[0] > field[2] > label:
+desc_test_complex.proto:146:5
+desc_test_complex.proto:146:13
+
+
+ > message_type[5] > nested_type[0] > field[2] > type:
+desc_test_complex.proto:146:14
+desc_test_complex.proto:146:19
+
+
+ > message_type[5] > nested_type[0] > field[2] > name:
+desc_test_complex.proto:146:20
+desc_test_complex.proto:146:27
+
+
+ > message_type[5] > nested_type[0] > field[2] > number:
+desc_test_complex.proto:146:30
+desc_test_complex.proto:146:31
+
+
+ > message_type[5] > nested_type[0] > field[3]:
+desc_test_complex.proto:147:5
+desc_test_complex.proto:147:32
+
+
+ > message_type[5] > nested_type[0] > field[3] > label:
+desc_test_complex.proto:147:5
+desc_test_complex.proto:147:13
+
+
+ > message_type[5] > nested_type[0] > field[3] > type:
+desc_test_complex.proto:147:14
+desc_test_complex.proto:147:19
+
+
+ > message_type[5] > nested_type[0] > field[3] > name:
+desc_test_complex.proto:147:20
+desc_test_complex.proto:147:27
+
+
+ > message_type[5] > nested_type[0] > field[3] > number:
+desc_test_complex.proto:147:30
+desc_test_complex.proto:147:31
+
+
+ > message_type[5] > nested_type[1]:
+desc_test_complex.proto:149:3
+desc_test_complex.proto:152:4
+
+
+ > message_type[5] > nested_type[1] > name:
+desc_test_complex.proto:149:11
+desc_test_complex.proto:149:18
+
+
+ > message_type[5] > nested_type[1] > field[0]:
+desc_test_complex.proto:150:5
+desc_test_complex.proto:150:32
+
+
+ > message_type[5] > nested_type[1] > field[0] > label:
+desc_test_complex.proto:150:5
+desc_test_complex.proto:150:13
+
+
+ > message_type[5] > nested_type[1] > field[0] > type:
+desc_test_complex.proto:150:14
+desc_test_complex.proto:150:19
+
+
+ > message_type[5] > nested_type[1] > field[0] > name:
+desc_test_complex.proto:150:20
+desc_test_complex.proto:150:27
+
+
+ > message_type[5] > nested_type[1] > field[0] > number:
+desc_test_complex.proto:150:30
+desc_test_complex.proto:150:31
+
+
+ > message_type[5] > nested_type[1] > field[1]:
+desc_test_complex.proto:151:5
+desc_test_complex.proto:151:33
+
+
+ > message_type[5] > nested_type[1] > field[1] > label:
+desc_test_complex.proto:151:5
+desc_test_complex.proto:151:13
+
+
+ > message_type[5] > nested_type[1] > field[1] > type:
+desc_test_complex.proto:151:14
+desc_test_complex.proto:151:20
+
+
+ > message_type[5] > nested_type[1] > field[1] > name:
+desc_test_complex.proto:151:21
+desc_test_complex.proto:151:28
+
+
+ > message_type[5] > nested_type[1] > field[1] > number:
+desc_test_complex.proto:151:31
+desc_test_complex.proto:151:32
+
+
+ > message_type[5] > nested_type[2]:
+desc_test_complex.proto:153:3
+desc_test_complex.proto:158:4
+
+
+ > message_type[5] > nested_type[2] > name:
+desc_test_complex.proto:153:11
+desc_test_complex.proto:153:23
+
+
+ > message_type[5] > nested_type[2] > field[0]:
+desc_test_complex.proto:154:5
+desc_test_complex.proto:154:35
+
+
+ > message_type[5] > nested_type[2] > field[0] > label:
+desc_test_complex.proto:154:5
+desc_test_complex.proto:154:13
+
+
+ > message_type[5] > nested_type[2] > field[0] > type:
+desc_test_complex.proto:154:14
+desc_test_complex.proto:154:18
+
+
+ > message_type[5] > nested_type[2] > field[0] > name:
+desc_test_complex.proto:154:19
+desc_test_complex.proto:154:30
+
+
+ > message_type[5] > nested_type[2] > field[0] > number:
+desc_test_complex.proto:154:33
+desc_test_complex.proto:154:34
+
+
+ > message_type[5] > nested_type[2] > field[1]:
+desc_test_complex.proto:155:5
+desc_test_complex.proto:155:34
+
+
+ > message_type[5] > nested_type[2] > field[1] > label:
+desc_test_complex.proto:155:5
+desc_test_complex.proto:155:13
+
+
+ > message_type[5] > nested_type[2] > field[1] > type:
+desc_test_complex.proto:155:14
+desc_test_complex.proto:155:19
+
+
+ > message_type[5] > nested_type[2] > field[1] > name:
+desc_test_complex.proto:155:20
+desc_test_complex.proto:155:29
+
+
+ > message_type[5] > nested_type[2] > field[1] > number:
+desc_test_complex.proto:155:32
+desc_test_complex.proto:155:33
+
+
+ > message_type[5] > nested_type[2] > field[2]:
+desc_test_complex.proto:156:5
+desc_test_complex.proto:156:34
+
+
+ > message_type[5] > nested_type[2] > field[2] > label:
+desc_test_complex.proto:156:5
+desc_test_complex.proto:156:13
+
+
+ > message_type[5] > nested_type[2] > field[2] > type:
+desc_test_complex.proto:156:14
+desc_test_complex.proto:156:19
+
+
+ > message_type[5] > nested_type[2] > field[2] > name:
+desc_test_complex.proto:156:20
+desc_test_complex.proto:156:29
+
+
+ > message_type[5] > nested_type[2] > field[2] > number:
+desc_test_complex.proto:156:32
+desc_test_complex.proto:156:33
+
+
+ > message_type[5] > nested_type[2] > field[3]:
+desc_test_complex.proto:157:5
+desc_test_complex.proto:157:29
+
+
+ > message_type[5] > nested_type[2] > field[3] > label:
+desc_test_complex.proto:157:5
+desc_test_complex.proto:157:13
+
+
+ > message_type[5] > nested_type[2] > field[3] > type_name:
+desc_test_complex.proto:157:14
+desc_test_complex.proto:157:18
+
+
+ > message_type[5] > nested_type[2] > field[3] > name:
+desc_test_complex.proto:157:19
+desc_test_complex.proto:157:24
+
+
+ > message_type[5] > nested_type[2] > field[3] > number:
+desc_test_complex.proto:157:27
+desc_test_complex.proto:157:28
+
+
+ > message_type[5] > oneof_decl[0]:
+desc_test_complex.proto:159:3
+desc_test_complex.proto:167:4
+
+
+ > message_type[5] > oneof_decl[0] > name:
+desc_test_complex.proto:159:9
+desc_test_complex.proto:159:13
+
+
+ > message_type[5] > field[0]:
+desc_test_complex.proto:160:5
+desc_test_complex.proto:160:27
+
+
+ > message_type[5] > field[0] > type_name:
+desc_test_complex.proto:160:5
+desc_test_complex.proto:160:15
+
+
+ > message_type[5] > field[0] > name:
+desc_test_complex.proto:160:16
+desc_test_complex.proto:160:22
+
+
+ > message_type[5] > field[0] > number:
+desc_test_complex.proto:160:25
+desc_test_complex.proto:160:26
+
+
+ > message_type[5] > field[1]:
+desc_test_complex.proto:161:5
+desc_test_complex.proto:161:31
+
+
+ > message_type[5] > field[1] > type_name:
+desc_test_complex.proto:161:5
+desc_test_complex.proto:161:17
+
+
+ > message_type[5] > field[1] > name:
+desc_test_complex.proto:161:18
+desc_test_complex.proto:161:26
+
+
+ > message_type[5] > field[1] > number:
+desc_test_complex.proto:161:29
+desc_test_complex.proto:161:30
+
+
+ > message_type[5] > field[2]:
+desc_test_complex.proto:162:5
+desc_test_complex.proto:162:21
+
+
+ > message_type[5] > field[2] > type_name:
+desc_test_complex.proto:162:5
+desc_test_complex.proto:162:12
+
+
+ > message_type[5] > field[2] > name:
+desc_test_complex.proto:162:13
+desc_test_complex.proto:162:16
+
+
+ > message_type[5] > field[2] > number:
+desc_test_complex.proto:162:19
+desc_test_complex.proto:162:20
+
+
+ > message_type[5] > field[3]:
+desc_test_complex.proto:163:9
+desc_test_complex.proto:166:10
+
+
+ > message_type[5] > field[3] > type:
+desc_test_complex.proto:163:9
+desc_test_complex.proto:163:14
+
+
+ > message_type[5] > field[3] > name:
+desc_test_complex.proto:163:15
+desc_test_complex.proto:163:24
+
+
+ > message_type[5] > field[3] > number:
+desc_test_complex.proto:163:27
+desc_test_complex.proto:163:28
+
+
+ > message_type[5] > nested_type[3]:
+desc_test_complex.proto:163:9
+desc_test_complex.proto:166:10
+
+
+ > message_type[5] > nested_type[3] > name:
+desc_test_complex.proto:163:15
+desc_test_complex.proto:163:24
+
+
+ > message_type[5] > field[3] > type_name:
+desc_test_complex.proto:163:15
+desc_test_complex.proto:163:24
+
+
+ > message_type[5] > nested_type[3] > field[0]:
+desc_test_complex.proto:164:17
+desc_test_complex.proto:164:45
+
+
+ > message_type[5] > nested_type[3] > field[0] > label:
+desc_test_complex.proto:164:17
+desc_test_complex.proto:164:25
+
+
+ > message_type[5] > nested_type[3] > field[0] > type:
+desc_test_complex.proto:164:26
+desc_test_complex.proto:164:32
+
+
+ > message_type[5] > nested_type[3] > field[0] > name:
+desc_test_complex.proto:164:33
+desc_test_complex.proto:164:40
+
+
+ > message_type[5] > nested_type[3] > field[0] > number:
+desc_test_complex.proto:164:43
+desc_test_complex.proto:164:44
+
+
+ > message_type[5] > nested_type[3] > field[1]:
+desc_test_complex.proto:165:17
+desc_test_complex.proto:165:45
+
+
+ > message_type[5] > nested_type[3] > field[1] > label:
+desc_test_complex.proto:165:17
+desc_test_complex.proto:165:25
+
+
+ > message_type[5] > nested_type[3] > field[1] > type:
+desc_test_complex.proto:165:26
+desc_test_complex.proto:165:32
+
+
+ > message_type[5] > nested_type[3] > field[1] > name:
+desc_test_complex.proto:165:33
+desc_test_complex.proto:165:40
+
+
+ > message_type[5] > nested_type[3] > field[1] > number:
+desc_test_complex.proto:165:43
+desc_test_complex.proto:165:44
+
+
+ > extension:
+desc_test_complex.proto:170:1
+desc_test_complex.proto:172:2
+
+
+ > extension[5]:
+desc_test_complex.proto:171:3
+desc_test_complex.proto:171:30
+
+
+ > extension[5] > extendee:
+desc_test_complex.proto:170:8
+desc_test_complex.proto:170:36
+
+
+ > extension[5] > label:
+desc_test_complex.proto:171:3
+desc_test_complex.proto:171:11
+
+
+ > extension[5] > type_name:
+desc_test_complex.proto:171:12
+desc_test_complex.proto:171:16
+
+
+ > extension[5] > name:
+desc_test_complex.proto:171:17
+desc_test_complex.proto:171:22
+
+
+ > extension[5] > number:
+desc_test_complex.proto:171:25
+desc_test_complex.proto:171:29
+
+
+ > message_type[6]:
+desc_test_complex.proto:174:1
+desc_test_complex.proto:180:2
+
+
+ > message_type[6] > name:
+desc_test_complex.proto:174:9
+desc_test_complex.proto:174:24
+
+
+ > message_type[6] > field[0]:
+desc_test_complex.proto:175:5
+desc_test_complex.proto:179:11
+
+
+ > message_type[6] > field[0] > label:
+desc_test_complex.proto:175:5
+desc_test_complex.proto:175:13
+
+
+ > message_type[6] > field[0] > type:
+desc_test_complex.proto:175:14
+desc_test_complex.proto:175:20
+
+
+ > message_type[6] > field[0] > name:
+desc_test_complex.proto:175:21
+desc_test_complex.proto:175:29
+
+
+ > message_type[6] > field[0] > number:
+desc_test_complex.proto:175:32
+desc_test_complex.proto:175:33
+
+
+ > message_type[6] > field[0] > options:
+desc_test_complex.proto:176:7
+desc_test_complex.proto:179:10
+
+
+ > message_type[6] > field[0] > options > rules > repeated:
+desc_test_complex.proto:176:8
+desc_test_complex.proto:179:9
+
+
+ > message_type[7]:
+desc_test_complex.proto:184:1
+desc_test_complex.proto:220:2
+    Leading detached comment [0]:
+ tests cases where field names collide with keywords
+
+
+
+ > message_type[7] > name:
+desc_test_complex.proto:184:9
+desc_test_complex.proto:184:26
+
+
+ > message_type[7] > field[0]:
+desc_test_complex.proto:185:9
+desc_test_complex.proto:185:34
+
+
+ > message_type[7] > field[0] > label:
+desc_test_complex.proto:185:9
+desc_test_complex.proto:185:17
+
+
+ > message_type[7] > field[0] > type:
+desc_test_complex.proto:185:18
+desc_test_complex.proto:185:22
+
+
+ > message_type[7] > field[0] > name:
+desc_test_complex.proto:185:23
+desc_test_complex.proto:185:29
+
+
+ > message_type[7] > field[0] > number:
+desc_test_complex.proto:185:32
+desc_test_complex.proto:185:33
+
+
+ > message_type[7] > field[1]:
+desc_test_complex.proto:186:9
+desc_test_complex.proto:186:34
+
+
+ > message_type[7] > field[1] > label:
+desc_test_complex.proto:186:9
+desc_test_complex.proto:186:17
+
+
+ > message_type[7] > field[1] > type:
+desc_test_complex.proto:186:18
+desc_test_complex.proto:186:22
+
+
+ > message_type[7] > field[1] > name:
+desc_test_complex.proto:186:23
+desc_test_complex.proto:186:29
+
+
+ > message_type[7] > field[1] > number:
+desc_test_complex.proto:186:32
+desc_test_complex.proto:186:33
+
+
+ > message_type[7] > field[2]:
+desc_test_complex.proto:187:9
+desc_test_complex.proto:187:34
+
+
+ > message_type[7] > field[2] > label:
+desc_test_complex.proto:187:9
+desc_test_complex.proto:187:17
+
+
+ > message_type[7] > field[2] > type:
+desc_test_complex.proto:187:18
+desc_test_complex.proto:187:22
+
+
+ > message_type[7] > field[2] > name:
+desc_test_complex.proto:187:23
+desc_test_complex.proto:187:29
+
+
+ > message_type[7] > field[2] > number:
+desc_test_complex.proto:187:32
+desc_test_complex.proto:187:33
+
+
+ > message_type[7] > field[3]:
+desc_test_complex.proto:188:9
+desc_test_complex.proto:188:32
+
+
+ > message_type[7] > field[3] > label:
+desc_test_complex.proto:188:9
+desc_test_complex.proto:188:17
+
+
+ > message_type[7] > field[3] > type:
+desc_test_complex.proto:188:18
+desc_test_complex.proto:188:22
+
+
+ > message_type[7] > field[3] > name:
+desc_test_complex.proto:188:23
+desc_test_complex.proto:188:27
+
+
+ > message_type[7] > field[3] > number:
+desc_test_complex.proto:188:30
+desc_test_complex.proto:188:31
+
+
+ > message_type[7] > field[4]:
+desc_test_complex.proto:189:9
+desc_test_complex.proto:189:35
+
+
+ > message_type[7] > field[4] > label:
+desc_test_complex.proto:189:9
+desc_test_complex.proto:189:17
+
+
+ > message_type[7] > field[4] > type:
+desc_test_complex.proto:189:18
+desc_test_complex.proto:189:22
+
+
+ > message_type[7] > field[4] > name:
+desc_test_complex.proto:189:23
+desc_test_complex.proto:189:30
+
+
+ > message_type[7] > field[4] > number:
+desc_test_complex.proto:189:33
+desc_test_complex.proto:189:34
+
+
+ > message_type[7] > field[5]:
+desc_test_complex.proto:190:9
+desc_test_complex.proto:190:36
+
+
+ > message_type[7] > field[5] > label:
+desc_test_complex.proto:190:9
+desc_test_complex.proto:190:17
+
+
+ > message_type[7] > field[5] > type:
+desc_test_complex.proto:190:18
+desc_test_complex.proto:190:24
+
+
+ > message_type[7] > field[5] > name:
+desc_test_complex.proto:190:25
+desc_test_complex.proto:190:31
+
+
+ > message_type[7] > field[5] > number:
+desc_test_complex.proto:190:34
+desc_test_complex.proto:190:35
+
+
+ > message_type[7] > field[6]:
+desc_test_complex.proto:191:9
+desc_test_complex.proto:191:34
+
+
+ > message_type[7] > field[6] > label:
+desc_test_complex.proto:191:9
+desc_test_complex.proto:191:17
+
+
+ > message_type[7] > field[6] > type:
+desc_test_complex.proto:191:18
+desc_test_complex.proto:191:23
+
+
+ > message_type[7] > field[6] > name:
+desc_test_complex.proto:191:24
+desc_test_complex.proto:191:29
+
+
+ > message_type[7] > field[6] > number:
+desc_test_complex.proto:191:32
+desc_test_complex.proto:191:33
+
+
+ > message_type[7] > field[7]:
+desc_test_complex.proto:192:9
+desc_test_complex.proto:192:34
+
+
+ > message_type[7] > field[7] > label:
+desc_test_complex.proto:192:9
+desc_test_complex.proto:192:17
+
+
+ > message_type[7] > field[7] > type:
+desc_test_complex.proto:192:18
+desc_test_complex.proto:192:23
+
+
+ > message_type[7] > field[7] > name:
+desc_test_complex.proto:192:24
+desc_test_complex.proto:192:29
+
+
+ > message_type[7] > field[7] > number:
+desc_test_complex.proto:192:32
+desc_test_complex.proto:192:33
+
+
+ > message_type[7] > field[8]:
+desc_test_complex.proto:193:9
+desc_test_complex.proto:193:34
+
+
+ > message_type[7] > field[8] > label:
+desc_test_complex.proto:193:9
+desc_test_complex.proto:193:17
+
+
+ > message_type[7] > field[8] > type:
+desc_test_complex.proto:193:18
+desc_test_complex.proto:193:23
+
+
+ > message_type[7] > field[8] > name:
+desc_test_complex.proto:193:24
+desc_test_complex.proto:193:29
+
+
+ > message_type[7] > field[8] > number:
+desc_test_complex.proto:193:32
+desc_test_complex.proto:193:33
+
+
+ > message_type[7] > field[9]:
+desc_test_complex.proto:194:9
+desc_test_complex.proto:194:37
+
+
+ > message_type[7] > field[9] > label:
+desc_test_complex.proto:194:9
+desc_test_complex.proto:194:17
+
+
+ > message_type[7] > field[9] > type:
+desc_test_complex.proto:194:18
+desc_test_complex.proto:194:24
+
+
+ > message_type[7] > field[9] > name:
+desc_test_complex.proto:194:25
+desc_test_complex.proto:194:31
+
+
+ > message_type[7] > field[9] > number:
+desc_test_complex.proto:194:34
+desc_test_complex.proto:194:36
+
+
+ > message_type[7] > field[10]:
+desc_test_complex.proto:195:9
+desc_test_complex.proto:195:37
+
+
+ > message_type[7] > field[10] > label:
+desc_test_complex.proto:195:9
+desc_test_complex.proto:195:17
+
+
+ > message_type[7] > field[10] > type:
+desc_test_complex.proto:195:18
+desc_test_complex.proto:195:24
+
+
+ > message_type[7] > field[10] > name:
+desc_test_complex.proto:195:25
+desc_test_complex.proto:195:31
+
+
+ > message_type[7] > field[10] > number:
+desc_test_complex.proto:195:34
+desc_test_complex.proto:195:36
+
+
+ > message_type[7] > field[11]:
+desc_test_complex.proto:196:9
+desc_test_complex.proto:196:37
+
+
+ > message_type[7] > field[11] > label:
+desc_test_complex.proto:196:9
+desc_test_complex.proto:196:17
+
+
+ > message_type[7] > field[11] > type:
+desc_test_complex.proto:196:18
+desc_test_complex.proto:196:24
+
+
+ > message_type[7] > field[11] > name:
+desc_test_complex.proto:196:25
+desc_test_complex.proto:196:31
+
+
+ > message_type[7] > field[11] > number:
+desc_test_complex.proto:196:34
+desc_test_complex.proto:196:36
+
+
+ > message_type[7] > field[12]:
+desc_test_complex.proto:197:9
+desc_test_complex.proto:197:37
+
+
+ > message_type[7] > field[12] > label:
+desc_test_complex.proto:197:9
+desc_test_complex.proto:197:17
+
+
+ > message_type[7] > field[12] > type:
+desc_test_complex.proto:197:18
+desc_test_complex.proto:197:24
+
+
+ > message_type[7] > field[12] > name:
+desc_test_complex.proto:197:25
+desc_test_complex.proto:197:31
+
+
+ > message_type[7] > field[12] > number:
+desc_test_complex.proto:197:34
+desc_test_complex.proto:197:36
+
+
+ > message_type[7] > field[13]:
+desc_test_complex.proto:198:9
+desc_test_complex.proto:198:39
+
+
+ > message_type[7] > field[13] > label:
+desc_test_complex.proto:198:9
+desc_test_complex.proto:198:17
+
+
+ > message_type[7] > field[13] > type:
+desc_test_complex.proto:198:18
+desc_test_complex.proto:198:25
+
+
+ > message_type[7] > field[13] > name:
+desc_test_complex.proto:198:26
+desc_test_complex.proto:198:33
+
+
+ > message_type[7] > field[13] > number:
+desc_test_complex.proto:198:36
+desc_test_complex.proto:198:38
+
+
+ > message_type[7] > field[14]:
+desc_test_complex.proto:199:9
+desc_test_complex.proto:199:39
+
+
+ > message_type[7] > field[14] > label:
+desc_test_complex.proto:199:9
+desc_test_complex.proto:199:17
+
+
+ > message_type[7] > field[14] > type:
+desc_test_complex.proto:199:18
+desc_test_complex.proto:199:25
+
+
+ > message_type[7] > field[14] > name:
+desc_test_complex.proto:199:26
+desc_test_complex.proto:199:33
+
+
+ > message_type[7] > field[14] > number:
+desc_test_complex.proto:199:36
+desc_test_complex.proto:199:38
+
+
+ > message_type[7] > field[15]:
+desc_test_complex.proto:200:9
+desc_test_complex.proto:200:41
+
+
+ > message_type[7] > field[15] > label:
+desc_test_complex.proto:200:9
+desc_test_complex.proto:200:17
+
+
+ > message_type[7] > field[15] > type:
+desc_test_complex.proto:200:18
+desc_test_complex.proto:200:26
+
+
+ > message_type[7] > field[15] > name:
+desc_test_complex.proto:200:27
+desc_test_complex.proto:200:35
+
+
+ > message_type[7] > field[15] > number:
+desc_test_complex.proto:200:38
+desc_test_complex.proto:200:40
+
+
+ > message_type[7] > field[16]:
+desc_test_complex.proto:201:9
+desc_test_complex.proto:201:41
+
+
+ > message_type[7] > field[16] > label:
+desc_test_complex.proto:201:9
+desc_test_complex.proto:201:17
+
+
+ > message_type[7] > field[16] > type:
+desc_test_complex.proto:201:18
+desc_test_complex.proto:201:26
+
+
+ > message_type[7] > field[16] > name:
+desc_test_complex.proto:201:27
+desc_test_complex.proto:201:35
+
+
+ > message_type[7] > field[16] > number:
+desc_test_complex.proto:201:38
+desc_test_complex.proto:201:40
+
+
+ > message_type[7] > field[17]:
+desc_test_complex.proto:202:9
+desc_test_complex.proto:202:33
+
+
+ > message_type[7] > field[17] > label:
+desc_test_complex.proto:202:9
+desc_test_complex.proto:202:17
+
+
+ > message_type[7] > field[17] > type:
+desc_test_complex.proto:202:18
+desc_test_complex.proto:202:22
+
+
+ > message_type[7] > field[17] > name:
+desc_test_complex.proto:202:23
+desc_test_complex.proto:202:27
+
+
+ > message_type[7] > field[17] > number:
+desc_test_complex.proto:202:30
+desc_test_complex.proto:202:32
+
+
+ > message_type[7] > field[18]:
+desc_test_complex.proto:203:9
+desc_test_complex.proto:203:35
+
+
+ > message_type[7] > field[18] > label:
+desc_test_complex.proto:203:9
+desc_test_complex.proto:203:17
+
+
+ > message_type[7] > field[18] > type:
+desc_test_complex.proto:203:18
+desc_test_complex.proto:203:23
+
+
+ > message_type[7] > field[18] > name:
+desc_test_complex.proto:203:24
+desc_test_complex.proto:203:29
+
+
+ > message_type[7] > field[18] > number:
+desc_test_complex.proto:203:32
+desc_test_complex.proto:203:34
+
+
+ > message_type[7] > field[19]:
+desc_test_complex.proto:204:9
+desc_test_complex.proto:204:37
+
+
+ > message_type[7] > field[19] > label:
+desc_test_complex.proto:204:9
+desc_test_complex.proto:204:17
+
+
+ > message_type[7] > field[19] > type:
+desc_test_complex.proto:204:18
+desc_test_complex.proto:204:24
+
+
+ > message_type[7] > field[19] > name:
+desc_test_complex.proto:204:25
+desc_test_complex.proto:204:31
+
+
+ > message_type[7] > field[19] > number:
+desc_test_complex.proto:204:34
+desc_test_complex.proto:204:36
+
+
+ > message_type[7] > field[20]:
+desc_test_complex.proto:205:9
+desc_test_complex.proto:205:37
+
+
+ > message_type[7] > field[20] > label:
+desc_test_complex.proto:205:9
+desc_test_complex.proto:205:17
+
+
+ > message_type[7] > field[20] > type:
+desc_test_complex.proto:205:18
+desc_test_complex.proto:205:22
+
+
+ > message_type[7] > field[20] > name:
+desc_test_complex.proto:205:23
+desc_test_complex.proto:205:31
+
+
+ > message_type[7] > field[20] > number:
+desc_test_complex.proto:205:34
+desc_test_complex.proto:205:36
+
+
+ > message_type[7] > field[21]:
+desc_test_complex.proto:206:9
+desc_test_complex.proto:206:37
+
+
+ > message_type[7] > field[21] > label:
+desc_test_complex.proto:206:9
+desc_test_complex.proto:206:17
+
+
+ > message_type[7] > field[21] > type:
+desc_test_complex.proto:206:18
+desc_test_complex.proto:206:22
+
+
+ > message_type[7] > field[21] > name:
+desc_test_complex.proto:206:23
+desc_test_complex.proto:206:31
+
+
+ > message_type[7] > field[21] > number:
+desc_test_complex.proto:206:34
+desc_test_complex.proto:206:36
+
+
+ > message_type[7] > field[22]:
+desc_test_complex.proto:207:9
+desc_test_complex.proto:207:37
+
+
+ > message_type[7] > field[22] > label:
+desc_test_complex.proto:207:9
+desc_test_complex.proto:207:17
+
+
+ > message_type[7] > field[22] > type:
+desc_test_complex.proto:207:18
+desc_test_complex.proto:207:22
+
+
+ > message_type[7] > field[22] > name:
+desc_test_complex.proto:207:23
+desc_test_complex.proto:207:31
+
+
+ > message_type[7] > field[22] > number:
+desc_test_complex.proto:207:34
+desc_test_complex.proto:207:36
+
+
+ > message_type[7] > field[23]:
+desc_test_complex.proto:208:9
+desc_test_complex.proto:208:36
+
+
+ > message_type[7] > field[23] > label:
+desc_test_complex.proto:208:9
+desc_test_complex.proto:208:17
+
+
+ > message_type[7] > field[23] > type:
+desc_test_complex.proto:208:18
+desc_test_complex.proto:208:22
+
+
+ > message_type[7] > field[23] > name:
+desc_test_complex.proto:208:23
+desc_test_complex.proto:208:30
+
+
+ > message_type[7] > field[23] > number:
+desc_test_complex.proto:208:33
+desc_test_complex.proto:208:35
+
+
+ > message_type[7] > field[24]:
+desc_test_complex.proto:209:9
+desc_test_complex.proto:209:33
+
+
+ > message_type[7] > field[24] > label:
+desc_test_complex.proto:209:9
+desc_test_complex.proto:209:17
+
+
+ > message_type[7] > field[24] > type:
+desc_test_complex.proto:209:18
+desc_test_complex.proto:209:22
+
+
+ > message_type[7] > field[24] > name:
+desc_test_complex.proto:209:23
+desc_test_complex.proto:209:27
+
+
+ > message_type[7] > field[24] > number:
+desc_test_complex.proto:209:30
+desc_test_complex.proto:209:32
+
+
+ > message_type[7] > field[25]:
+desc_test_complex.proto:210:9
+desc_test_complex.proto:210:36
+
+
+ > message_type[7] > field[25] > label:
+desc_test_complex.proto:210:9
+desc_test_complex.proto:210:17
+
+
+ > message_type[7] > field[25] > type:
+desc_test_complex.proto:210:18
+desc_test_complex.proto:210:22
+
+
+ > message_type[7] > field[25] > name:
+desc_test_complex.proto:210:23
+desc_test_complex.proto:210:30
+
+
+ > message_type[7] > field[25] > number:
+desc_test_complex.proto:210:33
+desc_test_complex.proto:210:35
+
+
+ > message_type[7] > field[26]:
+desc_test_complex.proto:211:9
+desc_test_complex.proto:211:32
+
+
+ > message_type[7] > field[26] > label:
+desc_test_complex.proto:211:9
+desc_test_complex.proto:211:17
+
+
+ > message_type[7] > field[26] > type:
+desc_test_complex.proto:211:18
+desc_test_complex.proto:211:22
+
+
+ > message_type[7] > field[26] > name:
+desc_test_complex.proto:211:23
+desc_test_complex.proto:211:26
+
+
+ > message_type[7] > field[26] > number:
+desc_test_complex.proto:211:29
+desc_test_complex.proto:211:31
+
+
+ > message_type[7] > field[27]:
+desc_test_complex.proto:212:9
+desc_test_complex.proto:212:35
+
+
+ > message_type[7] > field[27] > label:
+desc_test_complex.proto:212:9
+desc_test_complex.proto:212:17
+
+
+ > message_type[7] > field[27] > type:
+desc_test_complex.proto:212:18
+desc_test_complex.proto:212:22
+
+
+ > message_type[7] > field[27] > name:
+desc_test_complex.proto:212:23
+desc_test_complex.proto:212:29
+
+
+ > message_type[7] > field[27] > number:
+desc_test_complex.proto:212:32
+desc_test_complex.proto:212:34
+
+
+ > message_type[7] > field[28]:
+desc_test_complex.proto:213:9
+desc_test_complex.proto:213:35
+
+
+ > message_type[7] > field[28] > label:
+desc_test_complex.proto:213:9
+desc_test_complex.proto:213:17
+
+
+ > message_type[7] > field[28] > type:
+desc_test_complex.proto:213:18
+desc_test_complex.proto:213:22
+
+
+ > message_type[7] > field[28] > name:
+desc_test_complex.proto:213:23
+desc_test_complex.proto:213:29
+
+
+ > message_type[7] > field[28] > number:
+desc_test_complex.proto:213:32
+desc_test_complex.proto:213:34
+
+
+ > message_type[7] > field[29]:
+desc_test_complex.proto:214:9
+desc_test_complex.proto:214:39
+
+
+ > message_type[7] > field[29] > label:
+desc_test_complex.proto:214:9
+desc_test_complex.proto:214:17
+
+
+ > message_type[7] > field[29] > type:
+desc_test_complex.proto:214:18
+desc_test_complex.proto:214:22
+
+
+ > message_type[7] > field[29] > name:
+desc_test_complex.proto:214:23
+desc_test_complex.proto:214:33
+
+
+ > message_type[7] > field[29] > number:
+desc_test_complex.proto:214:36
+desc_test_complex.proto:214:38
+
+
+ > message_type[7] > field[30]:
+desc_test_complex.proto:215:9
+desc_test_complex.proto:215:37
+
+
+ > message_type[7] > field[30] > label:
+desc_test_complex.proto:215:9
+desc_test_complex.proto:215:17
+
+
+ > message_type[7] > field[30] > type:
+desc_test_complex.proto:215:18
+desc_test_complex.proto:215:22
+
+
+ > message_type[7] > field[30] > name:
+desc_test_complex.proto:215:23
+desc_test_complex.proto:215:31
+
+
+ > message_type[7] > field[30] > number:
+desc_test_complex.proto:215:34
+desc_test_complex.proto:215:36
+
+
+ > message_type[7] > field[31]:
+desc_test_complex.proto:216:9
+desc_test_complex.proto:216:31
+
+
+ > message_type[7] > field[31] > label:
+desc_test_complex.proto:216:9
+desc_test_complex.proto:216:17
+
+
+ > message_type[7] > field[31] > type:
+desc_test_complex.proto:216:18
+desc_test_complex.proto:216:22
+
+
+ > message_type[7] > field[31] > name:
+desc_test_complex.proto:216:23
+desc_test_complex.proto:216:25
+
+
+ > message_type[7] > field[31] > number:
+desc_test_complex.proto:216:28
+desc_test_complex.proto:216:30
+
+
+ > message_type[7] > field[32]:
+desc_test_complex.proto:217:9
+desc_test_complex.proto:217:34
+
+
+ > message_type[7] > field[32] > label:
+desc_test_complex.proto:217:9
+desc_test_complex.proto:217:17
+
+
+ > message_type[7] > field[32] > type:
+desc_test_complex.proto:217:18
+desc_test_complex.proto:217:23
+
+
+ > message_type[7] > field[32] > name:
+desc_test_complex.proto:217:24
+desc_test_complex.proto:217:28
+
+
+ > message_type[7] > field[32] > number:
+desc_test_complex.proto:217:31
+desc_test_complex.proto:217:33
+
+
+ > message_type[7] > field[33]:
+desc_test_complex.proto:218:9
+desc_test_complex.proto:218:35
+
+
+ > message_type[7] > field[33] > label:
+desc_test_complex.proto:218:9
+desc_test_complex.proto:218:17
+
+
+ > message_type[7] > field[33] > type:
+desc_test_complex.proto:218:18
+desc_test_complex.proto:218:23
+
+
+ > message_type[7] > field[33] > name:
+desc_test_complex.proto:218:24
+desc_test_complex.proto:218:29
+
+
+ > message_type[7] > field[33] > number:
+desc_test_complex.proto:218:32
+desc_test_complex.proto:218:34
+
+
+ > message_type[7] > field[34]:
+desc_test_complex.proto:219:9
+desc_test_complex.proto:219:37
+
+
+ > message_type[7] > field[34] > label:
+desc_test_complex.proto:219:9
+desc_test_complex.proto:219:17
+
+
+ > message_type[7] > field[34] > type:
+desc_test_complex.proto:219:18
+desc_test_complex.proto:219:23
+
+
+ > message_type[7] > field[34] > name:
+desc_test_complex.proto:219:24
+desc_test_complex.proto:219:31
+
+
+ > message_type[7] > field[34] > number:
+desc_test_complex.proto:219:34
+desc_test_complex.proto:219:36
+
+
+ > extension:
+desc_test_complex.proto:222:1
+desc_test_complex.proto:259:2
+
+
+ > extension[6]:
+desc_test_complex.proto:223:9
+desc_test_complex.proto:223:38
+
+
+ > extension[6] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[6] > label:
+desc_test_complex.proto:223:9
+desc_test_complex.proto:223:17
+
+
+ > extension[6] > type:
+desc_test_complex.proto:223:18
+desc_test_complex.proto:223:22
+
+
+ > extension[6] > name:
+desc_test_complex.proto:223:23
+desc_test_complex.proto:223:29
+
+
+ > extension[6] > number:
+desc_test_complex.proto:223:32
+desc_test_complex.proto:223:37
+
+
+ > extension[7]:
+desc_test_complex.proto:224:9
+desc_test_complex.proto:224:38
+
+
+ > extension[7] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[7] > label:
+desc_test_complex.proto:224:9
+desc_test_complex.proto:224:17
+
+
+ > extension[7] > type:
+desc_test_complex.proto:224:18
+desc_test_complex.proto:224:22
+
+
+ > extension[7] > name:
+desc_test_complex.proto:224:23
+desc_test_complex.proto:224:29
+
+
+ > extension[7] > number:
+desc_test_complex.proto:224:32
+desc_test_complex.proto:224:37
+
+
+ > extension[8]:
+desc_test_complex.proto:225:9
+desc_test_complex.proto:225:38
+
+
+ > extension[8] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[8] > label:
+desc_test_complex.proto:225:9
+desc_test_complex.proto:225:17
+
+
+ > extension[8] > type:
+desc_test_complex.proto:225:18
+desc_test_complex.proto:225:22
+
+
+ > extension[8] > name:
+desc_test_complex.proto:225:23
+desc_test_complex.proto:225:29
+
+
+ > extension[8] > number:
+desc_test_complex.proto:225:32
+desc_test_complex.proto:225:37
+
+
+ > extension[9]:
+desc_test_complex.proto:226:9
+desc_test_complex.proto:226:36
+
+
+ > extension[9] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[9] > label:
+desc_test_complex.proto:226:9
+desc_test_complex.proto:226:17
+
+
+ > extension[9] > type:
+desc_test_complex.proto:226:18
+desc_test_complex.proto:226:22
+
+
+ > extension[9] > name:
+desc_test_complex.proto:226:23
+desc_test_complex.proto:226:27
+
+
+ > extension[9] > number:
+desc_test_complex.proto:226:30
+desc_test_complex.proto:226:35
+
+
+ > extension[10]:
+desc_test_complex.proto:227:9
+desc_test_complex.proto:227:39
+
+
+ > extension[10] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[10] > label:
+desc_test_complex.proto:227:9
+desc_test_complex.proto:227:17
+
+
+ > extension[10] > type:
+desc_test_complex.proto:227:18
+desc_test_complex.proto:227:22
+
+
+ > extension[10] > name:
+desc_test_complex.proto:227:23
+desc_test_complex.proto:227:30
+
+
+ > extension[10] > number:
+desc_test_complex.proto:227:33
+desc_test_complex.proto:227:38
+
+
+ > extension[11]:
+desc_test_complex.proto:228:9
+desc_test_complex.proto:228:40
+
+
+ > extension[11] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[11] > label:
+desc_test_complex.proto:228:9
+desc_test_complex.proto:228:17
+
+
+ > extension[11] > type:
+desc_test_complex.proto:228:18
+desc_test_complex.proto:228:24
+
+
+ > extension[11] > name:
+desc_test_complex.proto:228:25
+desc_test_complex.proto:228:31
+
+
+ > extension[11] > number:
+desc_test_complex.proto:228:34
+desc_test_complex.proto:228:39
+
+
+ > extension[12]:
+desc_test_complex.proto:229:9
+desc_test_complex.proto:229:38
+
+
+ > extension[12] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[12] > label:
+desc_test_complex.proto:229:9
+desc_test_complex.proto:229:17
+
+
+ > extension[12] > type:
+desc_test_complex.proto:229:18
+desc_test_complex.proto:229:23
+
+
+ > extension[12] > name:
+desc_test_complex.proto:229:24
+desc_test_complex.proto:229:29
+
+
+ > extension[12] > number:
+desc_test_complex.proto:229:32
+desc_test_complex.proto:229:37
+
+
+ > extension[13]:
+desc_test_complex.proto:230:9
+desc_test_complex.proto:230:38
+
+
+ > extension[13] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[13] > label:
+desc_test_complex.proto:230:9
+desc_test_complex.proto:230:17
+
+
+ > extension[13] > type:
+desc_test_complex.proto:230:18
+desc_test_complex.proto:230:23
+
+
+ > extension[13] > name:
+desc_test_complex.proto:230:24
+desc_test_complex.proto:230:29
+
+
+ > extension[13] > number:
+desc_test_complex.proto:230:32
+desc_test_complex.proto:230:37
+
+
+ > extension[14]:
+desc_test_complex.proto:231:9
+desc_test_complex.proto:231:38
+
+
+ > extension[14] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[14] > label:
+desc_test_complex.proto:231:9
+desc_test_complex.proto:231:17
+
+
+ > extension[14] > type:
+desc_test_complex.proto:231:18
+desc_test_complex.proto:231:23
+
+
+ > extension[14] > name:
+desc_test_complex.proto:231:24
+desc_test_complex.proto:231:29
+
+
+ > extension[14] > number:
+desc_test_complex.proto:231:32
+desc_test_complex.proto:231:37
+
+
+ > extension[15]:
+desc_test_complex.proto:232:9
+desc_test_complex.proto:232:40
+
+
+ > extension[15] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[15] > label:
+desc_test_complex.proto:232:9
+desc_test_complex.proto:232:17
+
+
+ > extension[15] > type:
+desc_test_complex.proto:232:18
+desc_test_complex.proto:232:24
+
+
+ > extension[15] > name:
+desc_test_complex.proto:232:25
+desc_test_complex.proto:232:31
+
+
+ > extension[15] > number:
+desc_test_complex.proto:232:34
+desc_test_complex.proto:232:39
+
+
+ > extension[16]:
+desc_test_complex.proto:233:9
+desc_test_complex.proto:233:40
+
+
+ > extension[16] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[16] > label:
+desc_test_complex.proto:233:9
+desc_test_complex.proto:233:17
+
+
+ > extension[16] > type:
+desc_test_complex.proto:233:18
+desc_test_complex.proto:233:24
+
+
+ > extension[16] > name:
+desc_test_complex.proto:233:25
+desc_test_complex.proto:233:31
+
+
+ > extension[16] > number:
+desc_test_complex.proto:233:34
+desc_test_complex.proto:233:39
+
+
+ > extension[17]:
+desc_test_complex.proto:234:9
+desc_test_complex.proto:234:40
+
+
+ > extension[17] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[17] > label:
+desc_test_complex.proto:234:9
+desc_test_complex.proto:234:17
+
+
+ > extension[17] > type:
+desc_test_complex.proto:234:18
+desc_test_complex.proto:234:24
+
+
+ > extension[17] > name:
+desc_test_complex.proto:234:25
+desc_test_complex.proto:234:31
+
+
+ > extension[17] > number:
+desc_test_complex.proto:234:34
+desc_test_complex.proto:234:39
+
+
+ > extension[18]:
+desc_test_complex.proto:235:9
+desc_test_complex.proto:235:40
+
+
+ > extension[18] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[18] > label:
+desc_test_complex.proto:235:9
+desc_test_complex.proto:235:17
+
+
+ > extension[18] > type:
+desc_test_complex.proto:235:18
+desc_test_complex.proto:235:24
+
+
+ > extension[18] > name:
+desc_test_complex.proto:235:25
+desc_test_complex.proto:235:31
+
+
+ > extension[18] > number:
+desc_test_complex.proto:235:34
+desc_test_complex.proto:235:39
+
+
+ > extension[19]:
+desc_test_complex.proto:236:9
+desc_test_complex.proto:236:42
+
+
+ > extension[19] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[19] > label:
+desc_test_complex.proto:236:9
+desc_test_complex.proto:236:17
+
+
+ > extension[19] > type:
+desc_test_complex.proto:236:18
+desc_test_complex.proto:236:25
+
+
+ > extension[19] > name:
+desc_test_complex.proto:236:26
+desc_test_complex.proto:236:33
+
+
+ > extension[19] > number:
+desc_test_complex.proto:236:36
+desc_test_complex.proto:236:41
+
+
+ > extension[20]:
+desc_test_complex.proto:237:9
+desc_test_complex.proto:237:42
+
+
+ > extension[20] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[20] > label:
+desc_test_complex.proto:237:9
+desc_test_complex.proto:237:17
+
+
+ > extension[20] > type:
+desc_test_complex.proto:237:18
+desc_test_complex.proto:237:25
+
+
+ > extension[20] > name:
+desc_test_complex.proto:237:26
+desc_test_complex.proto:237:33
+
+
+ > extension[20] > number:
+desc_test_complex.proto:237:36
+desc_test_complex.proto:237:41
+
+
+ > extension[21]:
+desc_test_complex.proto:238:9
+desc_test_complex.proto:238:44
+
+
+ > extension[21] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[21] > label:
+desc_test_complex.proto:238:9
+desc_test_complex.proto:238:17
+
+
+ > extension[21] > type:
+desc_test_complex.proto:238:18
+desc_test_complex.proto:238:26
+
+
+ > extension[21] > name:
+desc_test_complex.proto:238:27
+desc_test_complex.proto:238:35
+
+
+ > extension[21] > number:
+desc_test_complex.proto:238:38
+desc_test_complex.proto:238:43
+
+
+ > extension[22]:
+desc_test_complex.proto:239:9
+desc_test_complex.proto:239:44
+
+
+ > extension[22] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[22] > label:
+desc_test_complex.proto:239:9
+desc_test_complex.proto:239:17
+
+
+ > extension[22] > type:
+desc_test_complex.proto:239:18
+desc_test_complex.proto:239:26
+
+
+ > extension[22] > name:
+desc_test_complex.proto:239:27
+desc_test_complex.proto:239:35
+
+
+ > extension[22] > number:
+desc_test_complex.proto:239:38
+desc_test_complex.proto:239:43
+
+
+ > extension[23]:
+desc_test_complex.proto:240:9
+desc_test_complex.proto:240:36
+
+
+ > extension[23] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[23] > label:
+desc_test_complex.proto:240:9
+desc_test_complex.proto:240:17
+
+
+ > extension[23] > type:
+desc_test_complex.proto:240:18
+desc_test_complex.proto:240:22
+
+
+ > extension[23] > name:
+desc_test_complex.proto:240:23
+desc_test_complex.proto:240:27
+
+
+ > extension[23] > number:
+desc_test_complex.proto:240:30
+desc_test_complex.proto:240:35
+
+
+ > extension[24]:
+desc_test_complex.proto:241:9
+desc_test_complex.proto:241:38
+
+
+ > extension[24] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[24] > label:
+desc_test_complex.proto:241:9
+desc_test_complex.proto:241:17
+
+
+ > extension[24] > type:
+desc_test_complex.proto:241:18
+desc_test_complex.proto:241:23
+
+
+ > extension[24] > name:
+desc_test_complex.proto:241:24
+desc_test_complex.proto:241:29
+
+
+ > extension[24] > number:
+desc_test_complex.proto:241:32
+desc_test_complex.proto:241:37
+
+
+ > extension[25]:
+desc_test_complex.proto:242:9
+desc_test_complex.proto:242:40
+
+
+ > extension[25] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[25] > label:
+desc_test_complex.proto:242:9
+desc_test_complex.proto:242:17
+
+
+ > extension[25] > type:
+desc_test_complex.proto:242:18
+desc_test_complex.proto:242:24
+
+
+ > extension[25] > name:
+desc_test_complex.proto:242:25
+desc_test_complex.proto:242:31
+
+
+ > extension[25] > number:
+desc_test_complex.proto:242:34
+desc_test_complex.proto:242:39
+
+
+ > extension[26]:
+desc_test_complex.proto:243:9
+desc_test_complex.proto:243:40
+
+
+ > extension[26] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[26] > label:
+desc_test_complex.proto:243:9
+desc_test_complex.proto:243:17
+
+
+ > extension[26] > type:
+desc_test_complex.proto:243:18
+desc_test_complex.proto:243:22
+
+
+ > extension[26] > name:
+desc_test_complex.proto:243:23
+desc_test_complex.proto:243:31
+
+
+ > extension[26] > number:
+desc_test_complex.proto:243:34
+desc_test_complex.proto:243:39
+
+
+ > extension[27]:
+desc_test_complex.proto:244:9
+desc_test_complex.proto:244:40
+
+
+ > extension[27] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[27] > label:
+desc_test_complex.proto:244:9
+desc_test_complex.proto:244:17
+
+
+ > extension[27] > type:
+desc_test_complex.proto:244:18
+desc_test_complex.proto:244:22
+
+
+ > extension[27] > name:
+desc_test_complex.proto:244:23
+desc_test_complex.proto:244:31
+
+
+ > extension[27] > number:
+desc_test_complex.proto:244:34
+desc_test_complex.proto:244:39
+
+
+ > extension[28]:
+desc_test_complex.proto:245:9
+desc_test_complex.proto:245:40
+
+
+ > extension[28] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[28] > label:
+desc_test_complex.proto:245:9
+desc_test_complex.proto:245:17
+
+
+ > extension[28] > type:
+desc_test_complex.proto:245:18
+desc_test_complex.proto:245:22
+
+
+ > extension[28] > name:
+desc_test_complex.proto:245:23
+desc_test_complex.proto:245:31
+
+
+ > extension[28] > number:
+desc_test_complex.proto:245:34
+desc_test_complex.proto:245:39
+
+
+ > extension[29]:
+desc_test_complex.proto:246:9
+desc_test_complex.proto:246:39
+
+
+ > extension[29] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[29] > label:
+desc_test_complex.proto:246:9
+desc_test_complex.proto:246:17
+
+
+ > extension[29] > type:
+desc_test_complex.proto:246:18
+desc_test_complex.proto:246:22
+
+
+ > extension[29] > name:
+desc_test_complex.proto:246:23
+desc_test_complex.proto:246:30
+
+
+ > extension[29] > number:
+desc_test_complex.proto:246:33
+desc_test_complex.proto:246:38
+
+
+ > extension[30]:
+desc_test_complex.proto:247:9
+desc_test_complex.proto:247:36
+
+
+ > extension[30] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[30] > label:
+desc_test_complex.proto:247:9
+desc_test_complex.proto:247:17
+
+
+ > extension[30] > type:
+desc_test_complex.proto:247:18
+desc_test_complex.proto:247:22
+
+
+ > extension[30] > name:
+desc_test_complex.proto:247:23
+desc_test_complex.proto:247:27
+
+
+ > extension[30] > number:
+desc_test_complex.proto:247:30
+desc_test_complex.proto:247:35
+
+
+ > extension[31]:
+desc_test_complex.proto:248:9
+desc_test_complex.proto:248:39
+
+
+ > extension[31] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[31] > label:
+desc_test_complex.proto:248:9
+desc_test_complex.proto:248:17
+
+
+ > extension[31] > type:
+desc_test_complex.proto:248:18
+desc_test_complex.proto:248:22
+
+
+ > extension[31] > name:
+desc_test_complex.proto:248:23
+desc_test_complex.proto:248:30
+
+
+ > extension[31] > number:
+desc_test_complex.proto:248:33
+desc_test_complex.proto:248:38
+
+
+ > extension[32]:
+desc_test_complex.proto:249:9
+desc_test_complex.proto:249:35
+
+
+ > extension[32] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[32] > label:
+desc_test_complex.proto:249:9
+desc_test_complex.proto:249:17
+
+
+ > extension[32] > type:
+desc_test_complex.proto:249:18
+desc_test_complex.proto:249:22
+
+
+ > extension[32] > name:
+desc_test_complex.proto:249:23
+desc_test_complex.proto:249:26
+
+
+ > extension[32] > number:
+desc_test_complex.proto:249:29
+desc_test_complex.proto:249:34
+
+
+ > extension[33]:
+desc_test_complex.proto:250:9
+desc_test_complex.proto:250:38
+
+
+ > extension[33] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[33] > label:
+desc_test_complex.proto:250:9
+desc_test_complex.proto:250:17
+
+
+ > extension[33] > type:
+desc_test_complex.proto:250:18
+desc_test_complex.proto:250:22
+
+
+ > extension[33] > name:
+desc_test_complex.proto:250:23
+desc_test_complex.proto:250:29
+
+
+ > extension[33] > number:
+desc_test_complex.proto:250:32
+desc_test_complex.proto:250:37
+
+
+ > extension[34]:
+desc_test_complex.proto:251:9
+desc_test_complex.proto:251:38
+
+
+ > extension[34] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[34] > label:
+desc_test_complex.proto:251:9
+desc_test_complex.proto:251:17
+
+
+ > extension[34] > type:
+desc_test_complex.proto:251:18
+desc_test_complex.proto:251:22
+
+
+ > extension[34] > name:
+desc_test_complex.proto:251:23
+desc_test_complex.proto:251:29
+
+
+ > extension[34] > number:
+desc_test_complex.proto:251:32
+desc_test_complex.proto:251:37
+
+
+ > extension[35]:
+desc_test_complex.proto:252:9
+desc_test_complex.proto:252:42
+
+
+ > extension[35] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[35] > label:
+desc_test_complex.proto:252:9
+desc_test_complex.proto:252:17
+
+
+ > extension[35] > type:
+desc_test_complex.proto:252:18
+desc_test_complex.proto:252:22
+
+
+ > extension[35] > name:
+desc_test_complex.proto:252:23
+desc_test_complex.proto:252:33
+
+
+ > extension[35] > number:
+desc_test_complex.proto:252:36
+desc_test_complex.proto:252:41
+
+
+ > extension[36]:
+desc_test_complex.proto:253:9
+desc_test_complex.proto:253:40
+
+
+ > extension[36] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[36] > label:
+desc_test_complex.proto:253:9
+desc_test_complex.proto:253:17
+
+
+ > extension[36] > type:
+desc_test_complex.proto:253:18
+desc_test_complex.proto:253:22
+
+
+ > extension[36] > name:
+desc_test_complex.proto:253:23
+desc_test_complex.proto:253:31
+
+
+ > extension[36] > number:
+desc_test_complex.proto:253:34
+desc_test_complex.proto:253:39
+
+
+ > extension[37]:
+desc_test_complex.proto:254:9
+desc_test_complex.proto:254:34
+
+
+ > extension[37] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[37] > label:
+desc_test_complex.proto:254:9
+desc_test_complex.proto:254:17
+
+
+ > extension[37] > type:
+desc_test_complex.proto:254:18
+desc_test_complex.proto:254:22
+
+
+ > extension[37] > name:
+desc_test_complex.proto:254:23
+desc_test_complex.proto:254:25
+
+
+ > extension[37] > number:
+desc_test_complex.proto:254:28
+desc_test_complex.proto:254:33
+
+
+ > extension[38]:
+desc_test_complex.proto:255:9
+desc_test_complex.proto:255:37
+
+
+ > extension[38] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[38] > label:
+desc_test_complex.proto:255:9
+desc_test_complex.proto:255:17
+
+
+ > extension[38] > type:
+desc_test_complex.proto:255:18
+desc_test_complex.proto:255:23
+
+
+ > extension[38] > name:
+desc_test_complex.proto:255:24
+desc_test_complex.proto:255:28
+
+
+ > extension[38] > number:
+desc_test_complex.proto:255:31
+desc_test_complex.proto:255:36
+
+
+ > extension[39]:
+desc_test_complex.proto:256:9
+desc_test_complex.proto:256:38
+
+
+ > extension[39] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[39] > label:
+desc_test_complex.proto:256:9
+desc_test_complex.proto:256:17
+
+
+ > extension[39] > type:
+desc_test_complex.proto:256:18
+desc_test_complex.proto:256:23
+
+
+ > extension[39] > name:
+desc_test_complex.proto:256:24
+desc_test_complex.proto:256:29
+
+
+ > extension[39] > number:
+desc_test_complex.proto:256:32
+desc_test_complex.proto:256:37
+
+
+ > extension[40]:
+desc_test_complex.proto:257:9
+desc_test_complex.proto:257:40
+
+
+ > extension[40] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[40] > label:
+desc_test_complex.proto:257:9
+desc_test_complex.proto:257:17
+
+
+ > extension[40] > type:
+desc_test_complex.proto:257:18
+desc_test_complex.proto:257:23
+
+
+ > extension[40] > name:
+desc_test_complex.proto:257:24
+desc_test_complex.proto:257:31
+
+
+ > extension[40] > number:
+desc_test_complex.proto:257:34
+desc_test_complex.proto:257:39
+
+
+ > extension[41]:
+desc_test_complex.proto:258:9
+desc_test_complex.proto:258:49
+
+
+ > extension[41] > extendee:
+desc_test_complex.proto:222:8
+desc_test_complex.proto:222:36
+
+
+ > extension[41] > label:
+desc_test_complex.proto:258:9
+desc_test_complex.proto:258:17
+
+
+ > extension[41] > type_name:
+desc_test_complex.proto:258:18
+desc_test_complex.proto:258:35
+
+
+ > extension[41] > name:
+desc_test_complex.proto:258:36
+desc_test_complex.proto:258:40
+
+
+ > extension[41] > number:
+desc_test_complex.proto:258:43
+desc_test_complex.proto:258:48
+
+
+ > message_type[8]:
+desc_test_complex.proto:261:1
+desc_test_complex.proto:286:2
+
+
+ > message_type[8] > name:
+desc_test_complex.proto:261:9
+desc_test_complex.proto:261:32
+
+
+ > message_type[8] > field[0]:
+desc_test_complex.proto:262:9
+desc_test_complex.proto:272:11
+
+
+ > message_type[8] > field[0] > label:
+desc_test_complex.proto:262:9
+desc_test_complex.proto:262:17
+
+
+ > message_type[8] > field[0] > type:
+desc_test_complex.proto:262:18
+desc_test_complex.proto:262:24
+
+
+ > message_type[8] > field[0] > name:
+desc_test_complex.proto:262:25
+desc_test_complex.proto:262:27
+
+
+ > message_type[8] > field[0] > number:
+desc_test_complex.proto:262:30
+desc_test_complex.proto:262:31
+
+
+ > message_type[8] > field[0] > options:
+desc_test_complex.proto:262:32
+desc_test_complex.proto:272:10
+
+
+ > message_type[8] > field[0] > options > syntax:
+desc_test_complex.proto:263:17
+desc_test_complex.proto:263:32
+
+
+ > message_type[8] > field[0] > options > import:
+desc_test_complex.proto:263:34
+desc_test_complex.proto:263:49
+
+
+ > message_type[8] > field[0] > options > public:
+desc_test_complex.proto:263:51
+desc_test_complex.proto:263:66
+
+
+ > message_type[8] > field[0] > options > weak:
+desc_test_complex.proto:263:68
+desc_test_complex.proto:263:81
+
+
+ > message_type[8] > field[0] > options > package:
+desc_test_complex.proto:263:83
+desc_test_complex.proto:263:99
+
+
+ > message_type[8] > field[0] > options > string:
+desc_test_complex.proto:264:17
+desc_test_complex.proto:264:36
+
+
+ > message_type[8] > field[0] > options > bytes:
+desc_test_complex.proto:264:38
+desc_test_complex.proto:264:55
+
+
+ > message_type[8] > field[0] > options > bool:
+desc_test_complex.proto:264:57
+desc_test_complex.proto:264:70
+
+
+ > message_type[8] > field[0] > options > float:
+desc_test_complex.proto:265:17
+desc_test_complex.proto:265:31
+
+
+ > message_type[8] > field[0] > options > double:
+desc_test_complex.proto:265:33
+desc_test_complex.proto:265:51
+
+
+ > message_type[8] > field[0] > options > int32:
+desc_test_complex.proto:266:17
+desc_test_complex.proto:266:29
+
+
+ > message_type[8] > field[0] > options > int64:
+desc_test_complex.proto:266:31
+desc_test_complex.proto:266:43
+
+
+ > message_type[8] > field[0] > options > uint32:
+desc_test_complex.proto:266:45
+desc_test_complex.proto:266:60
+
+
+ > message_type[8] > field[0] > options > uint64:
+desc_test_complex.proto:266:62
+desc_test_complex.proto:266:77
+
+
+ > message_type[8] > field[0] > options > sint32:
+desc_test_complex.proto:266:79
+desc_test_complex.proto:266:93
+
+
+ > message_type[8] > field[0] > options > sint64:
+desc_test_complex.proto:266:95
+desc_test_complex.proto:266:109
+
+
+ > message_type[8] > field[0] > options > fixed32:
+desc_test_complex.proto:267:17
+desc_test_complex.proto:267:33
+
+
+ > message_type[8] > field[0] > options > fixed64:
+desc_test_complex.proto:267:35
+desc_test_complex.proto:267:51
+
+
+ > message_type[8] > field[0] > options > sfixed32:
+desc_test_complex.proto:267:53
+desc_test_complex.proto:267:71
+
+
+ > message_type[8] > field[0] > options > sfixed64:
+desc_test_complex.proto:267:73
+desc_test_complex.proto:267:91
+
+
+ > message_type[8] > field[0] > options > optional:
+desc_test_complex.proto:268:17
+desc_test_complex.proto:268:34
+
+
+ > message_type[8] > field[0] > options > repeated:
+desc_test_complex.proto:268:36
+desc_test_complex.proto:268:53
+
+
+ > message_type[8] > field[0] > options > required:
+desc_test_complex.proto:268:55
+desc_test_complex.proto:268:72
+
+
+ > message_type[8] > field[0] > options > message:
+desc_test_complex.proto:269:17
+desc_test_complex.proto:269:33
+
+
+ > message_type[8] > field[0] > options > enum:
+desc_test_complex.proto:269:35
+desc_test_complex.proto:269:48
+
+
+ > message_type[8] > field[0] > options > service:
+desc_test_complex.proto:269:50
+desc_test_complex.proto:269:66
+
+
+ > message_type[8] > field[0] > options > rpc:
+desc_test_complex.proto:269:68
+desc_test_complex.proto:269:80
+
+
+ > message_type[8] > field[0] > options > option:
+desc_test_complex.proto:270:17
+desc_test_complex.proto:270:32
+
+
+ > message_type[8] > field[0] > options > extend:
+desc_test_complex.proto:270:34
+desc_test_complex.proto:270:49
+
+
+ > message_type[8] > field[0] > options > extensions:
+desc_test_complex.proto:270:51
+desc_test_complex.proto:270:70
+
+
+ > message_type[8] > field[0] > options > reserved:
+desc_test_complex.proto:270:72
+desc_test_complex.proto:270:89
+
+
+ > message_type[8] > field[0] > options > to:
+desc_test_complex.proto:271:17
+desc_test_complex.proto:271:28
+
+
+ > message_type[8] > field[0] > options > true:
+desc_test_complex.proto:271:30
+desc_test_complex.proto:271:42
+
+
+ > message_type[8] > field[0] > options > false:
+desc_test_complex.proto:271:44
+desc_test_complex.proto:271:58
+
+
+ > message_type[8] > field[0] > options > default:
+desc_test_complex.proto:271:60
+desc_test_complex.proto:271:75
+
+
+ > message_type[8] > field[1]:
+desc_test_complex.proto:273:9
+desc_test_complex.proto:285:11
+
+
+ > message_type[8] > field[1] > label:
+desc_test_complex.proto:273:9
+desc_test_complex.proto:273:17
+
+
+ > message_type[8] > field[1] > type:
+desc_test_complex.proto:273:18
+desc_test_complex.proto:273:24
+
+
+ > message_type[8] > field[1] > name:
+desc_test_complex.proto:273:25
+desc_test_complex.proto:273:29
+
+
+ > message_type[8] > field[1] > number:
+desc_test_complex.proto:273:32
+desc_test_complex.proto:273:33
+
+
+ > message_type[8] > field[1] > options:
+desc_test_complex.proto:273:34
+desc_test_complex.proto:285:10
+
+
+ > message_type[8] > field[1] > options > boom:
+desc_test_complex.proto:274:17
+desc_test_complex.proto:284:18
 ---- desc_test_options.proto ----
 
 
 :
 desc_test_options.proto:1:1
-desc_test_options.proto:62:34
+desc_test_options.proto:63:2
 
 
  > syntax:
@@ -942,49 +5383,54 @@
 desc_test_options.proto:5:20
 
 
- > dependency:
-desc_test_options.proto:7:1
-desc_test_options.proto:7:43
-
-
  > dependency[0]:
 desc_test_options.proto:7:1
 desc_test_options.proto:7:43
 
 
+ > extension:
+desc_test_options.proto:9:1
+desc_test_options.proto:11:2
+
+
+ > extension[0]:
+desc_test_options.proto:10:9
+desc_test_options.proto:10:38
+
+
  > extension[0] > extendee:
 desc_test_options.proto:9:8
 desc_test_options.proto:9:38
 
 
- > extension:
-desc_test_options.proto:10:2
-desc_test_options.proto:62:34
-
-
- > extension[0]:
-desc_test_options.proto:10:2
-desc_test_options.proto:10:31
-
-
  > extension[0] > label:
-desc_test_options.proto:10:2
-desc_test_options.proto:10:10
+desc_test_options.proto:10:9
+desc_test_options.proto:10:17
 
 
  > extension[0] > type:
-desc_test_options.proto:10:11
-desc_test_options.proto:10:15
-
-
- > extension[0] > name:
-desc_test_options.proto:10:16
+desc_test_options.proto:10:18
 desc_test_options.proto:10:22
 
 
+ > extension[0] > name:
+desc_test_options.proto:10:23
+desc_test_options.proto:10:29
+
+
  > extension[0] > number:
-desc_test_options.proto:10:25
-desc_test_options.proto:10:30
+desc_test_options.proto:10:32
+desc_test_options.proto:10:37
+
+
+ > extension:
+desc_test_options.proto:13:1
+desc_test_options.proto:16:2
+
+
+ > extension[1]:
+desc_test_options.proto:14:9
+desc_test_options.proto:14:40
 
 
  > extension[1] > extendee:
@@ -992,59 +5438,64 @@
 desc_test_options.proto:13:36
 
 
+ > extension[1] > label:
+desc_test_options.proto:14:9
+desc_test_options.proto:14:17
+
+
+ > extension[1] > type:
+desc_test_options.proto:14:18
+desc_test_options.proto:14:24
+
+
+ > extension[1] > name:
+desc_test_options.proto:14:25
+desc_test_options.proto:14:31
+
+
+ > extension[1] > number:
+desc_test_options.proto:14:34
+desc_test_options.proto:14:39
+
+
+ > extension[2]:
+desc_test_options.proto:15:9
+desc_test_options.proto:15:40
+
+
  > extension[2] > extendee:
 desc_test_options.proto:13:8
 desc_test_options.proto:13:36
 
 
- > extension[1]:
-desc_test_options.proto:14:2
-desc_test_options.proto:14:33
-
-
- > extension[1] > label:
-desc_test_options.proto:14:2
-desc_test_options.proto:14:10
-
-
- > extension[1] > type:
-desc_test_options.proto:14:11
-desc_test_options.proto:14:17
-
-
- > extension[1] > name:
-desc_test_options.proto:14:18
-desc_test_options.proto:14:24
-
-
- > extension[1] > number:
-desc_test_options.proto:14:27
-desc_test_options.proto:14:32
-
-
- > extension[2]:
-desc_test_options.proto:15:2
-desc_test_options.proto:15:33
-
-
  > extension[2] > label:
-desc_test_options.proto:15:2
-desc_test_options.proto:15:10
+desc_test_options.proto:15:9
+desc_test_options.proto:15:17
 
 
  > extension[2] > type:
-desc_test_options.proto:15:11
-desc_test_options.proto:15:16
+desc_test_options.proto:15:18
+desc_test_options.proto:15:23
 
 
  > extension[2] > name:
-desc_test_options.proto:15:17
 desc_test_options.proto:15:24
+desc_test_options.proto:15:31
 
 
  > extension[2] > number:
-desc_test_options.proto:15:27
-desc_test_options.proto:15:32
+desc_test_options.proto:15:34
+desc_test_options.proto:15:39
+
+
+ > extension:
+desc_test_options.proto:18:1
+desc_test_options.proto:24:2
+
+
+ > extension[3]:
+desc_test_options.proto:19:9
+desc_test_options.proto:19:39
 
 
  > extension[3] > extendee:
@@ -1052,149 +5503,154 @@
 desc_test_options.proto:18:35
 
 
+ > extension[3] > label:
+desc_test_options.proto:19:9
+desc_test_options.proto:19:17
+
+
+ > extension[3] > type:
+desc_test_options.proto:19:18
+desc_test_options.proto:19:23
+
+
+ > extension[3] > name:
+desc_test_options.proto:19:24
+desc_test_options.proto:19:30
+
+
+ > extension[3] > number:
+desc_test_options.proto:19:33
+desc_test_options.proto:19:38
+
+
+ > extension[4]:
+desc_test_options.proto:20:9
+desc_test_options.proto:20:41
+
+
  > extension[4] > extendee:
 desc_test_options.proto:18:8
 desc_test_options.proto:18:35
 
 
+ > extension[4] > label:
+desc_test_options.proto:20:9
+desc_test_options.proto:20:17
+
+
+ > extension[4] > type:
+desc_test_options.proto:20:18
+desc_test_options.proto:20:24
+
+
+ > extension[4] > name:
+desc_test_options.proto:20:25
+desc_test_options.proto:20:32
+
+
+ > extension[4] > number:
+desc_test_options.proto:20:35
+desc_test_options.proto:20:40
+
+
+ > extension[5]:
+desc_test_options.proto:21:9
+desc_test_options.proto:21:44
+
+
  > extension[5] > extendee:
 desc_test_options.proto:18:8
 desc_test_options.proto:18:35
 
 
+ > extension[5] > label:
+desc_test_options.proto:21:9
+desc_test_options.proto:21:17
+
+
+ > extension[5] > type:
+desc_test_options.proto:21:18
+desc_test_options.proto:21:26
+
+
+ > extension[5] > name:
+desc_test_options.proto:21:27
+desc_test_options.proto:21:35
+
+
+ > extension[5] > number:
+desc_test_options.proto:21:38
+desc_test_options.proto:21:43
+
+
+ > extension[6]:
+desc_test_options.proto:22:9
+desc_test_options.proto:22:41
+
+
  > extension[6] > extendee:
 desc_test_options.proto:18:8
 desc_test_options.proto:18:35
 
 
+ > extension[6] > label:
+desc_test_options.proto:22:9
+desc_test_options.proto:22:17
+
+
+ > extension[6] > type:
+desc_test_options.proto:22:18
+desc_test_options.proto:22:24
+
+
+ > extension[6] > name:
+desc_test_options.proto:22:25
+desc_test_options.proto:22:32
+
+
+ > extension[6] > number:
+desc_test_options.proto:22:35
+desc_test_options.proto:22:40
+
+
+ > extension[7]:
+desc_test_options.proto:23:9
+desc_test_options.proto:23:43
+
+
  > extension[7] > extendee:
 desc_test_options.proto:18:8
 desc_test_options.proto:18:35
 
 
- > extension[3]:
-desc_test_options.proto:19:2
-desc_test_options.proto:19:32
-
-
- > extension[3] > label:
-desc_test_options.proto:19:2
-desc_test_options.proto:19:10
-
-
- > extension[3] > type:
-desc_test_options.proto:19:11
-desc_test_options.proto:19:16
-
-
- > extension[3] > name:
-desc_test_options.proto:19:17
-desc_test_options.proto:19:23
-
-
- > extension[3] > number:
-desc_test_options.proto:19:26
-desc_test_options.proto:19:31
-
-
- > extension[4]:
-desc_test_options.proto:20:2
-desc_test_options.proto:20:34
-
-
- > extension[4] > label:
-desc_test_options.proto:20:2
-desc_test_options.proto:20:10
-
-
- > extension[4] > type:
-desc_test_options.proto:20:11
-desc_test_options.proto:20:17
-
-
- > extension[4] > name:
-desc_test_options.proto:20:18
-desc_test_options.proto:20:25
-
-
- > extension[4] > number:
-desc_test_options.proto:20:28
-desc_test_options.proto:20:33
-
-
- > extension[5]:
-desc_test_options.proto:21:2
-desc_test_options.proto:21:37
-
-
- > extension[5] > label:
-desc_test_options.proto:21:2
-desc_test_options.proto:21:10
-
-
- > extension[5] > type:
-desc_test_options.proto:21:11
-desc_test_options.proto:21:19
-
-
- > extension[5] > name:
-desc_test_options.proto:21:20
-desc_test_options.proto:21:28
-
-
- > extension[5] > number:
-desc_test_options.proto:21:31
-desc_test_options.proto:21:36
-
-
- > extension[6]:
-desc_test_options.proto:22:2
-desc_test_options.proto:22:34
-
-
- > extension[6] > label:
-desc_test_options.proto:22:2
-desc_test_options.proto:22:10
-
-
- > extension[6] > type:
-desc_test_options.proto:22:11
-desc_test_options.proto:22:17
-
-
- > extension[6] > name:
-desc_test_options.proto:22:18
-desc_test_options.proto:22:25
-
-
- > extension[6] > number:
-desc_test_options.proto:22:28
-desc_test_options.proto:22:33
-
-
- > extension[7]:
-desc_test_options.proto:23:2
-desc_test_options.proto:23:36
-
-
  > extension[7] > label:
-desc_test_options.proto:23:2
-desc_test_options.proto:23:10
+desc_test_options.proto:23:9
+desc_test_options.proto:23:17
 
 
  > extension[7] > type:
-desc_test_options.proto:23:11
 desc_test_options.proto:23:18
+desc_test_options.proto:23:25
 
 
  > extension[7] > name:
-desc_test_options.proto:23:19
-desc_test_options.proto:23:27
+desc_test_options.proto:23:26
+desc_test_options.proto:23:34
 
 
  > extension[7] > number:
-desc_test_options.proto:23:30
-desc_test_options.proto:23:35
+desc_test_options.proto:23:37
+desc_test_options.proto:23:42
+
+
+ > extension:
+desc_test_options.proto:26:1
+desc_test_options.proto:32:2
+
+
+ > extension[8]:
+desc_test_options.proto:27:9
+desc_test_options.proto:27:40
 
 
  > extension[8] > extendee:
@@ -1202,149 +5658,154 @@
 desc_test_options.proto:26:40
 
 
+ > extension[8] > label:
+desc_test_options.proto:27:9
+desc_test_options.proto:27:17
+
+
+ > extension[8] > type:
+desc_test_options.proto:27:18
+desc_test_options.proto:27:23
+
+
+ > extension[8] > name:
+desc_test_options.proto:27:24
+desc_test_options.proto:27:31
+
+
+ > extension[8] > number:
+desc_test_options.proto:27:34
+desc_test_options.proto:27:39
+
+
+ > extension[9]:
+desc_test_options.proto:28:9
+desc_test_options.proto:28:42
+
+
  > extension[9] > extendee:
 desc_test_options.proto:26:8
 desc_test_options.proto:26:40
 
 
+ > extension[9] > label:
+desc_test_options.proto:28:9
+desc_test_options.proto:28:17
+
+
+ > extension[9] > type:
+desc_test_options.proto:28:18
+desc_test_options.proto:28:24
+
+
+ > extension[9] > name:
+desc_test_options.proto:28:25
+desc_test_options.proto:28:33
+
+
+ > extension[9] > number:
+desc_test_options.proto:28:36
+desc_test_options.proto:28:41
+
+
+ > extension[10]:
+desc_test_options.proto:29:9
+desc_test_options.proto:29:45
+
+
  > extension[10] > extendee:
 desc_test_options.proto:26:8
 desc_test_options.proto:26:40
 
 
+ > extension[10] > label:
+desc_test_options.proto:29:9
+desc_test_options.proto:29:17
+
+
+ > extension[10] > type:
+desc_test_options.proto:29:18
+desc_test_options.proto:29:26
+
+
+ > extension[10] > name:
+desc_test_options.proto:29:27
+desc_test_options.proto:29:36
+
+
+ > extension[10] > number:
+desc_test_options.proto:29:39
+desc_test_options.proto:29:44
+
+
+ > extension[11]:
+desc_test_options.proto:30:9
+desc_test_options.proto:30:42
+
+
  > extension[11] > extendee:
 desc_test_options.proto:26:8
 desc_test_options.proto:26:40
 
 
+ > extension[11] > label:
+desc_test_options.proto:30:9
+desc_test_options.proto:30:17
+
+
+ > extension[11] > type:
+desc_test_options.proto:30:18
+desc_test_options.proto:30:24
+
+
+ > extension[11] > name:
+desc_test_options.proto:30:25
+desc_test_options.proto:30:33
+
+
+ > extension[11] > number:
+desc_test_options.proto:30:36
+desc_test_options.proto:30:41
+
+
+ > extension[12]:
+desc_test_options.proto:31:9
+desc_test_options.proto:31:44
+
+
  > extension[12] > extendee:
 desc_test_options.proto:26:8
 desc_test_options.proto:26:40
 
 
- > extension[8]:
-desc_test_options.proto:27:2
-desc_test_options.proto:27:33
-
-
- > extension[8] > label:
-desc_test_options.proto:27:2
-desc_test_options.proto:27:10
-
-
- > extension[8] > type:
-desc_test_options.proto:27:11
-desc_test_options.proto:27:16
-
-
- > extension[8] > name:
-desc_test_options.proto:27:17
-desc_test_options.proto:27:24
-
-
- > extension[8] > number:
-desc_test_options.proto:27:27
-desc_test_options.proto:27:32
-
-
- > extension[9]:
-desc_test_options.proto:28:2
-desc_test_options.proto:28:35
-
-
- > extension[9] > label:
-desc_test_options.proto:28:2
-desc_test_options.proto:28:10
-
-
- > extension[9] > type:
-desc_test_options.proto:28:11
-desc_test_options.proto:28:17
-
-
- > extension[9] > name:
-desc_test_options.proto:28:18
-desc_test_options.proto:28:26
-
-
- > extension[9] > number:
-desc_test_options.proto:28:29
-desc_test_options.proto:28:34
-
-
- > extension[10]:
-desc_test_options.proto:29:2
-desc_test_options.proto:29:38
-
-
- > extension[10] > label:
-desc_test_options.proto:29:2
-desc_test_options.proto:29:10
-
-
- > extension[10] > type:
-desc_test_options.proto:29:11
-desc_test_options.proto:29:19
-
-
- > extension[10] > name:
-desc_test_options.proto:29:20
-desc_test_options.proto:29:29
-
-
- > extension[10] > number:
-desc_test_options.proto:29:32
-desc_test_options.proto:29:37
-
-
- > extension[11]:
-desc_test_options.proto:30:2
-desc_test_options.proto:30:35
-
-
- > extension[11] > label:
-desc_test_options.proto:30:2
-desc_test_options.proto:30:10
-
-
- > extension[11] > type:
-desc_test_options.proto:30:11
-desc_test_options.proto:30:17
-
-
- > extension[11] > name:
-desc_test_options.proto:30:18
-desc_test_options.proto:30:26
-
-
- > extension[11] > number:
-desc_test_options.proto:30:29
-desc_test_options.proto:30:34
-
-
- > extension[12]:
-desc_test_options.proto:31:2
-desc_test_options.proto:31:37
-
-
  > extension[12] > label:
-desc_test_options.proto:31:2
-desc_test_options.proto:31:10
+desc_test_options.proto:31:9
+desc_test_options.proto:31:17
 
 
  > extension[12] > type:
-desc_test_options.proto:31:11
 desc_test_options.proto:31:18
+desc_test_options.proto:31:25
 
 
  > extension[12] > name:
-desc_test_options.proto:31:19
-desc_test_options.proto:31:28
+desc_test_options.proto:31:26
+desc_test_options.proto:31:35
 
 
  > extension[12] > number:
-desc_test_options.proto:31:31
-desc_test_options.proto:31:36
+desc_test_options.proto:31:38
+desc_test_options.proto:31:43
+
+
+ > extension:
+desc_test_options.proto:34:1
+desc_test_options.proto:37:2
+
+
+ > extension[13]:
+desc_test_options.proto:35:9
+desc_test_options.proto:35:53
 
 
  > extension[13] > extendee:
@@ -1352,59 +5813,64 @@
 desc_test_options.proto:34:38
 
 
+ > extension[13] > label:
+desc_test_options.proto:35:9
+desc_test_options.proto:35:17
+
+
+ > extension[13] > type_name:
+desc_test_options.proto:35:18
+desc_test_options.proto:35:37
+
+
+ > extension[13] > name:
+desc_test_options.proto:35:38
+desc_test_options.proto:35:44
+
+
+ > extension[13] > number:
+desc_test_options.proto:35:47
+desc_test_options.proto:35:52
+
+
+ > extension[14]:
+desc_test_options.proto:36:9
+desc_test_options.proto:36:51
+
+
  > extension[14] > extendee:
 desc_test_options.proto:34:8
 desc_test_options.proto:34:38
 
 
- > extension[13]:
-desc_test_options.proto:35:2
-desc_test_options.proto:35:46
-
-
- > extension[13] > label:
-desc_test_options.proto:35:2
-desc_test_options.proto:35:10
-
-
- > extension[13] > type:
-desc_test_options.proto:35:11
-desc_test_options.proto:35:30
-
-
- > extension[13] > name:
-desc_test_options.proto:35:31
-desc_test_options.proto:35:37
-
-
- > extension[13] > number:
-desc_test_options.proto:35:40
-desc_test_options.proto:35:45
-
-
- > extension[14]:
-desc_test_options.proto:36:2
-desc_test_options.proto:36:44
-
-
  > extension[14] > label:
-desc_test_options.proto:36:2
-desc_test_options.proto:36:10
+desc_test_options.proto:36:9
+desc_test_options.proto:36:17
 
 
- > extension[14] > type:
-desc_test_options.proto:36:11
-desc_test_options.proto:36:27
+ > extension[14] > type_name:
+desc_test_options.proto:36:18
+desc_test_options.proto:36:34
 
 
  > extension[14] > name:
-desc_test_options.proto:36:28
 desc_test_options.proto:36:35
+desc_test_options.proto:36:42
 
 
  > extension[14] > number:
-desc_test_options.proto:36:38
-desc_test_options.proto:36:43
+desc_test_options.proto:36:45
+desc_test_options.proto:36:50
+
+
+ > extension:
+desc_test_options.proto:39:1
+desc_test_options.proto:42:2
+
+
+ > extension[15]:
+desc_test_options.proto:40:9
+desc_test_options.proto:40:40
 
 
  > extension[15] > extendee:
@@ -1412,64 +5878,54 @@
 desc_test_options.proto:39:37
 
 
+ > extension[15] > label:
+desc_test_options.proto:40:9
+desc_test_options.proto:40:17
+
+
+ > extension[15] > type:
+desc_test_options.proto:40:18
+desc_test_options.proto:40:23
+
+
+ > extension[15] > name:
+desc_test_options.proto:40:24
+desc_test_options.proto:40:31
+
+
+ > extension[15] > number:
+desc_test_options.proto:40:34
+desc_test_options.proto:40:39
+
+
+ > extension[16]:
+desc_test_options.proto:41:9
+desc_test_options.proto:41:42
+
+
  > extension[16] > extendee:
 desc_test_options.proto:39:8
 desc_test_options.proto:39:37
 
 
- > extension[15]:
-desc_test_options.proto:40:2
-desc_test_options.proto:40:33
-
-
- > extension[15] > label:
-desc_test_options.proto:40:2
-desc_test_options.proto:40:10
-
-
- > extension[15] > type:
-desc_test_options.proto:40:11
-desc_test_options.proto:40:16
-
-
- > extension[15] > name:
-desc_test_options.proto:40:17
-desc_test_options.proto:40:24
-
-
- > extension[15] > number:
-desc_test_options.proto:40:27
-desc_test_options.proto:40:32
-
-
- > extension[16]:
-desc_test_options.proto:41:2
-desc_test_options.proto:41:35
-
-
  > extension[16] > label:
-desc_test_options.proto:41:2
-desc_test_options.proto:41:10
-
-
- > extension[16] > type:
-desc_test_options.proto:41:11
+desc_test_options.proto:41:9
 desc_test_options.proto:41:17
 
 
- > extension[16] > name:
+ > extension[16] > type:
 desc_test_options.proto:41:18
-desc_test_options.proto:41:26
+desc_test_options.proto:41:24
+
+
+ > extension[16] > name:
+desc_test_options.proto:41:25
+desc_test_options.proto:41:33
 
 
  > extension[16] > number:
-desc_test_options.proto:41:29
-desc_test_options.proto:41:34
-
-
- > message_type:
-desc_test_options.proto:45:1
-desc_test_options.proto:48:2
+desc_test_options.proto:41:36
+desc_test_options.proto:41:41
 
 
  > message_type[0]:
@@ -1479,69 +5935,60 @@
  Test message used by custom options
 
 
+
  > message_type[0] > name:
 desc_test_options.proto:45:9
 desc_test_options.proto:45:28
 
 
- > message_type[0] > field:
-desc_test_options.proto:46:2
-desc_test_options.proto:47:27
-
-
  > message_type[0] > field[0]:
-desc_test_options.proto:46:2
-desc_test_options.proto:46:25
+desc_test_options.proto:46:9
+desc_test_options.proto:46:32
 
 
  > message_type[0] > field[0] > label:
-desc_test_options.proto:46:2
-desc_test_options.proto:46:10
-
-
- > message_type[0] > field[0] > type:
-desc_test_options.proto:46:11
+desc_test_options.proto:46:9
 desc_test_options.proto:46:17
 
 
- > message_type[0] > field[0] > name:
+ > message_type[0] > field[0] > type:
 desc_test_options.proto:46:18
-desc_test_options.proto:46:20
-
-
- > message_type[0] > field[0] > number:
-desc_test_options.proto:46:23
 desc_test_options.proto:46:24
 
 
+ > message_type[0] > field[0] > name:
+desc_test_options.proto:46:25
+desc_test_options.proto:46:27
+
+
+ > message_type[0] > field[0] > number:
+desc_test_options.proto:46:30
+desc_test_options.proto:46:31
+
+
  > message_type[0] > field[1]:
-desc_test_options.proto:47:2
-desc_test_options.proto:47:27
+desc_test_options.proto:47:9
+desc_test_options.proto:47:34
 
 
  > message_type[0] > field[1] > label:
-desc_test_options.proto:47:2
-desc_test_options.proto:47:10
-
-
- > message_type[0] > field[1] > type:
-desc_test_options.proto:47:11
+desc_test_options.proto:47:9
 desc_test_options.proto:47:17
 
 
- > message_type[0] > field[1] > name:
+ > message_type[0] > field[1] > type:
 desc_test_options.proto:47:18
-desc_test_options.proto:47:22
+desc_test_options.proto:47:24
+
+
+ > message_type[0] > field[1] > name:
+desc_test_options.proto:47:25
+desc_test_options.proto:47:29
 
 
  > message_type[0] > field[1] > number:
-desc_test_options.proto:47:25
-desc_test_options.proto:47:26
-
-
- > enum_type:
-desc_test_options.proto:51:1
-desc_test_options.proto:53:2
+desc_test_options.proto:47:32
+desc_test_options.proto:47:33
 
 
  > enum_type[0]:
@@ -1551,29 +5998,35 @@
  Test enum used by custom options
 
 
+
  > enum_type[0] > name:
 desc_test_options.proto:51:6
 desc_test_options.proto:51:22
 
 
- > enum_type[0] > value:
-desc_test_options.proto:52:2
-desc_test_options.proto:52:12
-
-
  > enum_type[0] > value[0]:
-desc_test_options.proto:52:2
-desc_test_options.proto:52:12
+desc_test_options.proto:52:9
+desc_test_options.proto:52:19
 
 
  > enum_type[0] > value[0] > name:
-desc_test_options.proto:52:2
-desc_test_options.proto:52:7
+desc_test_options.proto:52:9
+desc_test_options.proto:52:14
 
 
  > enum_type[0] > value[0] > number:
-desc_test_options.proto:52:10
-desc_test_options.proto:52:11
+desc_test_options.proto:52:17
+desc_test_options.proto:52:18
+
+
+ > extension:
+desc_test_options.proto:55:1
+desc_test_options.proto:58:2
+
+
+ > extension[17]:
+desc_test_options.proto:56:9
+desc_test_options.proto:56:41
 
 
  > extension[17] > extendee:
@@ -1581,59 +6034,64 @@
 desc_test_options.proto:55:45
 
 
+ > extension[17] > label:
+desc_test_options.proto:56:9
+desc_test_options.proto:56:17
+
+
+ > extension[17] > type:
+desc_test_options.proto:56:18
+desc_test_options.proto:56:24
+
+
+ > extension[17] > name:
+desc_test_options.proto:56:25
+desc_test_options.proto:56:32
+
+
+ > extension[17] > number:
+desc_test_options.proto:56:35
+desc_test_options.proto:56:40
+
+
+ > extension[18]:
+desc_test_options.proto:57:9
+desc_test_options.proto:57:41
+
+
  > extension[18] > extendee:
 desc_test_options.proto:55:8
 desc_test_options.proto:55:45
 
 
- > extension[17]:
-desc_test_options.proto:56:2
-desc_test_options.proto:56:34
-
-
- > extension[17] > label:
-desc_test_options.proto:56:2
-desc_test_options.proto:56:10
-
-
- > extension[17] > type:
-desc_test_options.proto:56:11
-desc_test_options.proto:56:17
-
-
- > extension[17] > name:
-desc_test_options.proto:56:18
-desc_test_options.proto:56:25
-
-
- > extension[17] > number:
-desc_test_options.proto:56:28
-desc_test_options.proto:56:33
-
-
- > extension[18]:
-desc_test_options.proto:57:2
-desc_test_options.proto:57:34
-
-
  > extension[18] > label:
-desc_test_options.proto:57:2
-desc_test_options.proto:57:10
+desc_test_options.proto:57:9
+desc_test_options.proto:57:17
 
 
  > extension[18] > type:
-desc_test_options.proto:57:11
-desc_test_options.proto:57:16
+desc_test_options.proto:57:18
+desc_test_options.proto:57:23
 
 
  > extension[18] > name:
-desc_test_options.proto:57:17
-desc_test_options.proto:57:25
+desc_test_options.proto:57:24
+desc_test_options.proto:57:32
 
 
  > extension[18] > number:
-desc_test_options.proto:57:28
-desc_test_options.proto:57:33
+desc_test_options.proto:57:35
+desc_test_options.proto:57:40
+
+
+ > extension:
+desc_test_options.proto:60:1
+desc_test_options.proto:63:2
+
+
+ > extension[19]:
+desc_test_options.proto:61:9
+desc_test_options.proto:61:41
 
 
  > extension[19] > extendee:
@@ -1641,56 +6099,51 @@
 desc_test_options.proto:60:36
 
 
+ > extension[19] > label:
+desc_test_options.proto:61:9
+desc_test_options.proto:61:17
+
+
+ > extension[19] > type:
+desc_test_options.proto:61:18
+desc_test_options.proto:61:24
+
+
+ > extension[19] > name:
+desc_test_options.proto:61:25
+desc_test_options.proto:61:32
+
+
+ > extension[19] > number:
+desc_test_options.proto:61:35
+desc_test_options.proto:61:40
+
+
+ > extension[20]:
+desc_test_options.proto:62:9
+desc_test_options.proto:62:41
+
+
  > extension[20] > extendee:
 desc_test_options.proto:60:8
 desc_test_options.proto:60:36
 
 
- > extension[19]:
-desc_test_options.proto:61:2
-desc_test_options.proto:61:34
-
-
- > extension[19] > label:
-desc_test_options.proto:61:2
-desc_test_options.proto:61:10
-
-
- > extension[19] > type:
-desc_test_options.proto:61:11
-desc_test_options.proto:61:17
-
-
- > extension[19] > name:
-desc_test_options.proto:61:18
-desc_test_options.proto:61:25
-
-
- > extension[19] > number:
-desc_test_options.proto:61:28
-desc_test_options.proto:61:33
-
-
- > extension[20]:
-desc_test_options.proto:62:2
-desc_test_options.proto:62:34
-
-
  > extension[20] > label:
-desc_test_options.proto:62:2
-desc_test_options.proto:62:10
+desc_test_options.proto:62:9
+desc_test_options.proto:62:17
 
 
  > extension[20] > type:
-desc_test_options.proto:62:11
-desc_test_options.proto:62:16
+desc_test_options.proto:62:18
+desc_test_options.proto:62:23
 
 
  > extension[20] > name:
-desc_test_options.proto:62:17
-desc_test_options.proto:62:25
+desc_test_options.proto:62:24
+desc_test_options.proto:62:32
 
 
  > extension[20] > number:
-desc_test_options.proto:62:28
-desc_test_options.proto:62:33
+desc_test_options.proto:62:35
+desc_test_options.proto:62:40
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoprint/print.go b/vendor/github.com/jhump/protoreflect/desc/protoprint/print.go
index d8f7f22..0363cf0 100644
--- a/vendor/github.com/jhump/protoreflect/desc/protoprint/print.go
+++ b/vendor/github.com/jhump/protoreflect/desc/protoprint/print.go
@@ -94,7 +94,7 @@
 	TrailingCommentsOnSeparateLine bool
 
 	// If true, the printed output will eschew any blank lines, which otherwise
-	// appear between descriptor elements and comment blocks. Note that this if
+	// appear between descriptor elements and comment blocks. Note that if
 	// detached comments are being printed, this will cause them to be merged
 	// into the subsequent leading comments. Similarly, any element trailing
 	// comments will be merged into the subsequent leading comments.
@@ -266,7 +266,7 @@
 	mf := dynamic.NewMessageFactoryWithExtensionRegistry(&er)
 	fdp := dsc.GetFile().AsFileDescriptorProto()
 	sourceInfo := internal.CreateSourceInfoMap(fdp)
-	extendOptionLocations(sourceInfo)
+	extendOptionLocations(sourceInfo, fdp.GetSourceCodeInfo().GetLocation())
 
 	path := findElement(dsc)
 	switch d := dsc.(type) {
@@ -449,6 +449,8 @@
 	})
 	p.newLine(w)
 
+	skip := map[interface{}]bool{}
+
 	elements := elementAddrs{dsc: fd, opts: opts}
 	if fdp.Package != nil {
 		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.File_packageTag, elementIndex: 0, order: -3})
@@ -466,7 +468,13 @@
 	for i := range fd.GetServices() {
 		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.File_servicesTag, elementIndex: i})
 	}
-	for i := range fd.GetExtensions() {
+	exts := p.computeExtensions(sourceInfo, fd.GetExtensions(), []int32{internal.File_extensionsTag})
+	for i, extd := range fd.GetExtensions() {
+		if extd.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP {
+			// we don't emit nested messages for groups since
+			// they get special treatment
+			skip[extd.GetMessageType()] = true
+		}
 		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.File_extensionsTag, elementIndex: i})
 	}
 
@@ -474,69 +482,123 @@
 
 	pkgName := fd.GetPackage()
 
-	var ext *desc.FieldDescriptor
 	for i, el := range elements.addrs {
 		d := elements.at(el)
+
+		// skip[d] will panic if d is a slice (which it could be for []option),
+		// so just ignore it since we don't try to skip options
+		if reflect.TypeOf(d).Kind() != reflect.Slice && skip[d] {
+			// skip this element
+			continue
+		}
+
+		if i > 0 {
+			p.newLine(w)
+		}
+
 		path = []int32{el.elementType, int32(el.elementIndex)}
-		if el.elementType == internal.File_extensionsTag {
-			fld := d.(*desc.FieldDescriptor)
-			if ext == nil || ext.GetOwner() != fld.GetOwner() {
-				// need to open a new extend block
-				if ext != nil {
-					// close preceding extend block
-					fmt.Fprintln(w, "}")
-				}
-				if i > 0 {
-					p.newLine(w)
-				}
 
-				ext = fld
-				fmt.Fprint(w, "extend ")
-				extNameSi := sourceInfo.Get(append(path, internal.Field_extendeeTag))
-				p.printElementString(extNameSi, w, 0, p.qualifyName(pkgName, pkgName, fld.GetOwner().GetFullyQualifiedName()))
-				fmt.Fprintln(w, "{")
-			} else {
-				p.newLine(w)
-			}
-			p.printField(fld, mf, w, sourceInfo, path, pkgName, 1)
-		} else {
-			if ext != nil {
-				// close preceding extend block
-				fmt.Fprintln(w, "}")
-				ext = nil
-			}
-
-			if i > 0 {
-				p.newLine(w)
-			}
-
-			switch d := d.(type) {
-			case pkg:
-				si := sourceInfo.Get(path)
-				p.printElement(false, si, w, 0, func(w *writer) {
-					fmt.Fprintf(w, "package %s;", d)
-				})
-			case imp:
-				si := sourceInfo.Get(path)
-				p.printElement(false, si, w, 0, func(w *writer) {
-					fmt.Fprintf(w, "import %q;", d)
-				})
-			case []option:
-				p.printOptionsLong(d, w, sourceInfo, path, 0)
-			case *desc.MessageDescriptor:
-				p.printMessage(d, mf, w, sourceInfo, path, 0)
-			case *desc.EnumDescriptor:
-				p.printEnum(d, mf, w, sourceInfo, path, 0)
-			case *desc.ServiceDescriptor:
-				p.printService(d, mf, w, sourceInfo, path, 0)
+		switch d := d.(type) {
+		case pkg:
+			si := sourceInfo.Get(path)
+			p.printElement(false, si, w, 0, func(w *writer) {
+				fmt.Fprintf(w, "package %s;", d)
+			})
+		case imp:
+			si := sourceInfo.Get(path)
+			p.printElement(false, si, w, 0, func(w *writer) {
+				fmt.Fprintf(w, "import %q;", d)
+			})
+		case []option:
+			p.printOptionsLong(d, w, sourceInfo, path, 0)
+		case *desc.MessageDescriptor:
+			p.printMessage(d, mf, w, sourceInfo, path, 0)
+		case *desc.EnumDescriptor:
+			p.printEnum(d, mf, w, sourceInfo, path, 0)
+		case *desc.ServiceDescriptor:
+			p.printService(d, mf, w, sourceInfo, path, 0)
+		case *desc.FieldDescriptor:
+			extDecl := exts[d]
+			p.printExtensions(extDecl, exts, elements, i, mf, w, sourceInfo, nil, internal.File_extensionsTag, pkgName, pkgName, 0)
+			// we printed all extensions in the group, so we can skip the others
+			for _, fld := range extDecl.fields {
+				skip[fld] = true
 			}
 		}
 	}
+}
 
-	if ext != nil {
-		// close trailing extend block
-		fmt.Fprintln(w, "}")
+func findExtSi(fieldSi *descriptor.SourceCodeInfo_Location, extSis []*descriptor.SourceCodeInfo_Location) *descriptor.SourceCodeInfo_Location {
+	if len(fieldSi.GetSpan()) == 0 {
+		return nil
 	}
+	for _, extSi := range extSis {
+		if isSpanWithin(fieldSi.Span, extSi.Span) {
+			return extSi
+		}
+	}
+	return nil
+}
+
+func isSpanWithin(span, enclosing []int32) bool {
+	start := enclosing[0]
+	var end int32
+	if len(enclosing) == 3 {
+		end = enclosing[0]
+	} else {
+		end = enclosing[2]
+	}
+	if span[0] < start || span[0] > end {
+		return false
+	}
+
+	if span[0] == start {
+		return span[1] >= enclosing[1]
+	} else if span[0] == end {
+		return span[1] <= enclosing[len(enclosing)-1]
+	}
+	return true
+}
+
+type extensionDecl struct {
+	extendee   string
+	sourceInfo *descriptor.SourceCodeInfo_Location
+	fields     []*desc.FieldDescriptor
+}
+
+type extensions map[*desc.FieldDescriptor]*extensionDecl
+
+func (p *Printer) computeExtensions(sourceInfo internal.SourceInfoMap, exts []*desc.FieldDescriptor, path []int32) extensions {
+	extsMap := map[string]map[*descriptor.SourceCodeInfo_Location]*extensionDecl{}
+	extSis := sourceInfo.GetAll(path)
+	for _, extd := range exts {
+		name := extd.GetOwner().GetFullyQualifiedName()
+		extSi := findExtSi(extd.GetSourceInfo(), extSis)
+		extsBySi := extsMap[name]
+		if extsBySi == nil {
+			extsBySi = map[*descriptor.SourceCodeInfo_Location]*extensionDecl{}
+			extsMap[name] = extsBySi
+		}
+		extDecl := extsBySi[extSi]
+		if extDecl == nil {
+			extDecl = &extensionDecl{
+				sourceInfo: extSi,
+				extendee:   name,
+			}
+			extsBySi[extSi] = extDecl
+		}
+		extDecl.fields = append(extDecl.fields, extd)
+	}
+
+	ret := extensions{}
+	for _, extsBySi := range extsMap {
+		for _, extDecl := range extsBySi {
+			for _, extd := range extDecl.fields {
+				ret[extd] = extDecl
+			}
+		}
+	}
+	return ret
 }
 
 func (p *Printer) sort(elements elementAddrs, sourceInfo internal.SourceInfoMap, path []int32) {
@@ -680,7 +742,13 @@
 	for i := range md.GetNestedEnumTypes() {
 		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Message_enumsTag, elementIndex: i})
 	}
-	for i := range md.GetNestedExtensions() {
+	exts := p.computeExtensions(sourceInfo, md.GetNestedExtensions(), append(path, internal.Message_extensionsTag))
+	for i, extd := range md.GetNestedExtensions() {
+		if extd.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP {
+			// we don't emit nested messages for groups since
+			// they get special treatment
+			skip[extd.GetMessageType()] = true
+		}
 		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Message_extensionsTag, elementIndex: i})
 	}
 
@@ -689,9 +757,9 @@
 	pkg := md.GetFile().GetPackage()
 	scope := md.GetFullyQualifiedName()
 
-	var ext *desc.FieldDescriptor
 	for i, el := range elements.addrs {
 		d := elements.at(el)
+