Browse Source
* [chore]: Bump github.com/prometheus/client_golang from 1.18.0 to 1.19.1 Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.18.0 to 1.19.1. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.18.0...v1.19.1) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * [chore]: Bump github.com/KimMachineGun/automemlimit from 0.6.0 to 0.6.1 Bumps [github.com/KimMachineGun/automemlimit](https://github.com/KimMachineGun/automemlimit) from 0.6.0 to 0.6.1. - [Release notes](https://github.com/KimMachineGun/automemlimit/releases) - [Commits](https://github.com/KimMachineGun/automemlimit/compare/v0.6.0...v0.6.1) --- updated-dependencies: - dependency-name: github.com/KimMachineGun/automemlimit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * [chore]: Bump github.com/tdewolff/minify/v2 from 2.20.20 to 2.20.24 Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.20.20 to 2.20.24. - [Release notes](https://github.com/tdewolff/minify/releases) - [Commits](https://github.com/tdewolff/minify/compare/v2.20.20...v2.20.24) --- updated-dependencies: - dependency-name: github.com/tdewolff/minify/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * [chore]: Bump github.com/go-swagger/go-swagger Bumps [github.com/go-swagger/go-swagger](https://github.com/go-swagger/go-swagger) from 0.30.6-0.20240418033037-c46c303aaa02 to 0.31.0. - [Release notes](https://github.com/go-swagger/go-swagger/releases) - [Changelog](https://github.com/go-swagger/go-swagger/blob/master/.goreleaser.yml) - [Commits](https://github.com/go-swagger/go-swagger/commits/v0.31.0) --- updated-dependencies: - dependency-name: github.com/go-swagger/go-swagger dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * [chore]: Bump github.com/gin-gonic/gin from 1.9.1 to 1.10.0 Bumps [github.com/gin-gonic/gin](https://github.com/gin-gonic/gin) from 1.9.1 to 1.10.0. - [Release notes](https://github.com/gin-gonic/gin/releases) - [Changelog](https://github.com/gin-gonic/gin/blob/master/CHANGELOG.md) - [Commits](https://github.com/gin-gonic/gin/compare/v1.9.1...v1.10.0) --- updated-dependencies: - dependency-name: github.com/gin-gonic/gin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>pull/2923/head
85 changed files with 19843 additions and 13217 deletions
@ -0,0 +1,13 @@
|
||||
coverage: |
||||
require_ci_to_pass: true |
||||
|
||||
status: |
||||
project: |
||||
default: |
||||
target: 99% |
||||
threshold: 99% |
||||
|
||||
patch: |
||||
default: |
||||
target: 99% |
||||
threshold: 95% |
||||
@ -1,201 +0,0 @@
|
||||
Apache License |
||||
Version 2.0, January 2004 |
||||
http://www.apache.org/licenses/ |
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||
|
||||
1. Definitions. |
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, |
||||
and distribution as defined by Sections 1 through 9 of this document. |
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by |
||||
the copyright owner that is granting the License. |
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all |
||||
other entities that control, are controlled by, or are under common |
||||
control with that entity. For the purposes of this definition, |
||||
"control" means (i) the power, direct or indirect, to cause the |
||||
direction or management of such entity, whether by contract or |
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||
outstanding shares, or (iii) beneficial ownership of such entity. |
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity |
||||
exercising permissions granted by this License. |
||||
|
||||
"Source" form shall mean the preferred form for making modifications, |
||||
including but not limited to software source code, documentation |
||||
source, and configuration files. |
||||
|
||||
"Object" form shall mean any form resulting from mechanical |
||||
transformation or translation of a Source form, including but |
||||
not limited to compiled object code, generated documentation, |
||||
and conversions to other media types. |
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or |
||||
Object form, made available under the License, as indicated by a |
||||
copyright notice that is included in or attached to the work |
||||
(an example is provided in the Appendix below). |
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object |
||||
form, that is based on (or derived from) the Work and for which the |
||||
editorial revisions, annotations, elaborations, or other modifications |
||||
represent, as a whole, an original work of authorship. For the purposes |
||||
of this License, Derivative Works shall not include works that remain |
||||
separable from, or merely link (or bind by name) to the interfaces of, |
||||
the Work and Derivative Works thereof. |
||||
|
||||
"Contribution" shall mean any work of authorship, including |
||||
the original version of the Work and any modifications or additions |
||||
to that Work or Derivative Works thereof, that is intentionally |
||||
submitted to Licensor for inclusion in the Work by the copyright owner |
||||
or by an individual or Legal Entity authorized to submit on behalf of |
||||
the copyright owner. For the purposes of this definition, "submitted" |
||||
means any form of electronic, verbal, or written communication sent |
||||
to the Licensor or its representatives, including but not limited to |
||||
communication on electronic mailing lists, source code control systems, |
||||
and issue tracking systems that are managed by, or on behalf of, the |
||||
Licensor for the purpose of discussing and improving the Work, but |
||||
excluding communication that is conspicuously marked or otherwise |
||||
designated in writing by the copyright owner as "Not a Contribution." |
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||
on behalf of whom a Contribution has been received by Licensor and |
||||
subsequently incorporated within the Work. |
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
copyright license to reproduce, prepare Derivative Works of, |
||||
publicly display, publicly perform, sublicense, and distribute the |
||||
Work and such Derivative Works in Source or Object form. |
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of |
||||
this License, each Contributor hereby grants to You a perpetual, |
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
(except as stated in this section) patent license to make, have made, |
||||
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||
where such license applies only to those patent claims licensable |
||||
by such Contributor that are necessarily infringed by their |
||||
Contribution(s) alone or by combination of their Contribution(s) |
||||
with the Work to which such Contribution(s) was submitted. If You |
||||
institute patent litigation against any entity (including a |
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||
or a Contribution incorporated within the Work constitutes direct |
||||
or contributory patent infringement, then any patent licenses |
||||
granted to You under this License for that Work shall terminate |
||||
as of the date such litigation is filed. |
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the |
||||
Work or Derivative Works thereof in any medium, with or without |
||||
modifications, and in Source or Object form, provided that You |
||||
meet the following conditions: |
||||
|
||||
(a) You must give any other recipients of the Work or |
||||
Derivative Works a copy of this License; and |
||||
|
||||
(b) You must cause any modified files to carry prominent notices |
||||
stating that You changed the files; and |
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works |
||||
that You distribute, all copyright, patent, trademark, and |
||||
attribution notices from the Source form of the Work, |
||||
excluding those notices that do not pertain to any part of |
||||
the Derivative Works; and |
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its |
||||
distribution, then any Derivative Works that You distribute must |
||||
include a readable copy of the attribution notices contained |
||||
within such NOTICE file, excluding those notices that do not |
||||
pertain to any part of the Derivative Works, in at least one |
||||
of the following places: within a NOTICE text file distributed |
||||
as part of the Derivative Works; within the Source form or |
||||
documentation, if provided along with the Derivative Works; or, |
||||
within a display generated by the Derivative Works, if and |
||||
wherever such third-party notices normally appear. The contents |
||||
of the NOTICE file are for informational purposes only and |
||||
do not modify the License. You may add Your own attribution |
||||
notices within Derivative Works that You distribute, alongside |
||||
or as an addendum to the NOTICE text from the Work, provided |
||||
that such additional attribution notices cannot be construed |
||||
as modifying the License. |
||||
|
||||
You may add Your own copyright statement to Your modifications and |
||||
may provide additional or different license terms and conditions |
||||
for use, reproduction, or distribution of Your modifications, or |
||||
for any such Derivative Works as a whole, provided Your use, |
||||
reproduction, and distribution of the Work otherwise complies with |
||||
the conditions stated in this License. |
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||
any Contribution intentionally submitted for inclusion in the Work |
||||
by You to the Licensor shall be under the terms and conditions of |
||||
this License, without any additional terms or conditions. |
||||
Notwithstanding the above, nothing herein shall supersede or modify |
||||
the terms of any separate license agreement you may have executed |
||||
with Licensor regarding such Contributions. |
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade |
||||
names, trademarks, service marks, or product names of the Licensor, |
||||
except as required for reasonable and customary use in describing the |
||||
origin of the Work and reproducing the content of the NOTICE file. |
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or |
||||
agreed to in writing, Licensor provides the Work (and each |
||||
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||
implied, including, without limitation, any warranties or conditions |
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||
appropriateness of using or redistributing the Work and assume any |
||||
risks associated with Your exercise of permissions under this License. |
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, |
||||
whether in tort (including negligence), contract, or otherwise, |
||||
unless required by applicable law (such as deliberate and grossly |
||||
negligent acts) or agreed to in writing, shall any Contributor be |
||||
liable to You for damages, including any direct, indirect, special, |
||||
incidental, or consequential damages of any character arising as a |
||||
result of this License or out of the use or inability to use the |
||||
Work (including but not limited to damages for loss of goodwill, |
||||
work stoppage, computer failure or malfunction, or any and all |
||||
other commercial damages or losses), even if such Contributor |
||||
has been advised of the possibility of such damages. |
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing |
||||
the Work or Derivative Works thereof, You may choose to offer, |
||||
and charge a fee for, acceptance of support, warranty, indemnity, |
||||
or other liability obligations and/or rights consistent with this |
||||
License. However, in accepting such obligations, You may act only |
||||
on Your own behalf and on Your sole responsibility, not on behalf |
||||
of any other Contributor, and only if You agree to indemnify, |
||||
defend, and hold each Contributor harmless for any liability |
||||
incurred by, or claims asserted against, such Contributor by reason |
||||
of your accepting any such warranty or additional liability. |
||||
|
||||
END OF TERMS AND CONDITIONS |
||||
|
||||
APPENDIX: How to apply the Apache License to your work. |
||||
|
||||
To apply the Apache License to your work, attach the following |
||||
boilerplate notice, with the fields enclosed by brackets "{}" |
||||
replaced with your own identifying information. (Don't include |
||||
the brackets!) The text should be enclosed in the appropriate |
||||
comment syntax for the file format. We also recommend that a |
||||
file or class name and description of purpose be included on the |
||||
same "printed page" as the copyright notice for easier |
||||
identification within third-party archives. |
||||
|
||||
Copyright {yyyy} {name of copyright owner} |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
||||
@ -1 +0,0 @@
|
||||
Copyright 2012 Matt T. Proud (matt.proud@gmail.com) |
||||
@ -1 +0,0 @@
|
||||
cover.dat |
||||
@ -1,7 +0,0 @@
|
||||
all: |
||||
|
||||
cover: |
||||
go test -cover -v -coverprofile=cover.dat ./...
|
||||
go tool cover -func cover.dat
|
||||
|
||||
.PHONY: cover |
||||
@ -1,81 +0,0 @@
|
||||
// Copyright 2013 Matt T. Proud
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package pbutil |
||||
|
||||
import ( |
||||
"encoding/binary" |
||||
"errors" |
||||
"io" |
||||
|
||||
"google.golang.org/protobuf/proto" |
||||
) |
||||
|
||||
// TODO: Give error package name prefix in next minor release.
|
||||
var errInvalidVarint = errors.New("invalid varint32 encountered") |
||||
|
||||
// ReadDelimited decodes a message from the provided length-delimited stream,
|
||||
// where the length is encoded as 32-bit varint prefix to the message body.
|
||||
// It returns the total number of bytes read and any applicable error. This is
|
||||
// roughly equivalent to the companion Java API's
|
||||
// MessageLite#parseDelimitedFrom. As per the reader contract, this function
|
||||
// calls r.Read repeatedly as required until exactly one message including its
|
||||
// prefix is read and decoded (or an error has occurred). The function never
|
||||
// reads more bytes from the stream than required. The function never returns
|
||||
// an error if a message has been read and decoded correctly, even if the end
|
||||
// of the stream has been reached in doing so. In that case, any subsequent
|
||||
// calls return (0, io.EOF).
|
||||
func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) { |
||||
// TODO: Consider allowing the caller to specify a decode buffer in the
|
||||
// next major version.
|
||||
|
||||
// TODO: Consider using error wrapping to annotate error state in pass-
|
||||
// through cases in the next minor version.
|
||||
|
||||
// Per AbstractParser#parsePartialDelimitedFrom with
|
||||
// CodedInputStream#readRawVarint32.
|
||||
var headerBuf [binary.MaxVarintLen32]byte |
||||
var bytesRead, varIntBytes int |
||||
var messageLength uint64 |
||||
for varIntBytes == 0 { // i.e. no varint has been decoded yet.
|
||||
if bytesRead >= len(headerBuf) { |
||||
return bytesRead, errInvalidVarint |
||||
} |
||||
// We have to read byte by byte here to avoid reading more bytes
|
||||
// than required. Each read byte is appended to what we have
|
||||
// read before.
|
||||
newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1]) |
||||
if newBytesRead == 0 { |
||||
if err != nil { |
||||
return bytesRead, err |
||||
} |
||||
// A Reader should not return (0, nil); but if it does, it should
|
||||
// be treated as no-op according to the Reader contract.
|
||||
continue |
||||
} |
||||
bytesRead += newBytesRead |
||||
// Now present everything read so far to the varint decoder and
|
||||
// see if a varint can be decoded already.
|
||||
messageLength, varIntBytes = binary.Uvarint(headerBuf[:bytesRead]) |
||||
} |
||||
|
||||
messageBuf := make([]byte, messageLength) |
||||
newBytesRead, err := io.ReadFull(r, messageBuf) |
||||
bytesRead += newBytesRead |
||||
if err != nil { |
||||
return bytesRead, err |
||||
} |
||||
|
||||
return bytesRead, proto.Unmarshal(messageBuf, m) |
||||
} |
||||
@ -1,16 +0,0 @@
|
||||
// Copyright 2013 Matt T. Proud
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package pbutil provides record length-delimited Protocol Buffer streaming.
|
||||
package pbutil |
||||
@ -1,49 +0,0 @@
|
||||
// Copyright 2013 Matt T. Proud
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package pbutil |
||||
|
||||
import ( |
||||
"encoding/binary" |
||||
"io" |
||||
|
||||
"google.golang.org/protobuf/proto" |
||||
) |
||||
|
||||
// WriteDelimited encodes and dumps a message to the provided writer prefixed
|
||||
// with a 32-bit varint indicating the length of the encoded message, producing
|
||||
// a length-delimited record stream, which can be used to chain together
|
||||
// encoded messages of the same type together in a file. It returns the total
|
||||
// number of bytes written and any applicable error. This is roughly
|
||||
// equivalent to the companion Java API's MessageLite#writeDelimitedTo.
|
||||
func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) { |
||||
// TODO: Consider allowing the caller to specify an encode buffer in the
|
||||
// next major version.
|
||||
|
||||
buffer, err := proto.Marshal(m) |
||||
if err != nil { |
||||
return 0, err |
||||
} |
||||
|
||||
var buf [binary.MaxVarintLen32]byte |
||||
encodedLength := binary.PutUvarint(buf[:], uint64(len(buffer))) |
||||
|
||||
sync, err := w.Write(buf[:encodedLength]) |
||||
if err != nil { |
||||
return sync, err |
||||
} |
||||
|
||||
n, err = w.Write(buffer) |
||||
return n + sync, err |
||||
} |
||||
@ -0,0 +1,28 @@
|
||||
// Copyright 2023 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package model |
||||
|
||||
// MetricType represents metric type values.
|
||||
type MetricType string |
||||
|
||||
const ( |
||||
MetricTypeCounter = MetricType("counter") |
||||
MetricTypeGauge = MetricType("gauge") |
||||
MetricTypeHistogram = MetricType("histogram") |
||||
MetricTypeGaugeHistogram = MetricType("gaugehistogram") |
||||
MetricTypeSummary = MetricType("summary") |
||||
MetricTypeInfo = MetricType("info") |
||||
MetricTypeStateset = MetricType("stateset") |
||||
MetricTypeUnknown = MetricType("unknown") |
||||
) |
||||
@ -0,0 +1,483 @@
|
||||
package parse |
||||
|
||||
import ( |
||||
"encoding/binary" |
||||
"fmt" |
||||
"io" |
||||
"math" |
||||
"os" |
||||
) |
||||
|
||||
// BinaryReader is a binary big endian file format reader.
|
||||
type BinaryReader struct { |
||||
Endianness binary.ByteOrder |
||||
buf []byte |
||||
pos uint32 |
||||
eof bool |
||||
} |
||||
|
||||
// NewBinaryReader returns a big endian binary file format reader.
|
||||
func NewBinaryReader(buf []byte) *BinaryReader { |
||||
if math.MaxUint32 < uint(len(buf)) { |
||||
return &BinaryReader{binary.BigEndian, nil, 0, true} |
||||
} |
||||
return &BinaryReader{binary.BigEndian, buf, 0, false} |
||||
} |
||||
|
||||
// NewBinaryReaderLE returns a little endian binary file format reader.
|
||||
func NewBinaryReaderLE(buf []byte) *BinaryReader { |
||||
r := NewBinaryReader(buf) |
||||
r.Endianness = binary.LittleEndian |
||||
return r |
||||
} |
||||
|
||||
// Seek set the reader position in the buffer.
|
||||
func (r *BinaryReader) Seek(pos uint32) error { |
||||
if uint32(len(r.buf)) < pos { |
||||
r.eof = true |
||||
return io.EOF |
||||
} |
||||
r.pos = pos |
||||
r.eof = false |
||||
return nil |
||||
} |
||||
|
||||
// Pos returns the reader's position.
|
||||
func (r *BinaryReader) Pos() uint32 { |
||||
return r.pos |
||||
} |
||||
|
||||
// Len returns the remaining length of the buffer.
|
||||
func (r *BinaryReader) Len() uint32 { |
||||
return uint32(len(r.buf)) - r.pos |
||||
} |
||||
|
||||
// EOF returns true if we reached the end-of-file.
|
||||
func (r *BinaryReader) EOF() bool { |
||||
return r.eof |
||||
} |
||||
|
||||
// Read complies with io.Reader.
|
||||
func (r *BinaryReader) Read(b []byte) (int, error) { |
||||
n := copy(b, r.buf[r.pos:]) |
||||
r.pos += uint32(n) |
||||
if r.pos == uint32(len(r.buf)) { |
||||
r.eof = true |
||||
return n, io.EOF |
||||
} |
||||
return n, nil |
||||
} |
||||
|
||||
// ReadBytes reads n bytes.
|
||||
func (r *BinaryReader) ReadBytes(n uint32) []byte { |
||||
if r.eof || uint32(len(r.buf))-r.pos < n { |
||||
r.eof = true |
||||
return nil |
||||
} |
||||
buf := r.buf[r.pos : r.pos+n : r.pos+n] |
||||
r.pos += n |
||||
return buf |
||||
} |
||||
|
||||
// ReadString reads a string of length n.
|
||||
func (r *BinaryReader) ReadString(n uint32) string { |
||||
return string(r.ReadBytes(n)) |
||||
} |
||||
|
||||
// ReadByte reads a single byte.
|
||||
func (r *BinaryReader) ReadByte() byte { |
||||
b := r.ReadBytes(1) |
||||
if b == nil { |
||||
return 0 |
||||
} |
||||
return b[0] |
||||
} |
||||
|
||||
// ReadUint8 reads a uint8.
|
||||
func (r *BinaryReader) ReadUint8() uint8 { |
||||
return r.ReadByte() |
||||
} |
||||
|
||||
// ReadUint16 reads a uint16.
|
||||
func (r *BinaryReader) ReadUint16() uint16 { |
||||
b := r.ReadBytes(2) |
||||
if b == nil { |
||||
return 0 |
||||
} |
||||
return r.Endianness.Uint16(b) |
||||
} |
||||
|
||||
// ReadUint32 reads a uint32.
|
||||
func (r *BinaryReader) ReadUint32() uint32 { |
||||
b := r.ReadBytes(4) |
||||
if b == nil { |
||||
return 0 |
||||
} |
||||
return r.Endianness.Uint32(b) |
||||
} |
||||
|
||||
// ReadUint64 reads a uint64.
|
||||
func (r *BinaryReader) ReadUint64() uint64 { |
||||
b := r.ReadBytes(8) |
||||
if b == nil { |
||||
return 0 |
||||
} |
||||
return r.Endianness.Uint64(b) |
||||
} |
||||
|
||||
// ReadInt8 reads a int8.
|
||||
func (r *BinaryReader) ReadInt8() int8 { |
||||
return int8(r.ReadByte()) |
||||
} |
||||
|
||||
// ReadInt16 reads a int16.
|
||||
func (r *BinaryReader) ReadInt16() int16 { |
||||
return int16(r.ReadUint16()) |
||||
} |
||||
|
||||
// ReadInt32 reads a int32.
|
||||
func (r *BinaryReader) ReadInt32() int32 { |
||||
return int32(r.ReadUint32()) |
||||
} |
||||
|
||||
// ReadInt64 reads a int64.
|
||||
func (r *BinaryReader) ReadInt64() int64 { |
||||
return int64(r.ReadUint64()) |
||||
} |
||||
|
||||
type BinaryFileReader struct { |
||||
f *os.File |
||||
size uint64 |
||||
offset uint64 |
||||
|
||||
Endianness binary.ByteOrder |
||||
buf []byte |
||||
pos int |
||||
} |
||||
|
||||
func NewBinaryFileReader(f *os.File, chunk int) (*BinaryFileReader, error) { |
||||
var buf []byte |
||||
var size uint64 |
||||
if chunk == 0 { |
||||
var err error |
||||
if buf, err = io.ReadAll(f); err != nil { |
||||
return nil, err |
||||
} |
||||
} else { |
||||
buf = make([]byte, 0, chunk) |
||||
} |
||||
if info, err := f.Stat(); err != nil { |
||||
return nil, err |
||||
} else { |
||||
size = uint64(info.Size()) |
||||
} |
||||
return &BinaryFileReader{ |
||||
f: f, |
||||
size: size, |
||||
Endianness: binary.BigEndian, |
||||
buf: buf, |
||||
}, nil |
||||
} |
||||
|
||||
func (r *BinaryFileReader) buffer(pos, length uint64) error { |
||||
if pos < r.offset || r.offset+uint64(len(r.buf)) < pos+length { |
||||
if math.MaxInt64 < pos { |
||||
return fmt.Errorf("seek position too large") |
||||
} else if _, err := r.f.Seek(int64(pos), 0); err != nil { |
||||
return err |
||||
} else if n, err := r.f.Read(r.buf[:cap(r.buf)]); err != nil { |
||||
return err |
||||
} else { |
||||
r.offset = pos |
||||
r.buf = r.buf[:n] |
||||
r.pos = 0 |
||||
} |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
// Seek set the reader position in the buffer.
|
||||
func (r *BinaryFileReader) Seek(pos uint64) error { |
||||
if r.size <= pos { |
||||
return io.EOF |
||||
} else if err := r.buffer(pos, 0); err != nil { |
||||
return err |
||||
} |
||||
r.pos = int(pos - r.offset) |
||||
return nil |
||||
} |
||||
|
||||
// Pos returns the reader's position.
|
||||
func (r *BinaryFileReader) Pos() uint64 { |
||||
return r.offset + uint64(r.pos) |
||||
} |
||||
|
||||
// Len returns the remaining length of the buffer.
|
||||
func (r *BinaryFileReader) Len() uint64 { |
||||
return r.size - r.Pos() |
||||
} |
||||
|
||||
// Offset returns the offset of the buffer.
|
||||
func (r *BinaryFileReader) Offset() uint64 { |
||||
return r.offset |
||||
} |
||||
|
||||
// BufferLen returns the length of the buffer.
|
||||
func (r *BinaryFileReader) BufferLen() int { |
||||
return len(r.buf) |
||||
} |
||||
|
||||
// Read complies with io.Reader.
|
||||
func (r *BinaryFileReader) Read(b []byte) (int, error) { |
||||
if len(b) <= cap(r.buf) { |
||||
if err := r.buffer(r.offset+uint64(r.pos), uint64(len(b))); err != nil { |
||||
return 0, err |
||||
} |
||||
n := copy(b, r.buf[r.pos:]) |
||||
r.pos += n |
||||
return n, nil |
||||
} |
||||
|
||||
// read directly from file
|
||||
if _, err := r.f.Seek(int64(r.offset)+int64(r.pos), 0); err != nil { |
||||
return 0, err |
||||
} |
||||
n, err := r.f.Read(b) |
||||
r.offset += uint64(r.pos + n) |
||||
r.pos = 0 |
||||
r.buf = r.buf[:0] |
||||
return n, err |
||||
} |
||||
|
||||
// ReadBytes reads n bytes.
|
||||
func (r *BinaryFileReader) ReadBytes(n int) []byte { |
||||
if n < len(r.buf)-r.pos { |
||||
b := r.buf[r.pos : r.pos+n] |
||||
r.pos += n |
||||
return b |
||||
} |
||||
|
||||
b := make([]byte, n) |
||||
if _, err := r.Read(b); err != nil { |
||||
return nil |
||||
} |
||||
return b |
||||
} |
||||
|
||||
// ReadString reads a string of length n.
|
||||
func (r *BinaryFileReader) ReadString(n int) string { |
||||
return string(r.ReadBytes(n)) |
||||
} |
||||
|
||||
// ReadByte reads a single byte.
|
||||
func (r *BinaryFileReader) ReadByte() byte { |
||||
b := r.ReadBytes(1) |
||||
if b == nil { |
||||
return 0 |
||||
} |
||||
return b[0] |
||||
} |
||||
|
||||
// ReadUint8 reads a uint8.
|
||||
func (r *BinaryFileReader) ReadUint8() uint8 { |
||||
return r.ReadByte() |
||||
} |
||||
|
||||
// ReadUint16 reads a uint16.
|
||||
func (r *BinaryFileReader) ReadUint16() uint16 { |
||||
b := r.ReadBytes(2) |
||||
if b == nil { |
||||
return 0 |
||||
} |
||||
return r.Endianness.Uint16(b) |
||||
} |
||||
|
||||
// ReadUint32 reads a uint32.
|
||||
func (r *BinaryFileReader) ReadUint32() uint32 { |
||||
b := r.ReadBytes(4) |
||||
if b == nil { |
||||
return 0 |
||||
} |
||||
return r.Endianness.Uint32(b) |
||||
} |
||||
|
||||
// ReadUint64 reads a uint64.
|
||||
func (r *BinaryFileReader) ReadUint64() uint64 { |
||||
b := r.ReadBytes(8) |
||||
if b == nil { |
||||
return 0 |
||||
} |
||||
return r.Endianness.Uint64(b) |
||||
} |
||||
|
||||
// ReadInt8 reads a int8.
|
||||
func (r *BinaryFileReader) ReadInt8() int8 { |
||||
return int8(r.ReadByte()) |
||||
} |
||||
|
||||
// ReadInt16 reads a int16.
|
||||
func (r *BinaryFileReader) ReadInt16() int16 { |
||||
return int16(r.ReadUint16()) |
||||
} |
||||
|
||||
// ReadInt32 reads a int32.
|
||||
func (r *BinaryFileReader) ReadInt32() int32 { |
||||
return int32(r.ReadUint32()) |
||||
} |
||||
|
||||
// ReadInt64 reads a int64.
|
||||
func (r *BinaryFileReader) ReadInt64() int64 { |
||||
return int64(r.ReadUint64()) |
||||
} |
||||
|
||||
// BinaryWriter is a big endian binary file format writer.
|
||||
type BinaryWriter struct { |
||||
buf []byte |
||||
} |
||||
|
||||
// NewBinaryWriter returns a big endian binary file format writer.
|
||||
func NewBinaryWriter(buf []byte) *BinaryWriter { |
||||
return &BinaryWriter{buf} |
||||
} |
||||
|
||||
// Len returns the buffer's length in bytes.
|
||||
func (w *BinaryWriter) Len() uint32 { |
||||
return uint32(len(w.buf)) |
||||
} |
||||
|
||||
// Bytes returns the buffer's bytes.
|
||||
func (w *BinaryWriter) Bytes() []byte { |
||||
return w.buf |
||||
} |
||||
|
||||
// Write complies with io.Writer.
|
||||
func (w *BinaryWriter) Write(b []byte) (int, error) { |
||||
w.buf = append(w.buf, b...) |
||||
return len(b), nil |
||||
} |
||||
|
||||
// WriteBytes writes the given bytes to the buffer.
|
||||
func (w *BinaryWriter) WriteBytes(v []byte) { |
||||
w.buf = append(w.buf, v...) |
||||
} |
||||
|
||||
// WriteString writes the given string to the buffer.
|
||||
func (w *BinaryWriter) WriteString(v string) { |
||||
w.WriteBytes([]byte(v)) |
||||
} |
||||
|
||||
// WriteByte writes the given byte to the buffer.
|
||||
func (w *BinaryWriter) WriteByte(v byte) { |
||||
w.WriteBytes([]byte{v}) |
||||
} |
||||
|
||||
// WriteUint8 writes the given uint8 to the buffer.
|
||||
func (w *BinaryWriter) WriteUint8(v uint8) { |
||||
w.WriteByte(v) |
||||
} |
||||
|
||||
// WriteUint16 writes the given uint16 to the buffer.
|
||||
func (w *BinaryWriter) WriteUint16(v uint16) { |
||||
pos := len(w.buf) |
||||
w.buf = append(w.buf, make([]byte, 2)...) |
||||
binary.BigEndian.PutUint16(w.buf[pos:], v) |
||||
} |
||||
|
||||
// WriteUint32 writes the given uint32 to the buffer.
|
||||
func (w *BinaryWriter) WriteUint32(v uint32) { |
||||
pos := len(w.buf) |
||||
w.buf = append(w.buf, make([]byte, 4)...) |
||||
binary.BigEndian.PutUint32(w.buf[pos:], v) |
||||
} |
||||
|
||||
// WriteUint64 writes the given uint64 to the buffer.
|
||||
func (w *BinaryWriter) WriteUint64(v uint64) { |
||||
pos := len(w.buf) |
||||
w.buf = append(w.buf, make([]byte, 8)...) |
||||
binary.BigEndian.PutUint64(w.buf[pos:], v) |
||||
} |
||||
|
||||
// WriteInt8 writes the given int8 to the buffer.
|
||||
func (w *BinaryWriter) WriteInt8(v int8) { |
||||
w.WriteUint8(uint8(v)) |
||||
} |
||||
|
||||
// WriteInt16 writes the given int16 to the buffer.
|
||||
func (w *BinaryWriter) WriteInt16(v int16) { |
||||
w.WriteUint16(uint16(v)) |
||||
} |
||||
|
||||
// WriteInt32 writes the given int32 to the buffer.
|
||||
func (w *BinaryWriter) WriteInt32(v int32) { |
||||
w.WriteUint32(uint32(v)) |
||||
} |
||||
|
||||
// WriteInt64 writes the given int64 to the buffer.
|
||||
func (w *BinaryWriter) WriteInt64(v int64) { |
||||
w.WriteUint64(uint64(v)) |
||||
} |
||||
|
||||
// BitmapReader is a binary bitmap reader.
|
||||
type BitmapReader struct { |
||||
buf []byte |
||||
pos uint32 // TODO: to uint64
|
||||
eof bool |
||||
} |
||||
|
||||
// NewBitmapReader returns a binary bitmap reader.
|
||||
func NewBitmapReader(buf []byte) *BitmapReader { |
||||
return &BitmapReader{buf, 0, false} |
||||
} |
||||
|
||||
// Pos returns the current bit position.
|
||||
func (r *BitmapReader) Pos() uint32 { |
||||
return r.pos |
||||
} |
||||
|
||||
// EOF returns if we reached the buffer's end-of-file.
|
||||
func (r *BitmapReader) EOF() bool { |
||||
return r.eof |
||||
} |
||||
|
||||
// Read reads the next bit.
|
||||
func (r *BitmapReader) Read() bool { |
||||
if r.eof || uint32(len(r.buf)) <= (r.pos+1)/8 { |
||||
r.eof = true |
||||
return false |
||||
} |
||||
bit := r.buf[r.pos>>3]&(0x80>>(r.pos&7)) != 0 |
||||
r.pos += 1 |
||||
return bit |
||||
} |
||||
|
||||
// BitmapWriter is a binary bitmap writer.
|
||||
type BitmapWriter struct { |
||||
buf []byte |
||||
pos uint32 |
||||
} |
||||
|
||||
// NewBitmapWriter returns a binary bitmap writer.
|
||||
func NewBitmapWriter(buf []byte) *BitmapWriter { |
||||
return &BitmapWriter{buf, 0} |
||||
} |
||||
|
||||
// Len returns the buffer's length in bytes.
|
||||
func (w *BitmapWriter) Len() uint32 { |
||||
return uint32(len(w.buf)) |
||||
} |
||||
|
||||
// Bytes returns the buffer's bytes.
|
||||
func (w *BitmapWriter) Bytes() []byte { |
||||
return w.buf |
||||
} |
||||
|
||||
// Write writes the next bit.
|
||||
func (w *BitmapWriter) Write(bit bool) { |
||||
if uint32(len(w.buf)) <= (w.pos+1)/8 { |
||||
w.buf = append(w.buf, 0) |
||||
} |
||||
if bit { |
||||
w.buf[w.pos>>3] = w.buf[w.pos>>3] | (0x80 >> (w.pos & 7)) |
||||
} |
||||
w.pos += 1 |
||||
} |
||||
@ -1,59 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package tag provides the labels used for telemetry throughout gopls.
|
||||
package tag |
||||
|
||||
import ( |
||||
"golang.org/x/tools/internal/event/keys" |
||||
) |
||||
|
||||
var ( |
||||
// create the label keys we use
|
||||
Method = keys.NewString("method", "") |
||||
StatusCode = keys.NewString("status.code", "") |
||||
StatusMessage = keys.NewString("status.message", "") |
||||
RPCID = keys.NewString("id", "") |
||||
RPCDirection = keys.NewString("direction", "") |
||||
File = keys.NewString("file", "") |
||||
Directory = keys.New("directory", "") |
||||
URI = keys.New("URI", "") |
||||
Package = keys.NewString("package", "") // sorted comma-separated list of Package IDs
|
||||
PackagePath = keys.NewString("package_path", "") |
||||
Query = keys.New("query", "") |
||||
Snapshot = keys.NewUInt64("snapshot", "") |
||||
Operation = keys.NewString("operation", "") |
||||
|
||||
Position = keys.New("position", "") |
||||
Category = keys.NewString("category", "") |
||||
PackageCount = keys.NewInt("packages", "") |
||||
Files = keys.New("files", "") |
||||
Port = keys.NewInt("port", "") |
||||
Type = keys.New("type", "") |
||||
HoverKind = keys.NewString("hoverkind", "") |
||||
|
||||
NewServer = keys.NewString("new_server", "A new server was added") |
||||
EndServer = keys.NewString("end_server", "A server was shut down") |
||||
|
||||
ServerID = keys.NewString("server", "The server ID an event is related to") |
||||
Logfile = keys.NewString("logfile", "") |
||||
DebugAddress = keys.NewString("debug_address", "") |
||||
GoplsPath = keys.NewString("gopls_path", "") |
||||
ClientID = keys.NewString("client_id", "") |
||||
|
||||
Level = keys.NewInt("level", "The logging level") |
||||
) |
||||
|
||||
var ( |
||||
// create the stats we measure
|
||||
Started = keys.NewInt64("started", "Count of started RPCs.") |
||||
ReceivedBytes = keys.NewInt64("received_bytes", "Bytes received.") //, unit.Bytes)
|
||||
SentBytes = keys.NewInt64("sent_bytes", "Bytes sent.") //, unit.Bytes)
|
||||
Latency = keys.NewFloat64("latency_ms", "Elapsed time in milliseconds") //, unit.Milliseconds)
|
||||
) |
||||
|
||||
const ( |
||||
Inbound = "in" |
||||
Outbound = "out" |
||||
) |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,97 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run generate.go
|
||||
|
||||
// Package stdlib provides a table of all exported symbols in the
|
||||
// standard library, along with the version at which they first
|
||||
// appeared.
|
||||
package stdlib |
||||
|
||||
import ( |
||||
"fmt" |
||||
"strings" |
||||
) |
||||
|
||||
type Symbol struct { |
||||
Name string |
||||
Kind Kind |
||||
Version Version // Go version that first included the symbol
|
||||
} |
||||
|
||||
// A Kind indicates the kind of a symbol:
|
||||
// function, variable, constant, type, and so on.
|
||||
type Kind int8 |
||||
|
||||
const ( |
||||
Invalid Kind = iota // Example name:
|
||||
Type // "Buffer"
|
||||
Func // "Println"
|
||||
Var // "EOF"
|
||||
Const // "Pi"
|
||||
Field // "Point.X"
|
||||
Method // "(*Buffer).Grow"
|
||||
) |
||||
|
||||
func (kind Kind) String() string { |
||||
return [...]string{ |
||||
Invalid: "invalid", |
||||
Type: "type", |
||||
Func: "func", |
||||
Var: "var", |
||||
Const: "const", |
||||
Field: "field", |
||||
Method: "method", |
||||
}[kind] |
||||
} |
||||
|
||||
// A Version represents a version of Go of the form "go1.%d".
|
||||
type Version int8 |
||||
|
||||
// String returns a version string of the form "go1.23", without allocating.
|
||||
func (v Version) String() string { return versions[v] } |
||||
|
||||
var versions [30]string // (increase constant as needed)
|
||||
|
||||
func init() { |
||||
for i := range versions { |
||||
versions[i] = fmt.Sprintf("go1.%d", i) |
||||
} |
||||
} |
||||
|
||||
// HasPackage reports whether the specified package path is part of
|
||||
// the standard library's public API.
|
||||
func HasPackage(path string) bool { |
||||
_, ok := PackageSymbols[path] |
||||
return ok |
||||
} |
||||
|
||||
// SplitField splits the field symbol name into type and field
|
||||
// components. It must be called only on Field symbols.
|
||||
//
|
||||
// Example: "File.Package" -> ("File", "Package")
|
||||
func (sym *Symbol) SplitField() (typename, name string) { |
||||
if sym.Kind != Field { |
||||
panic("not a field") |
||||
} |
||||
typename, name, _ = strings.Cut(sym.Name, ".") |
||||
return |
||||
} |
||||
|
||||
// SplitMethod splits the method symbol name into pointer, receiver,
|
||||
// and method components. It must be called only on Method symbols.
|
||||
//
|
||||
// Example: "(*Buffer).Grow" -> (true, "Buffer", "Grow")
|
||||
func (sym *Symbol) SplitMethod() (ptr bool, recv, name string) { |
||||
if sym.Kind != Method { |
||||
panic("not a method") |
||||
} |
||||
recv, name, _ = strings.Cut(sym.Name, ".") |
||||
recv = recv[len("(") : len(recv)-len(")")] |
||||
ptr = recv[0] == '*' |
||||
if ptr { |
||||
recv = recv[len("*"):] |
||||
} |
||||
return |
||||
} |
||||
@ -1,195 +0,0 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package typeparams contains common utilities for writing tools that
|
||||
// interact with generic Go code, as introduced with Go 1.18. It
|
||||
// supplements the standard library APIs. Notably, the StructuralTerms
|
||||
// API computes a minimal representation of the structural
|
||||
// restrictions on a type parameter.
|
||||
//
|
||||
// An external version of these APIs is available in the
|
||||
// golang.org/x/exp/typeparams module.
|
||||
package typeparams |
||||
|
||||
import ( |
||||
"fmt" |
||||
"go/ast" |
||||
"go/token" |
||||
"go/types" |
||||
|
||||
"golang.org/x/tools/internal/aliases" |
||||
"golang.org/x/tools/internal/typesinternal" |
||||
) |
||||
|
||||
// UnpackIndexExpr extracts data from AST nodes that represent index
|
||||
// expressions.
|
||||
//
|
||||
// For an ast.IndexExpr, the resulting indices slice will contain exactly one
|
||||
// index expression. For an ast.IndexListExpr (go1.18+), it may have a variable
|
||||
// number of index expressions.
|
||||
//
|
||||
// For nodes that don't represent index expressions, the first return value of
|
||||
// UnpackIndexExpr will be nil.
|
||||
func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) { |
||||
switch e := n.(type) { |
||||
case *ast.IndexExpr: |
||||
return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack |
||||
case *ast.IndexListExpr: |
||||
return e.X, e.Lbrack, e.Indices, e.Rbrack |
||||
} |
||||
return nil, token.NoPos, nil, token.NoPos |
||||
} |
||||
|
||||
// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on
|
||||
// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0
|
||||
// will panic.
|
||||
func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr { |
||||
switch len(indices) { |
||||
case 0: |
||||
panic("empty indices") |
||||
case 1: |
||||
return &ast.IndexExpr{ |
||||
X: x, |
||||
Lbrack: lbrack, |
||||
Index: indices[0], |
||||
Rbrack: rbrack, |
||||
} |
||||
default: |
||||
return &ast.IndexListExpr{ |
||||
X: x, |
||||
Lbrack: lbrack, |
||||
Indices: indices, |
||||
Rbrack: rbrack, |
||||
} |
||||
} |
||||
} |
||||
|
||||
// IsTypeParam reports whether t is a type parameter (or an alias of one).
|
||||
func IsTypeParam(t types.Type) bool { |
||||
_, ok := aliases.Unalias(t).(*types.TypeParam) |
||||
return ok |
||||
} |
||||
|
||||
// OriginMethod returns the origin method associated with the method fn.
|
||||
// For methods on a non-generic receiver base type, this is just
|
||||
// fn. However, for methods with a generic receiver, OriginMethod returns the
|
||||
// corresponding method in the method set of the origin type.
|
||||
//
|
||||
// As a special case, if fn is not a method (has no receiver), OriginMethod
|
||||
// returns fn.
|
||||
func OriginMethod(fn *types.Func) *types.Func { |
||||
recv := fn.Type().(*types.Signature).Recv() |
||||
if recv == nil { |
||||
return fn |
||||
} |
||||
_, named := typesinternal.ReceiverNamed(recv) |
||||
if named == nil { |
||||
// Receiver is a *types.Interface.
|
||||
return fn |
||||
} |
||||
if named.TypeParams().Len() == 0 { |
||||
// Receiver base has no type parameters, so we can avoid the lookup below.
|
||||
return fn |
||||
} |
||||
orig := named.Origin() |
||||
gfn, _, _ := types.LookupFieldOrMethod(orig, true, fn.Pkg(), fn.Name()) |
||||
|
||||
// This is a fix for a gopls crash (#60628) due to a go/types bug (#60634). In:
|
||||
// package p
|
||||
// type T *int
|
||||
// func (*T) f() {}
|
||||
// LookupFieldOrMethod(T, true, p, f)=nil, but NewMethodSet(*T)={(*T).f}.
|
||||
// Here we make them consistent by force.
|
||||
// (The go/types bug is general, but this workaround is reached only
|
||||
// for generic T thanks to the early return above.)
|
||||
if gfn == nil { |
||||
mset := types.NewMethodSet(types.NewPointer(orig)) |
||||
for i := 0; i < mset.Len(); i++ { |
||||
m := mset.At(i) |
||||
if m.Obj().Id() == fn.Id() { |
||||
gfn = m.Obj() |
||||
break |
||||
} |
||||
} |
||||
} |
||||
|
||||
// In golang/go#61196, we observe another crash, this time inexplicable.
|
||||
if gfn == nil { |
||||
panic(fmt.Sprintf("missing origin method for %s.%s; named == origin: %t, named.NumMethods(): %d, origin.NumMethods(): %d", named, fn, named == orig, named.NumMethods(), orig.NumMethods())) |
||||
} |
||||
|
||||
return gfn.(*types.Func) |
||||
} |
||||
|
||||
// GenericAssignableTo is a generalization of types.AssignableTo that
|
||||
// implements the following rule for uninstantiated generic types:
|
||||
//
|
||||
// If V and T are generic named types, then V is considered assignable to T if,
|
||||
// for every possible instantation of V[A_1, ..., A_N], the instantiation
|
||||
// T[A_1, ..., A_N] is valid and V[A_1, ..., A_N] implements T[A_1, ..., A_N].
|
||||
//
|
||||
// If T has structural constraints, they must be satisfied by V.
|
||||
//
|
||||
// For example, consider the following type declarations:
|
||||
//
|
||||
// type Interface[T any] interface {
|
||||
// Accept(T)
|
||||
// }
|
||||
//
|
||||
// type Container[T any] struct {
|
||||
// Element T
|
||||
// }
|
||||
//
|
||||
// func (c Container[T]) Accept(t T) { c.Element = t }
|
||||
//
|
||||
// In this case, GenericAssignableTo reports that instantiations of Container
|
||||
// are assignable to the corresponding instantiation of Interface.
|
||||
func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool { |
||||
V = aliases.Unalias(V) |
||||
T = aliases.Unalias(T) |
||||
|
||||
// If V and T are not both named, or do not have matching non-empty type
|
||||
// parameter lists, fall back on types.AssignableTo.
|
||||
|
||||
VN, Vnamed := V.(*types.Named) |
||||
TN, Tnamed := T.(*types.Named) |
||||
if !Vnamed || !Tnamed { |
||||
return types.AssignableTo(V, T) |
||||
} |
||||
|
||||
vtparams := VN.TypeParams() |
||||
ttparams := TN.TypeParams() |
||||
if vtparams.Len() == 0 || vtparams.Len() != ttparams.Len() || VN.TypeArgs().Len() != 0 || TN.TypeArgs().Len() != 0 { |
||||
return types.AssignableTo(V, T) |
||||
} |
||||
|
||||
// V and T have the same (non-zero) number of type params. Instantiate both
|
||||
// with the type parameters of V. This must always succeed for V, and will
|
||||
// succeed for T if and only if the type set of each type parameter of V is a
|
||||
// subset of the type set of the corresponding type parameter of T, meaning
|
||||
// that every instantiation of V corresponds to a valid instantiation of T.
|
||||
|
||||
// Minor optimization: ensure we share a context across the two
|
||||
// instantiations below.
|
||||
if ctxt == nil { |
||||
ctxt = types.NewContext() |
||||
} |
||||
|
||||
var targs []types.Type |
||||
for i := 0; i < vtparams.Len(); i++ { |
||||
targs = append(targs, vtparams.At(i)) |
||||
} |
||||
|
||||
vinst, err := types.Instantiate(ctxt, V, targs, true) |
||||
if err != nil { |
||||
panic("type parameters should satisfy their own constraints") |
||||
} |
||||
|
||||
tinst, err := types.Instantiate(ctxt, T, targs, true) |
||||
if err != nil { |
||||
return false |
||||
} |
||||
|
||||
return types.AssignableTo(vinst, tinst) |
||||
} |
||||
@ -1,137 +0,0 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typeparams |
||||
|
||||
import ( |
||||
"fmt" |
||||
"go/types" |
||||
|
||||
"golang.org/x/tools/internal/aliases" |
||||
) |
||||
|
||||
// CoreType returns the core type of T or nil if T does not have a core type.
|
||||
//
|
||||
// See https://go.dev/ref/spec#Core_types for the definition of a core type.
|
||||
func CoreType(T types.Type) types.Type { |
||||
U := T.Underlying() |
||||
if _, ok := U.(*types.Interface); !ok { |
||||
return U // for non-interface types,
|
||||
} |
||||
|
||||
terms, err := _NormalTerms(U) |
||||
if len(terms) == 0 || err != nil { |
||||
// len(terms) -> empty type set of interface.
|
||||
// err != nil => U is invalid, exceeds complexity bounds, or has an empty type set.
|
||||
return nil // no core type.
|
||||
} |
||||
|
||||
U = terms[0].Type().Underlying() |
||||
var identical int // i in [0,identical) => Identical(U, terms[i].Type().Underlying())
|
||||
for identical = 1; identical < len(terms); identical++ { |
||||
if !types.Identical(U, terms[identical].Type().Underlying()) { |
||||
break |
||||
} |
||||
} |
||||
|
||||
if identical == len(terms) { |
||||
// https://go.dev/ref/spec#Core_types
|
||||
// "There is a single type U which is the underlying type of all types in the type set of T"
|
||||
return U |
||||
} |
||||
ch, ok := U.(*types.Chan) |
||||
if !ok { |
||||
return nil // no core type as identical < len(terms) and U is not a channel.
|
||||
} |
||||
// https://go.dev/ref/spec#Core_types
|
||||
// "the type chan E if T contains only bidirectional channels, or the type chan<- E or
|
||||
// <-chan E depending on the direction of the directional channels present."
|
||||
for chans := identical; chans < len(terms); chans++ { |
||||
curr, ok := terms[chans].Type().Underlying().(*types.Chan) |
||||
if !ok { |
||||
return nil |
||||
} |
||||
if !types.Identical(ch.Elem(), curr.Elem()) { |
||||
return nil // channel elements are not identical.
|
||||
} |
||||
if ch.Dir() == types.SendRecv { |
||||
// ch is bidirectional. We can safely always use curr's direction.
|
||||
ch = curr |
||||
} else if curr.Dir() != types.SendRecv && ch.Dir() != curr.Dir() { |
||||
// ch and curr are not bidirectional and not the same direction.
|
||||
return nil |
||||
} |
||||
} |
||||
return ch |
||||
} |
||||
|
||||
// _NormalTerms returns a slice of terms representing the normalized structural
|
||||
// type restrictions of a type, if any.
|
||||
//
|
||||
// For all types other than *types.TypeParam, *types.Interface, and
|
||||
// *types.Union, this is just a single term with Tilde() == false and
|
||||
// Type() == typ. For *types.TypeParam, *types.Interface, and *types.Union, see
|
||||
// below.
|
||||
//
|
||||
// Structural type restrictions of a type parameter are created via
|
||||
// non-interface types embedded in its constraint interface (directly, or via a
|
||||
// chain of interface embeddings). For example, in the declaration type
|
||||
// T[P interface{~int; m()}] int the structural restriction of the type
|
||||
// parameter P is ~int.
|
||||
//
|
||||
// With interface embedding and unions, the specification of structural type
|
||||
// restrictions may be arbitrarily complex. For example, consider the
|
||||
// following:
|
||||
//
|
||||
// type A interface{ ~string|~[]byte }
|
||||
//
|
||||
// type B interface{ int|string }
|
||||
//
|
||||
// type C interface { ~string|~int }
|
||||
//
|
||||
// type T[P interface{ A|B; C }] int
|
||||
//
|
||||
// In this example, the structural type restriction of P is ~string|int: A|B
|
||||
// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
|
||||
// which when intersected with C (~string|~int) yields ~string|int.
|
||||
//
|
||||
// _NormalTerms computes these expansions and reductions, producing a
|
||||
// "normalized" form of the embeddings. A structural restriction is normalized
|
||||
// if it is a single union containing no interface terms, and is minimal in the
|
||||
// sense that removing any term changes the set of types satisfying the
|
||||
// constraint. It is left as a proof for the reader that, modulo sorting, there
|
||||
// is exactly one such normalized form.
|
||||
//
|
||||
// Because the minimal representation always takes this form, _NormalTerms
|
||||
// returns a slice of tilde terms corresponding to the terms of the union in
|
||||
// the normalized structural restriction. An error is returned if the type is
|
||||
// invalid, exceeds complexity bounds, or has an empty type set. In the latter
|
||||
// case, _NormalTerms returns ErrEmptyTypeSet.
|
||||
//
|
||||
// _NormalTerms makes no guarantees about the order of terms, except that it
|
||||
// is deterministic.
|
||||
func _NormalTerms(typ types.Type) ([]*types.Term, error) { |
||||
switch typ := aliases.Unalias(typ).(type) { |
||||
case *types.TypeParam: |
||||
return StructuralTerms(typ) |
||||
case *types.Union: |
||||
return UnionTermSet(typ) |
||||
case *types.Interface: |
||||
return InterfaceTermSet(typ) |
||||
default: |
||||
return []*types.Term{types.NewTerm(false, typ)}, nil |
||||
} |
||||
} |
||||
|
||||
// MustDeref returns the type of the variable pointed to by t.
|
||||
// It panics if t's core type is not a pointer.
|
||||
//
|
||||
// TODO(adonovan): ideally this would live in typesinternal, but that
|
||||
// creates an import cycle. Move there when we melt this package down.
|
||||
func MustDeref(t types.Type) types.Type { |
||||
if ptr, ok := CoreType(t).(*types.Pointer); ok { |
||||
return ptr.Elem() |
||||
} |
||||
panic(fmt.Sprintf("%v is not a pointer", t)) |
||||
} |
||||
@ -1,218 +0,0 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typeparams |
||||
|
||||
import ( |
||||
"errors" |
||||
"fmt" |
||||
"go/types" |
||||
"os" |
||||
"strings" |
||||
) |
||||
|
||||
//go:generate go run copytermlist.go
|
||||
|
||||
const debug = false |
||||
|
||||
var ErrEmptyTypeSet = errors.New("empty type set") |
||||
|
||||
// StructuralTerms returns a slice of terms representing the normalized
|
||||
// structural type restrictions of a type parameter, if any.
|
||||
//
|
||||
// Structural type restrictions of a type parameter are created via
|
||||
// non-interface types embedded in its constraint interface (directly, or via a
|
||||
// chain of interface embeddings). For example, in the declaration
|
||||
//
|
||||
// type T[P interface{~int; m()}] int
|
||||
//
|
||||
// the structural restriction of the type parameter P is ~int.
|
||||
//
|
||||
// With interface embedding and unions, the specification of structural type
|
||||
// restrictions may be arbitrarily complex. For example, consider the
|
||||
// following:
|
||||
//
|
||||
// type A interface{ ~string|~[]byte }
|
||||
//
|
||||
// type B interface{ int|string }
|
||||
//
|
||||
// type C interface { ~string|~int }
|
||||
//
|
||||
// type T[P interface{ A|B; C }] int
|
||||
//
|
||||
// In this example, the structural type restriction of P is ~string|int: A|B
|
||||
// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
|
||||
// which when intersected with C (~string|~int) yields ~string|int.
|
||||
//
|
||||
// StructuralTerms computes these expansions and reductions, producing a
|
||||
// "normalized" form of the embeddings. A structural restriction is normalized
|
||||
// if it is a single union containing no interface terms, and is minimal in the
|
||||
// sense that removing any term changes the set of types satisfying the
|
||||
// constraint. It is left as a proof for the reader that, modulo sorting, there
|
||||
// is exactly one such normalized form.
|
||||
//
|
||||
// Because the minimal representation always takes this form, StructuralTerms
|
||||
// returns a slice of tilde terms corresponding to the terms of the union in
|
||||
// the normalized structural restriction. An error is returned if the
|
||||
// constraint interface is invalid, exceeds complexity bounds, or has an empty
|
||||
// type set. In the latter case, StructuralTerms returns ErrEmptyTypeSet.
|
||||
//
|
||||
// StructuralTerms makes no guarantees about the order of terms, except that it
|
||||
// is deterministic.
|
||||
func StructuralTerms(tparam *types.TypeParam) ([]*types.Term, error) { |
||||
constraint := tparam.Constraint() |
||||
if constraint == nil { |
||||
return nil, fmt.Errorf("%s has nil constraint", tparam) |
||||
} |
||||
iface, _ := constraint.Underlying().(*types.Interface) |
||||
if iface == nil { |
||||
return nil, fmt.Errorf("constraint is %T, not *types.Interface", constraint.Underlying()) |
||||
} |
||||
return InterfaceTermSet(iface) |
||||
} |
||||
|
||||
// InterfaceTermSet computes the normalized terms for a constraint interface,
|
||||
// returning an error if the term set cannot be computed or is empty. In the
|
||||
// latter case, the error will be ErrEmptyTypeSet.
|
||||
//
|
||||
// See the documentation of StructuralTerms for more information on
|
||||
// normalization.
|
||||
func InterfaceTermSet(iface *types.Interface) ([]*types.Term, error) { |
||||
return computeTermSet(iface) |
||||
} |
||||
|
||||
// UnionTermSet computes the normalized terms for a union, returning an error
|
||||
// if the term set cannot be computed or is empty. In the latter case, the
|
||||
// error will be ErrEmptyTypeSet.
|
||||
//
|
||||
// See the documentation of StructuralTerms for more information on
|
||||
// normalization.
|
||||
func UnionTermSet(union *types.Union) ([]*types.Term, error) { |
||||
return computeTermSet(union) |
||||
} |
||||
|
||||
func computeTermSet(typ types.Type) ([]*types.Term, error) { |
||||
tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
if tset.terms.isEmpty() { |
||||
return nil, ErrEmptyTypeSet |
||||
} |
||||
if tset.terms.isAll() { |
||||
return nil, nil |
||||
} |
||||
var terms []*types.Term |
||||
for _, term := range tset.terms { |
||||
terms = append(terms, types.NewTerm(term.tilde, term.typ)) |
||||
} |
||||
return terms, nil |
||||
} |
||||
|
||||
// A termSet holds the normalized set of terms for a given type.
|
||||
//
|
||||
// The name termSet is intentionally distinct from 'type set': a type set is
|
||||
// all types that implement a type (and includes method restrictions), whereas
|
||||
// a term set just represents the structural restrictions on a type.
|
||||
type termSet struct { |
||||
complete bool |
||||
terms termlist |
||||
} |
||||
|
||||
func indentf(depth int, format string, args ...interface{}) { |
||||
fmt.Fprintf(os.Stderr, strings.Repeat(".", depth)+format+"\n", args...) |
||||
} |
||||
|
||||
func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error) { |
||||
if t == nil { |
||||
panic("nil type") |
||||
} |
||||
|
||||
if debug { |
||||
indentf(depth, "%s", t.String()) |
||||
defer func() { |
||||
if err != nil { |
||||
indentf(depth, "=> %s", err) |
||||
} else { |
||||
indentf(depth, "=> %s", res.terms.String()) |
||||
} |
||||
}() |
||||
} |
||||
|
||||
const maxTermCount = 100 |
||||
if tset, ok := seen[t]; ok { |
||||
if !tset.complete { |
||||
return nil, fmt.Errorf("cycle detected in the declaration of %s", t) |
||||
} |
||||
return tset, nil |
||||
} |
||||
|
||||
// Mark the current type as seen to avoid infinite recursion.
|
||||
tset := new(termSet) |
||||
defer func() { |
||||
tset.complete = true |
||||
}() |
||||
seen[t] = tset |
||||
|
||||
switch u := t.Underlying().(type) { |
||||
case *types.Interface: |
||||
// The term set of an interface is the intersection of the term sets of its
|
||||
// embedded types.
|
||||
tset.terms = allTermlist |
||||
for i := 0; i < u.NumEmbeddeds(); i++ { |
||||
embedded := u.EmbeddedType(i) |
||||
if _, ok := embedded.Underlying().(*types.TypeParam); ok { |
||||
return nil, fmt.Errorf("invalid embedded type %T", embedded) |
||||
} |
||||
tset2, err := computeTermSetInternal(embedded, seen, depth+1) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
tset.terms = tset.terms.intersect(tset2.terms) |
||||
} |
||||
case *types.Union: |
||||
// The term set of a union is the union of term sets of its terms.
|
||||
tset.terms = nil |
||||
for i := 0; i < u.Len(); i++ { |
||||
t := u.Term(i) |
||||
var terms termlist |
||||
switch t.Type().Underlying().(type) { |
||||
case *types.Interface: |
||||
tset2, err := computeTermSetInternal(t.Type(), seen, depth+1) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
terms = tset2.terms |
||||
case *types.TypeParam, *types.Union: |
||||
// A stand-alone type parameter or union is not permitted as union
|
||||
// term.
|
||||
return nil, fmt.Errorf("invalid union term %T", t) |
||||
default: |
||||
if t.Type() == types.Typ[types.Invalid] { |
||||
continue |
||||
} |
||||
terms = termlist{{t.Tilde(), t.Type()}} |
||||
} |
||||
tset.terms = tset.terms.union(terms) |
||||
if len(tset.terms) > maxTermCount { |
||||
return nil, fmt.Errorf("exceeded max term count %d", maxTermCount) |
||||
} |
||||
} |
||||
case *types.TypeParam: |
||||
panic("unreachable") |
||||
default: |
||||
// For all other types, the term set is just a single non-tilde term
|
||||
// holding the type itself.
|
||||
if u != types.Typ[types.Invalid] { |
||||
tset.terms = termlist{{false, t}} |
||||
} |
||||
} |
||||
return tset, nil |
||||
} |
||||
|
||||
// under is a facade for the go/types internal function of the same name. It is
|
||||
// used by typeterm.go.
|
||||
func under(t types.Type) types.Type { |
||||
return t.Underlying() |
||||
} |
||||
@ -1,163 +0,0 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Code generated by copytermlist.go DO NOT EDIT.
|
||||
|
||||
package typeparams |
||||
|
||||
import ( |
||||
"bytes" |
||||
"go/types" |
||||
) |
||||
|
||||
// A termlist represents the type set represented by the union
|
||||
// t1 ∪ y2 ∪ ... tn of the type sets of the terms t1 to tn.
|
||||
// A termlist is in normal form if all terms are disjoint.
|
||||
// termlist operations don't require the operands to be in
|
||||
// normal form.
|
||||
type termlist []*term |
||||
|
||||
// allTermlist represents the set of all types.
|
||||
// It is in normal form.
|
||||
var allTermlist = termlist{new(term)} |
||||
|
||||
// String prints the termlist exactly (without normalization).
|
||||
func (xl termlist) String() string { |
||||
if len(xl) == 0 { |
||||
return "∅" |
||||
} |
||||
var buf bytes.Buffer |
||||
for i, x := range xl { |
||||
if i > 0 { |
||||
buf.WriteString(" | ") |
||||
} |
||||
buf.WriteString(x.String()) |
||||
} |
||||
return buf.String() |
||||
} |
||||
|
||||
// isEmpty reports whether the termlist xl represents the empty set of types.
|
||||
func (xl termlist) isEmpty() bool { |
||||
// If there's a non-nil term, the entire list is not empty.
|
||||
// If the termlist is in normal form, this requires at most
|
||||
// one iteration.
|
||||
for _, x := range xl { |
||||
if x != nil { |
||||
return false |
||||
} |
||||
} |
||||
return true |
||||
} |
||||
|
||||
// isAll reports whether the termlist xl represents the set of all types.
|
||||
func (xl termlist) isAll() bool { |
||||
// If there's a 𝓤 term, the entire list is 𝓤.
|
||||
// If the termlist is in normal form, this requires at most
|
||||
// one iteration.
|
||||
for _, x := range xl { |
||||
if x != nil && x.typ == nil { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
||||
|
||||
// norm returns the normal form of xl.
|
||||
func (xl termlist) norm() termlist { |
||||
// Quadratic algorithm, but good enough for now.
|
||||
// TODO(gri) fix asymptotic performance
|
||||
used := make([]bool, len(xl)) |
||||
var rl termlist |
||||
for i, xi := range xl { |
||||
if xi == nil || used[i] { |
||||
continue |
||||
} |
||||
for j := i + 1; j < len(xl); j++ { |
||||
xj := xl[j] |
||||
if xj == nil || used[j] { |
||||
continue |
||||
} |
||||
if u1, u2 := xi.union(xj); u2 == nil { |
||||
// If we encounter a 𝓤 term, the entire list is 𝓤.
|
||||
// Exit early.
|
||||
// (Note that this is not just an optimization;
|
||||
// if we continue, we may end up with a 𝓤 term
|
||||
// and other terms and the result would not be
|
||||
// in normal form.)
|
||||
if u1.typ == nil { |
||||
return allTermlist |
||||
} |
||||
xi = u1 |
||||
used[j] = true // xj is now unioned into xi - ignore it in future iterations
|
||||
} |
||||
} |
||||
rl = append(rl, xi) |
||||
} |
||||
return rl |
||||
} |
||||
|
||||
// union returns the union xl ∪ yl.
|
||||
func (xl termlist) union(yl termlist) termlist { |
||||
return append(xl, yl...).norm() |
||||
} |
||||
|
||||
// intersect returns the intersection xl ∩ yl.
|
||||
func (xl termlist) intersect(yl termlist) termlist { |
||||
if xl.isEmpty() || yl.isEmpty() { |
||||
return nil |
||||
} |
||||
|
||||
// Quadratic algorithm, but good enough for now.
|
||||
// TODO(gri) fix asymptotic performance
|
||||
var rl termlist |
||||
for _, x := range xl { |
||||
for _, y := range yl { |
||||
if r := x.intersect(y); r != nil { |
||||
rl = append(rl, r) |
||||
} |
||||
} |
||||
} |
||||
return rl.norm() |
||||
} |
||||
|
||||
// equal reports whether xl and yl represent the same type set.
|
||||
func (xl termlist) equal(yl termlist) bool { |
||||
// TODO(gri) this should be more efficient
|
||||
return xl.subsetOf(yl) && yl.subsetOf(xl) |
||||
} |
||||
|
||||
// includes reports whether t ∈ xl.
|
||||
func (xl termlist) includes(t types.Type) bool { |
||||
for _, x := range xl { |
||||
if x.includes(t) { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
||||
|
||||
// supersetOf reports whether y ⊆ xl.
|
||||
func (xl termlist) supersetOf(y *term) bool { |
||||
for _, x := range xl { |
||||
if y.subsetOf(x) { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
||||
|
||||
// subsetOf reports whether xl ⊆ yl.
|
||||
func (xl termlist) subsetOf(yl termlist) bool { |
||||
if yl.isEmpty() { |
||||
return xl.isEmpty() |
||||
} |
||||
|
||||
// each term x of xl must be a subset of yl
|
||||
for _, x := range xl { |
||||
if !yl.supersetOf(x) { |
||||
return false // x is not a subset yl
|
||||
} |
||||
} |
||||
return true |
||||
} |
||||
@ -1,169 +0,0 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Code generated by copytermlist.go DO NOT EDIT.
|
||||
|
||||
package typeparams |
||||
|
||||
import "go/types" |
||||
|
||||
// A term describes elementary type sets:
|
||||
//
|
||||
// ∅: (*term)(nil) == ∅ // set of no types (empty set)
|
||||
// 𝓤: &term{} == 𝓤 // set of all types (𝓤niverse)
|
||||
// T: &term{false, T} == {T} // set of type T
|
||||
// ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t
|
||||
type term struct { |
||||
tilde bool // valid if typ != nil
|
||||
typ types.Type |
||||
} |
||||
|
||||
func (x *term) String() string { |
||||
switch { |
||||
case x == nil: |
||||
return "∅" |
||||
case x.typ == nil: |
||||
return "𝓤" |
||||
case x.tilde: |
||||
return "~" + x.typ.String() |
||||
default: |
||||
return x.typ.String() |
||||
} |
||||
} |
||||
|
||||
// equal reports whether x and y represent the same type set.
|
||||
func (x *term) equal(y *term) bool { |
||||
// easy cases
|
||||
switch { |
||||
case x == nil || y == nil: |
||||
return x == y |
||||
case x.typ == nil || y.typ == nil: |
||||
return x.typ == y.typ |
||||
} |
||||
// ∅ ⊂ x, y ⊂ 𝓤
|
||||
|
||||
return x.tilde == y.tilde && types.Identical(x.typ, y.typ) |
||||
} |
||||
|
||||
// union returns the union x ∪ y: zero, one, or two non-nil terms.
|
||||
func (x *term) union(y *term) (_, _ *term) { |
||||
// easy cases
|
||||
switch { |
||||
case x == nil && y == nil: |
||||
return nil, nil // ∅ ∪ ∅ == ∅
|
||||
case x == nil: |
||||
return y, nil // ∅ ∪ y == y
|
||||
case y == nil: |
||||
return x, nil // x ∪ ∅ == x
|
||||
case x.typ == nil: |
||||
return x, nil // 𝓤 ∪ y == 𝓤
|
||||
case y.typ == nil: |
||||
return y, nil // x ∪ 𝓤 == 𝓤
|
||||
} |
||||
// ∅ ⊂ x, y ⊂ 𝓤
|
||||
|
||||
if x.disjoint(y) { |
||||
return x, y // x ∪ y == (x, y) if x ∩ y == ∅
|
||||
} |
||||
// x.typ == y.typ
|
||||
|
||||
// ~t ∪ ~t == ~t
|
||||
// ~t ∪ T == ~t
|
||||
// T ∪ ~t == ~t
|
||||
// T ∪ T == T
|
||||
if x.tilde || !y.tilde { |
||||
return x, nil |
||||
} |
||||
return y, nil |
||||
} |
||||
|
||||
// intersect returns the intersection x ∩ y.
|
||||
func (x *term) intersect(y *term) *term { |
||||
// easy cases
|
||||
switch { |
||||
case x == nil || y == nil: |
||||
return nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅
|
||||
case x.typ == nil: |
||||
return y // 𝓤 ∩ y == y
|
||||
case y.typ == nil: |
||||
return x // x ∩ 𝓤 == x
|
||||
} |
||||
// ∅ ⊂ x, y ⊂ 𝓤
|
||||
|
||||
if x.disjoint(y) { |
||||
return nil // x ∩ y == ∅ if x ∩ y == ∅
|
||||
} |
||||
// x.typ == y.typ
|
||||
|
||||
// ~t ∩ ~t == ~t
|
||||
// ~t ∩ T == T
|
||||
// T ∩ ~t == T
|
||||
// T ∩ T == T
|
||||
if !x.tilde || y.tilde { |
||||
return x |
||||
} |
||||
return y |
||||
} |
||||
|
||||
// includes reports whether t ∈ x.
|
||||
func (x *term) includes(t types.Type) bool { |
||||
// easy cases
|
||||
switch { |
||||
case x == nil: |
||||
return false // t ∈ ∅ == false
|
||||
case x.typ == nil: |
||||
return true // t ∈ 𝓤 == true
|
||||
} |
||||
// ∅ ⊂ x ⊂ 𝓤
|
||||
|
||||
u := t |
||||
if x.tilde { |
||||
u = under(u) |
||||
} |
||||
return types.Identical(x.typ, u) |
||||
} |
||||
|
||||
// subsetOf reports whether x ⊆ y.
|
||||
func (x *term) subsetOf(y *term) bool { |
||||
// easy cases
|
||||
switch { |
||||
case x == nil: |
||||
return true // ∅ ⊆ y == true
|
||||
case y == nil: |
||||
return false // x ⊆ ∅ == false since x != ∅
|
||||
case y.typ == nil: |
||||
return true // x ⊆ 𝓤 == true
|
||||
case x.typ == nil: |
||||
return false // 𝓤 ⊆ y == false since y != 𝓤
|
||||
} |
||||
// ∅ ⊂ x, y ⊂ 𝓤
|
||||
|
||||
if x.disjoint(y) { |
||||
return false // x ⊆ y == false if x ∩ y == ∅
|
||||
} |
||||
// x.typ == y.typ
|
||||
|
||||
// ~t ⊆ ~t == true
|
||||
// ~t ⊆ T == false
|
||||
// T ⊆ ~t == true
|
||||
// T ⊆ T == true
|
||||
return !x.tilde || y.tilde |
||||
} |
||||
|
||||
// disjoint reports whether x ∩ y == ∅.
|
||||
// x.typ and y.typ must not be nil.
|
||||
func (x *term) disjoint(y *term) bool { |
||||
if debug && (x.typ == nil || y.typ == nil) { |
||||
panic("invalid argument(s)") |
||||
} |
||||
ux := x.typ |
||||
if y.tilde { |
||||
ux = under(ux) |
||||
} |
||||
uy := y.typ |
||||
if x.tilde { |
||||
uy = under(uy) |
||||
} |
||||
return !types.Identical(ux, uy) |
||||
} |
||||
@ -0,0 +1,89 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typesinternal |
||||
|
||||
import ( |
||||
"go/types" |
||||
|
||||
"golang.org/x/tools/internal/stdlib" |
||||
"golang.org/x/tools/internal/versions" |
||||
) |
||||
|
||||
// TooNewStdSymbols computes the set of package-level symbols
|
||||
// exported by pkg that are not available at the specified version.
|
||||
// The result maps each symbol to its minimum version.
|
||||
//
|
||||
// The pkg is allowed to contain type errors.
|
||||
func TooNewStdSymbols(pkg *types.Package, version string) map[types.Object]string { |
||||
disallowed := make(map[types.Object]string) |
||||
|
||||
// Pass 1: package-level symbols.
|
||||
symbols := stdlib.PackageSymbols[pkg.Path()] |
||||
for _, sym := range symbols { |
||||
symver := sym.Version.String() |
||||
if versions.Before(version, symver) { |
||||
switch sym.Kind { |
||||
case stdlib.Func, stdlib.Var, stdlib.Const, stdlib.Type: |
||||
disallowed[pkg.Scope().Lookup(sym.Name)] = symver |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Pass 2: fields and methods.
|
||||
//
|
||||
// We allow fields and methods if their associated type is
|
||||
// disallowed, as otherwise we would report false positives
|
||||
// for compatibility shims. Consider:
|
||||
//
|
||||
// //go:build go1.22
|
||||
// type T struct { F std.Real } // correct new API
|
||||
//
|
||||
// //go:build !go1.22
|
||||
// type T struct { F fake } // shim
|
||||
// type fake struct { ... }
|
||||
// func (fake) M () {}
|
||||
//
|
||||
// These alternative declarations of T use either the std.Real
|
||||
// type, introduced in go1.22, or a fake type, for the field
|
||||
// F. (The fakery could be arbitrarily deep, involving more
|
||||
// nested fields and methods than are shown here.) Clients
|
||||
// that use the compatibility shim T will compile with any
|
||||
// version of go, whether older or newer than go1.22, but only
|
||||
// the newer version will use the std.Real implementation.
|
||||
//
|
||||
// Now consider a reference to method M in new(T).F.M() in a
|
||||
// module that requires a minimum of go1.21. The analysis may
|
||||
// occur using a version of Go higher than 1.21, selecting the
|
||||
// first version of T, so the method M is Real.M. This would
|
||||
// spuriously cause the analyzer to report a reference to a
|
||||
// too-new symbol even though this expression compiles just
|
||||
// fine (with the fake implementation) using go1.21.
|
||||
for _, sym := range symbols { |
||||
symVersion := sym.Version.String() |
||||
if !versions.Before(version, symVersion) { |
||||
continue // allowed
|
||||
} |
||||
|
||||
var obj types.Object |
||||
switch sym.Kind { |
||||
case stdlib.Field: |
||||
typename, name := sym.SplitField() |
||||
if t := pkg.Scope().Lookup(typename); t != nil && disallowed[t] == "" { |
||||
obj, _, _ = types.LookupFieldOrMethod(t.Type(), false, pkg, name) |
||||
} |
||||
|
||||
case stdlib.Method: |
||||
ptr, recvname, name := sym.SplitMethod() |
||||
if t := pkg.Scope().Lookup(recvname); t != nil && disallowed[t] == "" { |
||||
obj, _, _ = types.LookupFieldOrMethod(t.Type(), ptr, pkg, name) |
||||
} |
||||
} |
||||
if obj != nil { |
||||
disallowed[obj] = symVersion |
||||
} |
||||
} |
||||
|
||||
return disallowed |
||||
} |
||||
@ -1,16 +0,0 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package typesinternal |
||||
|
||||
import ( |
||||
"go/types" |
||||
) |
||||
|
||||
func init() { |
||||
SetGoVersion = func(conf *types.Config, version string) bool { |
||||
conf.GoVersion = version |
||||
return true |
||||
} |
||||
} |
||||
@ -0,0 +1,160 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package protodelim marshals and unmarshals varint size-delimited messages.
|
||||
package protodelim |
||||
|
||||
import ( |
||||
"bufio" |
||||
"encoding/binary" |
||||
"fmt" |
||||
"io" |
||||
|
||||
"google.golang.org/protobuf/encoding/protowire" |
||||
"google.golang.org/protobuf/internal/errors" |
||||
"google.golang.org/protobuf/proto" |
||||
) |
||||
|
||||
// MarshalOptions is a configurable varint size-delimited marshaler.
|
||||
type MarshalOptions struct{ proto.MarshalOptions } |
||||
|
||||
// MarshalTo writes a varint size-delimited wire-format message to w.
|
||||
// If w returns an error, MarshalTo returns it unchanged.
|
||||
func (o MarshalOptions) MarshalTo(w io.Writer, m proto.Message) (int, error) { |
||||
msgBytes, err := o.MarshalOptions.Marshal(m) |
||||
if err != nil { |
||||
return 0, err |
||||
} |
||||
|
||||
sizeBytes := protowire.AppendVarint(nil, uint64(len(msgBytes))) |
||||
sizeWritten, err := w.Write(sizeBytes) |
||||
if err != nil { |
||||
return sizeWritten, err |
||||
} |
||||
msgWritten, err := w.Write(msgBytes) |
||||
if err != nil { |
||||
return sizeWritten + msgWritten, err |
||||
} |
||||
return sizeWritten + msgWritten, nil |
||||
} |
||||
|
||||
// MarshalTo writes a varint size-delimited wire-format message to w
|
||||
// with the default options.
|
||||
//
|
||||
// See the documentation for [MarshalOptions.MarshalTo].
|
||||
func MarshalTo(w io.Writer, m proto.Message) (int, error) { |
||||
return MarshalOptions{}.MarshalTo(w, m) |
||||
} |
||||
|
||||
// UnmarshalOptions is a configurable varint size-delimited unmarshaler.
|
||||
type UnmarshalOptions struct { |
||||
proto.UnmarshalOptions |
||||
|
||||
// MaxSize is the maximum size in wire-format bytes of a single message.
|
||||
// Unmarshaling a message larger than MaxSize will return an error.
|
||||
// A zero MaxSize will default to 4 MiB.
|
||||
// Setting MaxSize to -1 disables the limit.
|
||||
MaxSize int64 |
||||
} |
||||
|
||||
const defaultMaxSize = 4 << 20 // 4 MiB, corresponds to the default gRPC max request/response size
|
||||
|
||||
// SizeTooLargeError is an error that is returned when the unmarshaler encounters a message size
|
||||
// that is larger than its configured [UnmarshalOptions.MaxSize].
|
||||
type SizeTooLargeError struct { |
||||
// Size is the varint size of the message encountered
|
||||
// that was larger than the provided MaxSize.
|
||||
Size uint64 |
||||
|
||||
// MaxSize is the MaxSize limit configured in UnmarshalOptions, which Size exceeded.
|
||||
MaxSize uint64 |
||||
} |
||||
|
||||
func (e *SizeTooLargeError) Error() string { |
||||
return fmt.Sprintf("message size %d exceeded unmarshaler's maximum configured size %d", e.Size, e.MaxSize) |
||||
} |
||||
|
||||
// Reader is the interface expected by [UnmarshalFrom].
|
||||
// It is implemented by *[bufio.Reader].
|
||||
type Reader interface { |
||||
io.Reader |
||||
io.ByteReader |
||||
} |
||||
|
||||
// UnmarshalFrom parses and consumes a varint size-delimited wire-format message
|
||||
// from r.
|
||||
// The provided message must be mutable (e.g., a non-nil pointer to a message).
|
||||
//
|
||||
// The error is [io.EOF] error only if no bytes are read.
|
||||
// If an EOF happens after reading some but not all the bytes,
|
||||
// UnmarshalFrom returns a non-io.EOF error.
|
||||
// In particular if r returns a non-io.EOF error, UnmarshalFrom returns it unchanged,
|
||||
// and if only a size is read with no subsequent message, [io.ErrUnexpectedEOF] is returned.
|
||||
func (o UnmarshalOptions) UnmarshalFrom(r Reader, m proto.Message) error { |
||||
var sizeArr [binary.MaxVarintLen64]byte |
||||
sizeBuf := sizeArr[:0] |
||||
for i := range sizeArr { |
||||
b, err := r.ReadByte() |
||||
if err != nil { |
||||
// Immediate EOF is unexpected.
|
||||
if err == io.EOF && i != 0 { |
||||
break |
||||
} |
||||
return err |
||||
} |
||||
sizeBuf = append(sizeBuf, b) |
||||
if b < 0x80 { |
||||
break |
||||
} |
||||
} |
||||
size, n := protowire.ConsumeVarint(sizeBuf) |
||||
if n < 0 { |
||||
return protowire.ParseError(n) |
||||
} |
||||
|
||||
maxSize := o.MaxSize |
||||
if maxSize == 0 { |
||||
maxSize = defaultMaxSize |
||||
} |
||||
if maxSize != -1 && size > uint64(maxSize) { |
||||
return errors.Wrap(&SizeTooLargeError{Size: size, MaxSize: uint64(maxSize)}, "") |
||||
} |
||||
|
||||
var b []byte |
||||
var err error |
||||
if br, ok := r.(*bufio.Reader); ok { |
||||
// Use the []byte from the bufio.Reader instead of having to allocate one.
|
||||
// This reduces CPU usage and allocated bytes.
|
||||
b, err = br.Peek(int(size)) |
||||
if err == nil { |
||||
defer br.Discard(int(size)) |
||||
} else { |
||||
b = nil |
||||
} |
||||
} |
||||
if b == nil { |
||||
b = make([]byte, size) |
||||
_, err = io.ReadFull(r, b) |
||||
} |
||||
|
||||
if err == io.EOF { |
||||
return io.ErrUnexpectedEOF |
||||
} |
||||
if err != nil { |
||||
return err |
||||
} |
||||
if err := o.Unmarshal(b, m); err != nil { |
||||
return err |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
// UnmarshalFrom parses and consumes a varint size-delimited wire-format message
|
||||
// from r with the default options.
|
||||
// The provided message must be mutable (e.g., a non-nil pointer to a message).
|
||||
//
|
||||
// See the documentation for [UnmarshalOptions.UnmarshalFrom].
|
||||
func UnmarshalFrom(r Reader, m proto.Message) error { |
||||
return UnmarshalOptions{}.UnmarshalFrom(r, m) |
||||
} |
||||
Binary file not shown.
Loading…
Reference in new issue